AutoHotkey Webinar- Finding and Clicking Text / Pixels / Images

AutoHotkey Webinar Resources:

Video Hour 1: High-level overview

Video Hour 2: Q&A and deep-dive into question about Encoding & Decoding images in Base64 (to prevent having to share image files)

 

Announcements:

https://the-automator.com/ahk-podcasts/

  • 030-mp3VideoGender and Programming
  • 031-mp3VideoShould you let your colleagues/boss know you’re using AutoHotkey?
  • 032-mp3VideoSecurity and plain text files

Udemy Course: Intro to AutoHotkey: https://www.udemy.com/course/intro-to-autohotkey/?couponCode=AHK-WEBINAR 

Udemy Course: Text Expansion on a PC with AutoHotkey (HotStrings) :  https://www.udemy.com/course/hotstrings-autocorrect-text-expansion-with-autohotkey/?couponCode=AHK-WEBINAR

Script Highlight:

Updated version of iWB2 Learner tool which breaks-out Classname

iWB2_Classname.ahk    https://the-automator.com/iwb2_Classname.ahk

  • Added ClassName as a separate Edit field
  • Added Coloring of text on Frames (because they’re evil)
  • Fixed some GUI ugliness

 

 

 

 

General Approach to Automation

From our Webinar 3/21/17 on connecting to programs
  1. COM / Component Object Model
  2. UI Automation Interface
  3. Microsoft Active Accessibility (MSAA) / Acc viewer
  4. Controls, Send/Post Message, MenuItems, DLL calls
  5. Clipboard Manipulation
  6. Sending Keystrokes & MouseClicks

ImageSearch

Pros: Built into AutoHotkey

Cons:

  • Needs to have local image file
  • Can be quirky
  • No fuzzy matching
  • No Built-in ways to Click / Send Text
#SingleInstance,Force
;~ CoordMode Pixel  ; Interprets the coordinates below as relative to the screen rather than the active window.
 ;~ Supported Image filetypes are GIF, JPG, ICO, CUR, ANI and BMP images that are 16bit+
ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenHeight,  B:\Progs\AutoHotkey_L\Icons\Alpha\B.ico
if (ErrorLevel = 2)
  MsgBox % "Could not conduct the search.`n`nThe SOURCE image does not exist"
else if (ErrorLevel = 1)
  MsgBox % "The Image could not be found on the screen"
else {
  MsgBox % "The icon was found at: X:=" FoundX " Y:=" FoundY
  FoundX:=FoundX+15, FoundY:=FoundY+15  ;padding because it returns upper-left pixel location of image
  click %FoundX% , %FoundY% ;Click the location that was found
}

 

FindText by feiyue

Pros:

  • No local file needed
  • Finds multiple instances of pixels
  • Easy to create a simple search
  • Reliable & Fast
  • Maybe Fuzzy matching?

Cons:

  • Multiple GUIs
  • Complex
  • Not clear on features / training
  • No built-in ways to Click / Send Text
  • Not obvious how to find on multi-screens
  • Requires programming knowledge

FindnClick by Maestrith & Joe Glines

Pros:

  • No local Image needed
  • Fast to create a new script
  • Runs fast & is Reliable
  • Work off Index of found item
  • Built-in Click / Send text
  • Can Nest multiple Steps
  • Noob Friendly
  • Works on All screens
  • Wait for Window

Cons:

  • No fuzzy matching
  • A little complex to start

 

Encoding and Decoding an Image into Base64 by SKAN

In the second part of the webinar, Dimitri asked about being able to encode an image from a file into a string, then being able to view the image from the encoding.  After about a bunch of work we finally found a working solution from SKAN.

#SingleInstance,Force
Path:="C:\Users\Joe\Dropbox\Camera Uploads\5th bday\2011-11-28 12.13.24.jpg"
pBitmap := Gdip_CreateBitmapFromFile(Path)

Gdip_SaveBitmapToFile(pBitmap, "C:\AHK Studio\Projects\image2.jpg")

DllCall(NumGet(NumGet(pStream + 0, 0, "uptr") + (A_PtrSize * 2), 0, "uptr"), "ptr",pStream)
DllCall("GlobalFree", "ptr",hData)
ObjRelease(pStream)
Gdip_DisposeImage(pBitmap)
return


Encode(Text){
  cp:=0
  VarSetCapacity(rawdata,StrPut(text,"UTF-8"))
  sz:=StrPut(text,&rawdata,"UTF-8")-1
  DllCall("Crypt32.dll\CryptBinaryToString","ptr",&rawdata,"uint",sz,"uint",0x40000001,"ptr",0,"uint*",cp)
  VarSetCapacity(str,cp*(A_IsUnicode?2:1))
  DllCall("Crypt32.dll\CryptBinaryToString","ptr",&rawdata,"uint",sz,"uint",0x40000001,"str",str,"uint*",cp)
  return str
}

b64Encode( ByRef buf, bufLen:="" ) {
  bufLen := (bufLen) ? bufLen : StrLen(buf) << !!A_IsUnicode
  DllCall( "crypt32\CryptBinaryToStringA", "ptr", &buf, "UInt", bufLen, "Uint", 1 | 0x40000000, "Ptr", 0, "UInt*", outLen )
  VarSetCapacity( outBuf, outLen, 0 )
  DllCall( "crypt32\CryptBinaryToStringA", "ptr", &buf, "UInt", bufLen, "Uint", 1 | 0x40000000, "Ptr", &outBuf, "UInt*", outLen )
  return strget( &outBuf, outLen, "CP0" )
}

b64Decode( b64str, ByRef outBuf ) {
  static CryptStringToBinary := "crypt32\CryptStringToBinary" (A_IsUnicode ? "W" : "A")

  DllCall( CryptStringToBinary, "ptr", &b64str, "UInt", 0, "Uint", 1, "Ptr", 0, "UInt*", outLen, "ptr", 0, "ptr", 0 )
  VarSetCapacity( outBuf, outLen, 0 )
  DllCall( CryptStringToBinary, "ptr", &b64str, "UInt", 0, "Uint", 1, "Ptr", &outBuf, "UInt*", outLen, "ptr", 0, "ptr", 0 )

  return outLen
}


Gdip_EncodeBitmapTo64string(pBitmap, ext, Quality=75) {

         if Ext not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
               return -1
         Extension := "." Ext

         DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
         VarSetCapacity(ci, nSize)
         DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
         if !(nCount && nSize)
            return -2



            Loop, %nCount%
            {
                  sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
                  if !InStr(sString, "*" Extension)
                     continue

                  pCodec := &ci+idx
                  break
            }


         if !pCodec
               return -3

         if (Quality != 75)
         {
               Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
               if Extension in .JPG,.JPEG,.JPE,.JFIF
               {
                     DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
                     VarSetCapacity(EncoderParameters, nSize, 0)
                     DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
                     Loop, % NumGet(EncoderParameters, "UInt")
                     {
                        elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
                        if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
                        {
                              p := elem+&EncoderParameters-pad-4
                              NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
                              break
                        }
                     }
               }
         }

         DllCall("ole32\CreateStreamOnHGlobal", "ptr",0, "int",true, "ptr*",pStream)
         DllCall("gdiplus\GdipSaveImageToStream", "ptr",pBitmap, "ptr",pStream, "ptr",pCodec, "uint",p ? p : 0)

         DllCall("ole32\GetHGlobalFromStream", "ptr",pStream, "uint*",hData)
         pData := DllCall("GlobalLock", "ptr",hData, "uptr")
         nSize := DllCall("GlobalSize", "uint",pData)

         VarSetCapacity(Bin, nSize, 0)
         DllCall("RtlMoveMemory", "ptr",&Bin , "ptr",pData , "uint",nSize)
         DllCall("GlobalUnlock", "ptr",hData)
         DllCall(NumGet(NumGet(pStream + 0, 0, "uptr") + (A_PtrSize * 2), 0, "uptr"), "ptr",pStream)
         DllCall("GlobalFree", "ptr",hData)
         
         DllCall("Crypt32.dll\CryptBinaryToString", "ptr",&Bin, "uint",nSize, "uint",0x01, "ptr",0, "uint*",base64Length)
         VarSetCapacity(base64, base64Length*2, 0)
         DllCall("Crypt32.dll\CryptBinaryToString", "ptr",&Bin, "uint",nSize, "uint",0x01, "ptr",&base64, "uint*",base64Length)
         Bin := ""
         VarSetCapacity(Bin, 0)
         VarSetCapacity(base64, -1)

         return base64
}

 

 

Comments are closed.