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
- COM / Component Object Model
- UI Automation Interface
- Microsoft Active Accessibility (MSAA) / Acc viewer
- Controls, Send/Post Message, MenuItems, DLL calls
- Clipboard Manipulation
- 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 }