Table of Contents

GeekDude's Tips, Tricks, and Standalones

String Manipulation

Repeat a String.

Pad a string to a given length.

Remove extraneous delimiters when compiling a list in a loop WITHOUT using an if statement.

Check if a string starts with another string.

; Using InStr
if (InStr("Monkey Tacos", "Monkey") == 1)
 
; Using SubStr (if you know the length of the other string)
if (SubStr("Monkey Tacos", 1, 6) == "Monkey")
 
; Using Regular Expressions
if ("Monkey Tacos" ~= "^Monkey")

Objects

Use standard JSON format when defining your objects by placing the definition into a continuation section.

Toggles

Do a toggle with only one line.

DllCall

Lock your screen.

DllCall("LockWorkStation")

Output to a console window. Notes:

See also Print.ahk.

; By hand using FileAppend. FileOpen could also have been used.
DllCall("AllocConsole")
Loop, 10
	FileAppend, %A_Index%`n, CONOUT$
 
 
; As a function using FileOpen. FileAppend could also have been used.
Print(Text){
	static c := FileOpen("CONOUT$", ("rw", DllCall("AllocConsole")))
 
	; Reference __Handle to force AHK to flush the write buffer. Without it,
	; Without it, AHK will cache the write until later, such as when the
	; file is closed.
	c.Write(Text), c.__Handle
}

Run command line tools without having a command prompt pop up by attaching to a hidden command prompt.

; Launch a command promt and attach to it
DetectHiddenWindows, On
Run, cmd,, Hide, PID
WinWait, ahk_pid %PID%
DllCall("AttachConsole", "UInt", PID)
 
; Run another process that would normally
; make a command prompt pop up
RunWait, %ComSpec% /c ping localhost > %A_Temp%\PingOutput.txt
 
; Close the hidden command prompt process
Process, Close, %PID%
 
; Look at the output
FileRead, Output, %A_Temp%\PingOutput.txt
MsgBox, %Output%

Get the name of the process that last touched the clipboard.

OnClipboardChange:
DetectHiddenWindows, on
WinGet, name, ProcessName, % "ahk_id" DllCall("GetClipboardOwner")
ToolTip, %name%
return

Writing Libraries

When writing a library that has code which must be run before any of your functions can be used, you can create an initialization function that runs itself automatically when the script starts. This eliminates any need for the library's users to put your code into their auto-execute section.

If your library defines hotkeys, it can break other scripts that include it in their auto-execute section. You can avoid this by wrapping your hotkey definitions in if False.

Windows

Change the default script template by modifying C:\Windows\ShellNew\Template.ahk

Run, *RunAs notepad.exe C:\Windows\ShellNew\Template.ahk

Start your scripts on login by placing shortcuts (or the actual scripts) into the Startup folder.

FileCreateShortcut, %A_ScriptFullPath%, %A_Startup%\%A_ScriptName%.lnk

Threading

:!: WARNING :!:

These tricks DO NOT add real multithreading to AutoHotkey. They are bound by the limitations of AutoHotkey's green thread implementation and do not work around those restrictions in any way. If you would like to use real multithreading with AutoHotkey look into AutoHotkey_H or multiprogramming (multiple programs/scripts interacting with eachother).

:!: WARNING :!:

Create a new thread context using SetTimer with a small negative period.

One example of where this is useful is if you have a message handler from OnMessage that you have to do a lot of processing in, but that the result of doesn't actually change what you return to the sender of the message. By using SetTimer to schedule a new thread context to be created, you can be responsive and return immediately, then do your processing afterward.

; The trick on its own
SetTimer, Label, -0
 
 
; The trick in context
WM_LBUTTONDOWN(wParam, lParam, Msg, hWnd)
{
	; Return immediately then handle the click afterward
	SetTimer, HandleClick, -0
	return
}
 
HandleClick:
MsgBox, You clicked!
return

GUI

Create a menu bar for your GUI using a well formatted object instead of a long list of menu commands.

; Create a well-formatted object using one of the tricks
; from the objects section of this document
Menu :=
( LTrim Join Comments
[
	["&File", [
		["&New`tCtrl+N", "LabelNew"],
		["&Open`tCtrl+O", "LabelOpen"],
		["&Save`tCtrl+S", "LabelSave"],
		[],
		["E&xit`tCtrl+W", "GuiClose"]
	]], ["&Edit", [
		["Find`tCtrl+F", "LabelFind"],
		[],
		["Copy`tCtrl+C", "LabelCopy"],
		["Paste`tCtrl+V", "LabelPaste"]
	]], ["&Help", [
		["&About", Func("About").Bind(A_Now)]
	]]
]
)
 
MenuArray := CreateMenus(Menu)
Gui, Menu, % MenuArray[1]
Gui, Show, w640 h480
return
 
LabelNew:
LabelOpen:
LabelSave:
LabelFind:
LabelCopy:
LabelPaste:
return
 
GuiClose:
Gui, Destroy
 
; Release menu bar (Has to be done after Gui, Destroy)
for Index, MenuName in MenuArray
	Menu, %MenuName%, DeleteAll
 
ExitApp
return
 
About(Time)
{
	FormatTime, Time, %Time%
	MsgBox, This menu was created at %Time%
}
 
CreateMenus(Menu)
{
	static MenuName := 0
	Menus := ["Menu_" MenuName++]
	for each, Item in Menu
	{
		Ref := Item[2]
		if IsObject(Ref) && Ref._NewEnum()
		{
			SubMenus := CreateMenus(Ref)
			Menus.Push(SubMenus*), Ref := ":" SubMenus[1]
		}
		Menu, % Menus[1], Add, % Item[1], %Ref%
	}
	return Menus
}

Regular Expressions

Find, and optionally replace, all matches of regular expression efficiently using a custom enumerator.

Networking and Web

Download a file from the web and use its contents without having to save to a temporary file.

Address := "https://example.com/"
 
; Send a request for the resource we want using an HTTP Request object
Request := ComObjCreate("WinHttp.WinHttpRequest.5.1")
Request.Open("GET", Address)
Request.Send()
 
 
; If you want to get text data:
 
MsgBox, % Request.responseText
 
 
; If you want to get binary data:
 
; Get the data pointer and size. The pointer will be valid
; only as long as a reference to Request.responseBody is kept.
pData := NumGet(ComObjValue(Request.responseBody)+8+A_PtrSize, "UPtr")
Size := Request.responseBody.MaxIndex()+1
 
; Do something with the binary data
FileOpen("BinaryFile.png", "w").RawWrite(pData+0, Size)

Files and Folders

Read a file directly in an expression using FileOpen.

MsgBox, % FileOpen("C:\Windows\System32\drivers\etc\hosts", "r").Read()

Overwrite a file in one step using FileOpen.

Notes

Originally on GitHub Gist.