jeeswg's documentation extension tutorial

Helpful script writing tricks and HowTo's
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

jeeswg's documentation extension tutorial

25 Jun 2017, 02:43

[updated: 2019-12-01]

This is part of a set of beginner's tutorials:
- beginner tutorial [to come]
- strings tutorial
- mathematics tutorial [to come]
- documentation extension tutorial

The documentation extension is:
- tips on commands/functions separated by category
- things I would add to (or highlight) in the documentation

==================================================

LINKS:

[ list every function/command/directive/variable/control flow statement]
list of every command/function/variable from across all versions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=27321&p=131642#p131642

[chm to txt]
[C:\Program Files\AutoHotkey\AutoHotkey.chm to a txt file]
htm to txt, AutoHotkey Help (chm file) to txt - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=26402

[chm to separate htm files]
[C:\Program Files\AutoHotkey\AutoHotkey.chm to separate htm files]
E.g. use 7-Zip.

[command/function list and parameter count/types]
conversion logic, v1 = -> v1 := -> v2, two-way compatibility - Page 5 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=37&t=27069&p=140146#p140146

[command/function list and parameters]
list of every command/function/variable from across all versions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=27321&p=130479#p130479

[how to create an old-style version of the latest AutoHotkey.chm file]
Suggestions on documentation improvements - Page 20 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=13&t=1434&p=210683#p210683

==================================================

LINKS TO KEY DOCUMENTATION PAGES:

[commands/functions, control flow statements, directives]
Alphabetical Command and Function Index
https://autohotkey.com/docs/commands/
Alphabetical Function Index
https://lexikos.github.io/v2/docs/commands/index.htm

[built-in variables, operators]
Variables and Expressions
https://autohotkey.com/docs/Variables.htm
Variables and Expressions
https://lexikos.github.io/v2/docs/Variables.htm

[auto-execute section, command-line parameters, comments, continuation sections, escape sequences]
AutoHotkey Scripts and Macros
https://autohotkey.com/docs/Scripts.htm
AutoHotkey Scripts and Macros
https://lexikos.github.io/v2/docs/Scripts.htm

[clipboard]
Clipboard and ClipboardAll
https://autohotkey.com/docs/misc/Clipboard.htm#ClipboardAll
Clipboard and ClipboardAll
https://lexikos.github.io/v2/docs/misc/Clipboard.htm#ClipboardAll

[GUIs (AHK v1)]
GUI
https://autohotkey.com/docs/commands/Gui.htm
GUI Control Types
https://autohotkey.com/docs/commands/GuiControls.htm
GuiControl
https://autohotkey.com/docs/commands/GuiControl.htm
GuiControlGet
https://autohotkey.com/docs/commands/GuiControlGet.htm
ListView (GUI)
https://autohotkey.com/docs/commands/ListView.htm
TreeView (GUI)
https://autohotkey.com/docs/commands/TreeView.htm
Menu
https://autohotkey.com/docs/commands/Menu.htm

[GUIs (AHK v2)]
GuiCreate
https://lexikos.github.io/v2/docs/commands/GuiCreate.htm
GUI Object
https://lexikos.github.io/v2/docs/objects/Gui.htm
GuiControl Object
https://lexikos.github.io/v2/docs/objects/GuiControl.htm
GUI Control Types
https://lexikos.github.io/v2/docs/commands/GuiControls.htm
ListView (GUI)
https://lexikos.github.io/v2/docs/commands/ListView.htm
TreeView (GUI)
https://lexikos.github.io/v2/docs/commands/TreeView.htm
MenuCreate
https://lexikos.github.io/v2/docs/commands/MenuCreate.htm
MenuBarCreate
https://lexikos.github.io/v2/docs/commands/MenuBarCreate.htm
Menu/MenuBar Object
https://lexikos.github.io/v2/docs/objects/Menu.htm
OnCommand
https://lexikos.github.io/v2/docs/objects/GuiOnCommand.htm
OnEvent
https://lexikos.github.io/v2/docs/objects/GuiOnEvent.htm
OnMessage
https://lexikos.github.io/v2/docs/commands/OnMessage.htm
OnNotify
https://lexikos.github.io/v2/docs/objects/GuiOnNotify.htm

==================================================

CONTENTS:

>>>GUI: internal GUIs only
>>>GUI: internal/external GUIs, images
>>>GUI: notifications/dialogs
>>>interaction, files/folders, system
>>>objects
>>>strings/variables
>>>binary data
>>>dates
>>>Internet
>>>mathematics
>>>keyboard/mouse
>>>AutoHotkey control flow statements
>>>AutoHotkey main window menu items
>>>AutoHotkey modes/settings
>>>AutoHotkey itself (further commands/functions)
>>>(A_ variables)
>>>(commands)
>>>(updated functions)
>>>(limits)
>>>(AutoHotkey v2)

==================================================

>>>GUI: internal GUIs only
>>GuiXXX
>>IL_XXX
>>LV_XXX/SB_XXX/TV_XXX
>>MenuXXX

[WARNING] Gui: If the Gui command is present in a script, or a script that it includes, that script becomes #Persistent. It can only be closed via ExitApp or by the user. I.e. this prevents scripts with no hotkeys from closing.
[LIMIT] Gui: The Gui command does not support specifying a custom class name: it must be 'AutoHotkeyGUI', although this can be edited in the AutoHotkey exe file or live in the virtual memory. Note: dialogs and windows can be created via dll functions, with any chosen class name, but these windows cannot be handled by the Gui command.
[LIMIT] Gui: The Gui command does not support specifying a window with no icon.
[LIMIT] Gui: There are no built-in commands/functions for use with toolbar controls.
[NOTE] Gui: In AHK v1, when labels handle GUI events the following variables can be useful: A_EventInfo, A_GuiXXX, A_ThisLabel.

Code: Select all

q:: ;create a simple GUI:
Gui, +HwndhWnd
Gui, Show, w300 h300
WinGetTitle, vWinTitle, % "ahk_id " hWnd
MsgBox, % vWinTitle
return
==================================================

>>>GUI: internal/external GUIs, images
>>ControlXXX/StatusBarXXX
>>ImageSearch/LoadPicture/PixelGetColor/PixelSearch
>>MenuSelect
>>ProcessXXX
>>WinXXX/GroupXXX
>>(also: #IfWinActive)

[LIMIT] ProcessSetPriority: There is no 'ProcessGetPriority' function.
[LIMIT] ControlGetText: There is no support for external treeviews.
[LIMIT] StatusBarGetText/StatusBarWait: only work on a control of the form ClassNN 'msctls_statusbar321', i.e. not on a second or custom status bar.
[NOTE] WinGetTransColor/WinGetTransparent: unfortunately, it is not possible to make one colour partially transparent using these commands (there may or may not be alternative methods to achieve this).
[NOTE] #IfWinActive: For '#IfWinActive WinCriteria', where 'WinCriteria' is not blank, then 'hWnd := WinExist()' will contain the hWnd of the window that matched WinCriteria when the hotkey was triggered, the 'Last Found Window'.
[NOTE] ImageSearch: To perform an image search on image data in memory, e.g. from a file, rather than live on the screen, use the custom function: Gdip_ImageSearch.
[NOTE] ImageSearch: The ErrorLevel values for ImageSearch can be confusing, it is: '0=found,1=not found,2=problem' (it is *not*: '0=not found,1=found').
[NOTE] WinGet/ControlGet: To get the window/control under the cursor use MouseGetPos.
[NOTE] WinWait/WinWaitActive: If a matching window is found, you can use hWnd := WinExist() to retrieve its hWnd.
[NOTE] WinGetProcessName/WinGetProcessPath: The case of the name/path retrieved does not necessarily match the that of the exe. A_LoopFileLongPath can be used to correct the case of a path.

Code: Select all

;#IfWinActive and Last Found Window
#IfWinActive A ;matches any window (Last Found Window set)
q::
#IfWinActive ;matches any window (Last Found Window not set)
w::
hWnd := WinExist()
WinGetTitle, vWinTitle, % "ahk_id " hWnd
MsgBox, % vWinTitle
return
[Use the Acc library to get text from more control types:]
Acc library (MSAA) and AccViewer download links - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=26201

Code: Select all

;e.g. LoadPicture:
hBitmap := LoadPicture(A_AhkPath) ;without type parameter, bitmap
hIcon := LoadPicture(A_AhkPath, "", vType) ;with type parameter, depends on the source

;e.g. ImageSearch:
ImageSearch, vPosX, vPosY, 0, 0, % A_ScreenWidth, % A_ScreenHeight, % "*84 HICON:*" hIcon

Code: Select all

q:: ;list visible/hidden windows
DetectHiddenWindows, On
WinGet, vWinList, List
vOutput := ""
Loop % vWinList
{
	hWnd := vWinList%A_Index%
	WinGetTitle, vWinTitle, % "ahk_id " hWnd
	WinGetClass, vWinClass, % "ahk_id " hWnd
	WinGet, vPName, ProcessName, % "ahk_id " hWnd
	;WinGet, vPID, PID, % "ahk_id " hWnd
	vWinIsVisible := DllCall("user32\IsWindowVisible", "Ptr",hWnd) ;1 = visible, 0 = not visible
	vWinVisibility := vWinIsVisible ? "V" : "H"
	vOutput .= vWinVisibility "|" hWnd "|" vWinTitle "|" vWinClass "|" vPName "`r`n"
	;alternatively to list hidden windows only:
	;if !vWinIsVisible
	;	vOutput .= hWnd "|" vWinTitle "|" vWinClass "|" vPName "`r`n"
}
MsgBox, % Clipboard := vOutput
return

Code: Select all

;q:: ;get a windows's coordinates
WinGet, hWnd, ID, A
WinGetPos, vWinX, vWinY, vWinW, vWinH, % "ahk_id " hWnd
vCoords1 := "X" vWinX ",Y" vWinY ",W" vWinW ",H" vWinH " (R" vWinX+vWinW ",B" vWinY+vWinH ")"

VarSetCapacity(RECT, 16, 0)
DllCall("user32\GetClientRect", "Ptr",hWnd, "Ptr",&RECT)
DllCall("user32\ClientToScreen", "Ptr",hWnd, "Ptr",&RECT)
vWinX := NumGet(RECT, 0, "Int"), vWinY := NumGet(RECT, 4, "Int")
vWinW := NumGet(RECT, 8, "Int"), vWinH := NumGet(RECT, 12, "Int")
vCoords2 := "X" vWinX ",Y" vWinY ",W" vWinW ",H" vWinH " (R" vWinX+vWinW ",B" vWinY+vWinH ")"

vOutput := ""
. "window: " vCoords1 "`r`n"
. "window's client area: " vCoords2
MsgBox, % vOutput
return

Code: Select all

q:: ;get a control's coordinates
WinGet, hWnd, ID, A
vCtlClassNN := "Edit1"
;vCtlClassNN := "DirectUIHWND3"
;vCtlClassNN := "SHELLDLL_DefView1"
ControlGet, hCtl, Hwnd,, % vCtlClassNN, A

;relative to screen
WinGetPos, vCtlX, vCtlY, vCtlW, vCtlH, % "ahk_id " hCtl
vCoords1 := "X" vCtlX ",Y" vCtlY ",W" vCtlW ",H" vCtlH " (R" vCtlX+vCtlW ",B" vCtlY+vCtlH ")"

;relative to window (specify ClassNN and hWnd)
ControlGetPos, vCtlX, vCtlY, vCtlW, vCtlH, % vCtlClassNN, A
vCoords2 := "X" vCtlX ",Y" vCtlY ",W" vCtlW ",H" vCtlH " (R" vCtlX+vCtlW ",B" vCtlY+vCtlH ")"

;relative to window (specify hCtl)
ControlGetPos, vCtlX, vCtlY, vCtlW, vCtlH,, % "ahk_id " hCtl
vCoords2X := "X" vCtlX ",Y" vCtlY ",W" vCtlW ",H" vCtlH " (R" vCtlX+vCtlW ",B" vCtlY+vCtlH ")"

;relative to window's client area
VarSetCapacity(RECT, 16, 0)
DllCall("user32\GetWindowRect", "Ptr",hCtl, "Ptr",&RECT)
DllCall("user32\MapWindowPoints", "Ptr",0, "Ptr",hWnd, "Ptr",&RECT, "UInt",2)
vCtlX := NumGet(RECT, 0, "Int"), vCtlY := NumGet(RECT, 4, "Int")
vCtlW := NumGet(RECT, 8, "Int")-vCtlX, vCtlH := NumGet(RECT, 12, "Int")-vCtlY
vCoords3 := "X" vCtlX ",Y" vCtlY ",W" vCtlW ",H" vCtlH " (R" vCtlX+vCtlW ",B" vCtlY+vCtlH ")"

vOutput := ""
. "relative to screen: " vCoords1 "`r`n"
. "relative to window: " vCoords2 "`r`n"
. "relative to window: " vCoords2X "`r`n"
. "relative to window's client area: " vCoords3
MsgBox, % vOutput
return
[e.g. repeated ImageSearch/PixelSearch:]
[repeated ImageSearch][ImageSearch: click image every time it's found]
My first project: How hard/easy it is to develop a script for this? - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=28023
[repeated PixelSearch][PixelSearch: click pixel every time it's found]
after 4 hours i decided i should get help lol - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=28516

For the full list of ahk_class/ahk_id/ahk_pid/ahk_exe/ahk_group see:
WinTitle & Last Found Window
https://autohotkey.com/docs/misc/WinTitle.htm

colour names and RGB values (color names):
Progress/SplashImage
https://autohotkey.com/docs/commands/Progress.htm
Black=000000
Silver=C0C0C0
Gray=808080
White=FFFFFF
Maroon=800000
Red=FF0000
Purple=800080
Fuchsia=FF00FF
Green=008000
Lime=00FF00
Olive=808000
Yellow=FFFF00
Navy=000080
Blue=0000FF
Teal=008080
Aqua=00FFFF

==================================================

>>>GUI: notifications/dialogs
>>FileSelect/DirSelect (previously: FileSelectFile/FileSelectFolder)
>>Exception
>>MsgBox/InputBox/ToolTip/TrayTip
>>(also previously: Progress/SplashImage/SplashTextOn)

[BACKGROUND] FileSelect: uses the Common File Dialog (pre-Windows Vista), and the Common Item Dialog (post-Windows Vista).
[LIMIT] FileSelect: has a different appearance depending on the operating system, you cannot choose the old style on a newer operating system.
[BACKGROUND] MsgBox: is based on the MessageBox dll function.
[BACKGROUND] InputBox: is based on the DialogBox dll function and a dialog resource inside the AutoHotkey exe (which can be inspected using Resource Hacker).
[LIMIT] MsgBox/InputBox: You cannot specify the font for MsgBox/InputBox commands. (The 'Font' parameter for InputBox is not implemented.)
[LIMIT] MsgBox: can cause a beep.
[NOTE] MsgBox: in AHK v2, the Text parameter has two defaults, 'Press OK to continue.', for MsgBox(), and a blank string otherwise, e.g. MsgBox(,, "").


==================================================

>>>interaction, files/folders, system
>>ClipWait (also: Clipboard variable)
>>DllCall/PostMessage/SendMessage
>>SoundXXX/DriveXXX/SysGet/MonitorXXX (also: SoundBeep, SoundPlay)
>>FileXXX/DirXXX
>>IniXXX
>>RegXXX
>>RunXXX/Shutdown
>>(also: A_OSVersion, A_AppData)

[LIMIT] FileRead: does not support UTF-16 BE ('Unicode big endian' on Notepad), use LCMapStringW (DllCall).
[LIMIT] FileGetTime/FileSetTime: do not handle milliseconds, and only handle local time, not UTC time.
[LIMIT] FileAppend/FileCopy/FileMove: only work if the specified directory already exists.
[LIMIT] FileRead: use *c to read the contents of a binary file, unfortunately you cannot do *c4 for example, to read the first 4 bytes. [Fixed in AHK v2.]
[WARNING] FileRead/FileAppend: do not support all of the encodings listed at: Code Page Identifiers (Windows) http://msdn.microsoft.com/en-us/library/dd317756.aspx
[WARNING] FileAppend: uses 'End of line (EOL) translation' by default, (it replaces lone LFs with CRLFs), use * to prevent this.
[LIMIT] FileGetShortcut: cannot retrieve a lnk file's shortcut key. Although FileGetShortcut can specify a shortcut key.
[BACKGROUND] PostMessage/SendMessage: AHK has PostMessage/SendMessage commands, but PostMessage and SendMessage are also dll functions, and can be used with DllCall.
[NOTE] PostMessage/SendMessage: both send a message to a window/control, however, the SendMessage command waits until it receives a reply before moving on to the next line.
[WARNING] IniRead: 'To store a blank value (empty string), specify %A_Space%'.
[LIMIT] IniRead/IniWrite: use GetPrivateProfileString and WritePrivateProfileString which don't support UTF-8, although you could create an ANSI ini file, and convert the bytes to UTF-8 when reading/writing.
[NOTE] IniWrite: if the ini file does not already exist, it will create a UTF-16 LE/ANSI ini file depending on whether the AHK version is Unicode/ANSI.
[NOTE] IniRead/IniWrite: cannot handle all characters in a key name e.g. these 3: [=;
[LIMIT] RegWrite: There is no 'RegCreateKey' function to create empty registry keys (cf. RegWrite which creates registry values).
[NOTE] SoundBeep: can only play one sound at a time, even if you open multiple scripts.
[NOTE] Run: To keep a ComSpec window open after the task completes use switch: '/K'.
[LIMIT] A_AppData: There is no 'A_Recent' variable, for the Recent Items folder.
[NOTE] A_AppData: %A_AppData% is C:\Users\%A_UserName%\AppData\Roaming (%A_AppData% is not C:\Users\%A_UserName%\AppData) (e.g. on Windows 7).
[NOTE] A_OSVersion gives a friendly name in AHK v1, but gives a version number in AHK v2

value types, same order as they appear in Registry Editor (Windows 7):
[REG_SZ,REG_BINARY,REG_DWORD,REG_QWORD,REG_MULTI_SZ,REG_EXPAND_SZ]
REG_SZ String Value
REG_BINARY Binary Value
REG_DWORD DWORD (32-bit) Value
REG_QWORD QWORD (64-bit) Value
REG_MULTI_SZ Multi-String Value
REG_EXPAND_SZ Expandable String Value

root keys, same order as they appear in Registry Editor (Windows 7):
[HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USERS,HKEY_CURRENT_CONFIG]
[HKCR,HKCU,HKLM,HKU,HKCC]
HKCR HKEY_CLASSES_ROOT
HKCU HKEY_CURRENT_USER
HKLM HKEY_LOCAL_MACHINE
HKU HKEY_USERS
HKCC HKEY_CURRENT_CONFIG

Code: Select all

q:: ;FileAppend/FileRead UTF-16 BE (in AHK Unicode versions)
;append
vLE := Chr(8730) ;square root sign
vLE := Chr(65279) vLE ;prepend BOM
vChars := StrLen(vLE)
VarSetCapacity(vBE, vChars*2)
DllCall("kernel32\LCMapStringW", "UInt",0, "UInt",0x800, "WStr",vLE, "Int",vChars, "WStr",vBE, "Int",vChars)
vPath := A_Desktop "\z " A_Now ".txt"
FileAppend, % vBE, % "*" vPath, UTF-16-RAW

;read
FileRead, vBE, % "*P1200 " vPath ;read as UTF-16 LE
FileGetSize, vSize, % vPath
vChars := Floor(vSize/2)
VarSetCapacity(vLE, vChars*2)
;LCMAP_BYTEREV := 0x800
DllCall("kernel32\LCMapStringW", "UInt",0, "UInt",0x800, "WStr",vBE, "Int",vChars, "WStr",vLE, "Int",vChars)
if (SubStr(vLE, 1, 1) = Chr(65279))
	vLE := SubStr(vLE, 2)
MsgBox, % vLE
return

Code: Select all

q:: ;convert Unicode text to ANSI (lossy) (best-fit characters on/off)
vText := Chr(8730) ;square root sign

;FileAppend (ANSI) and FileRead (best-fit characters on)
vPath := A_Desktop "\z " A_Now ".txt"
FileAppend, % vText, % "*" vPath, CP1252
FileRead, vTextNew, % vPath
MsgBox, % vTextNew ;v (best-fit character for square root sign)

;StrGet (best-fit characters off)
VarSetCapacity(vTemp, StrPut(vText, "CP0")*2)
StrPut(vText, &vTemp, "CP0")
vTextNew := StrGet(&vTemp, "CP0")
MsgBox, % vTextNew ;?

;DllCall (best-fit characters on/off)
Loop 2
{
	vBFC := (A_Index = 1)
	;WC_NO_BEST_FIT_CHARS := 0x400
	vFlags := vBFC ? 0 : 0x400

	;UTF-16 LE to ANSI
	vChars := StrLen(vText)+1
	VarSetCapacity(vTemp, vChars, 0)
 	DllCall("kernel32\WideCharToMultiByte", "UInt",0, "UInt",vFlags, "Ptr",&vText, "Int",vChars, "Ptr",&vTemp, "Int",vChars, "Ptr",0, "Ptr",0)

	;ANSI to UTF-16 LE
	VarSetCapacity(vTextNew, vChars*2, 0)
 	DllCall("kernel32\MultiByteToWideChar", "UInt",0, "UInt",0, "Ptr",&vTemp, "Int",vChars, "WStr",vTextNew, "Int",vChars)
	MsgBox, % vTextNew
}
return

Code: Select all

q:: ;FileAppend/FileRead (different encodings)
vText := "hello world " Chr(8730) ;square root sign
vList := "CP1252,UTF-8,UTF-8-RAW,UTF-16,UTF-16-RAW"
Loop Parse, vList, % ","
{
	vPath := A_Desktop "\z enc " A_LoopField ".txt"
	if !FileExist(vPath)
		FileAppend, % vText, % "*" vPath, % A_LoopField
}

;FileRead force opens a file with a UTF-8/UTF-16 BOM as UTF-8/UTF-16
vOutput := ""
Loop Parse, vList, % ","
{
	vPath := A_Desktop "\z enc " A_LoopField ".txt"
	FileRead, vText1, % "*P1252 " vPath ;read as ANSI (CP-1252)
	FileRead, vText2, % "*P65001 " vPath ;read as UTF-8
	FileRead, vText3, % "*P1200 " vPath ;read as UTF-16 LE
	vOutput .= "- " A_LoopField "`r`n" vText1 "`r`n" vText2 "`r`n" vText3 "`r`n"
}
MsgBox, % vOutput

;FileRead alternative, ignore BOM
vOutput := ""
Loop Parse, vList, % ","
{
	vPath := A_Desktop "\z enc " A_LoopField ".txt"
	FileGetSize, vSize, % vPath
	FileRead, vText, % "*c " vPath
	vText1 := StrGet(&vText, "CP1252")
	vText2 := StrGet(&vText, "UTF-8")
	vText3 := StrGet(&vText, "UTF-16")
	vOutput .= "- " A_LoopField "`r`n" vText1 "`r`n" vText2 "`r`n" vText3 "`r`n"
}
MsgBox, % vOutput
return

Code: Select all

q:: ;identify the encoding of a txt file
vPath := A_ScriptFullPath
vEnc := ""
if (oFile := FileOpen(vPath, "r"))
{
	vEnc := oFile.Encoding
	if !(SubStr(vEnc, 1, 3) = "UTF") ;e.g. CP1252/UTF-8/UTF-16
	{
		if (oFile.ReadUShort() = 65534) ;0xFFFE
			vEnc := "UTF-16 BE"
		else
			vEnc := "ANSI"
	}
	oFile.Close()
}
MsgBox, % vEnc "`r`n" vPath
return

Code: Select all

q:: ;get Windows version number (e.g. Windows 7: 6.1.7601)
vVersion := DllCall("kernel32\GetVersion", "UInt")
MsgBox, % Format("{}.{}.{:04}", vVersion & 0xFF, (vVersion >> 8) & 0xFF, (vVersion >> 16) & 0xFFFF)
return

Code: Select all

;get the output from a console application
MsgBox, % JEE_RunGetStdOut(ComSpec " /c set")
return

JEE_RunGetStdOut(vTarget, vSize:="")
{
	DetectHiddenWindows, On
	vComSpec := A_ComSpec ? A_ComSpec : ComSpec
	Run, % vComSpec,, Hide, vPID
	WinWait, % "ahk_pid " vPID
	DllCall("kernel32\AttachConsole", "UInt",vPID)
	oShell := ComObjCreate("WScript.Shell")
	oExec := oShell.Exec(vTarget)
	vStdOut := ""
	if !(vSize = "")
		VarSetCapacity(vStdOut, vSize)
	while !oExec.StdOut.AtEndOfStream
		vStdOut := oExec.StdOut.ReadAll()
	DllCall("kernel32\FreeConsole")
	Process, Close, % vPID
	return vStdOut
}
==================================================

>>>objects
>>Array/Object
>>ComObjXXX
>>IsObject
>>ObjXXX
>>Type

[NOTE] ObjAddRef/ObjRelease: Be careful with ObjAddRef and ObjRelease, and consider deleting objects when not needed e.g. oMyObj := "".
[LIMIT] Object: AHK objects do not have a Count method as standard.
[NOTE] Object: A key can have a value or child keys, but not both.
[LIMIT] Array: when defining an object via [] or Array(), it can have at most 255 keys (more keys can be added later) (StrSplit could be used instead)
[LIMIT] Object: when defining an object via {} or Object(), it can have at most 127 keys (more keys can be added later)

Code: Select all

;all 4 are equivalent:
oMyArray := Array(), oMyArray := []
oMyObj := Object(), oMyArray := {}

Code: Select all

;workarounds to get the object count:

ObjCount1(oObj)
{
	vCount := 0
	for vKey, vValue in oObj
		vCount++
	return vCount
}

;note: not guaranteed to work in future
ObjCount2(oObj)
{
	return NumGet(&oObj + 4*A_PtrSize)
}

Code: Select all

q:: ;increment via ++ doesn't work in the same way for object keys as variables, when applied to blank strings
var := 0
obj := {}, obj.a := 0
var++
obj.a++
MsgBox, % var ;1
MsgBox, % obj.a ;1

var := ""
obj := {}, obj.a := ""
var++
obj.a++
MsgBox, % var ;1
MsgBox, % obj.a ;(blank)
return

Code: Select all

q:: ;example of looping through an array
;this creates keys: '1,2,3,4' with values 'a,b,c,d' respectively
oArray := ["a","b","c","d"]

;now oArray[3] points to an object, instead of a string
;when it's value is requested, it will return blank
oArray.3 := ["e","f","g","h"]

vOutput := ""
for vKey, vValue in oArray
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

vOutput := ""
for vKey, vValue in oArray.3
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput
return
==================================================

>>>strings/variables
>>Chr/Ord (previously: Asc)
>>Deref
>>InStr/StrReplace
>>RegExMatch/RegExReplace
>>Sort
>>StrGet/StrPut
>>StringXXX
>>StrLen
>>StrLower/StrUpper
>>StrSplit/SplitPath
>>SubStr
>>Trim/LTrim/RTrim
>>(also: A_IsUnicode, if var in/contains list, if var is type)

[LIMIT] RegExMatch: In AHK Unicode, RegExMatch can only handle 2-byte pairs at 2-byte intervals, so is limited when handling ANSI/UTF-8/binary searches.
[NOTE] RegExMatch/RegExReplace: can be slow compared to other methods, e.g. sometimes using StrReplace multiple times can be faster than using RegExReplace.
[NOTE] RegExMatch/RegExReplace: 'Options)' is AHK-specific and is not a standard part of RegEx, although these options can usually be applied via standard RegEx instead.
[NOTE] RegExMatch/RegExReplace: There are some RegEx techniques that can be used that aren't in the AHK documentation, see: 'PCRE REGULAR EXPRESSION SYNTAX SUMMARY', at: pcresyntax specification http://www.pcre.org/original/doc/html/pcresyntax.html
[LIMIT] StrReplace: does not have a case sensitive parameter (cf. InStr). Use StringCaseSense to set the case sensitive/insensitive mode, or use RegExReplace to do a case sensitive/insensitive text replace.
[WARNING] Sort: uses unstable sort: e.g. if two items are regarded as identical e.g. 'A' and 'a' in a case-insensitive sort, the items may be swapped (the relative positions are not maintained). In a stable sort, identical items remain in their original order.
[WARNING (AHK V2)] InStr/SubStr/RegExMatch/RegExReplace: handle negative offsets differently.
[WARNING] Chr/Asc/Ord: differ in the range 128-255 depending on whether the AHK version is Unicode/ANSI.
[NOTE] StringXXX: StringXXX commands are generally deprecated, although StringCaseSense and StringLower/StringUpper are not deprecated.
[WARNING] A_IsUnicode: A_IsUnicode's value is 1 or blank (not 1 or 0).
[WARNING] if var is [not] type: a blank string returns a positive result for some types e.g. it is considered as alphanumeric/alpha.
[WARNING] If you do Trim(var, "abc"), that is a list of individual characters to trim, e.g. Trim(var, "`r`n") will trim any CRs or LFs, not just consecutive blocks of CRLFs.

for 'if var between/contains/in/is'
the position of the word 'not' is inconsistent:
if var [not] between low and high
if var [not] contains list
if var [not] in list
if var is [not] type

Code: Select all

;e.g. SubStr get last n characters:
SubStr(vText, 1-n) ;AHK v1
SubStr(vText, -n) ;AHK v2
vIsV1 := !!SubStr(1,0)
SubStr(vText, vIsV1-n) ;two-way compatible

Code: Select all

;callouts retrieve every possible matching pattern
q:: ;RegEx - use a custom callout function to understand what RegExMatch/RegExReplace is doing
RegExMatch("abc", ".*", vMatch)
MsgBox, % vMatch

vOutput := ""
RegExMatch("abc", ".*(?CMyCallout)")
MsgBox, % SubStr(vOutput, 1, -1) ;abc,ab,a,,

MsgBox, % RegExReplace("abc", ".*", "")

vOutput := ""
RegExReplace("abc", ".*(?CMyCallout)")
MsgBox, % SubStr(vOutput, 1, -1) ;abc,ab,a,,
return

MyCallout(vMatch)
{
	global vOutput
	vOutput .= vMatch ","
	return 1
}

Code: Select all

q:: ;for each 'if var is type', does blank return positive
;note: 'number', not 'numeric'
vList := "integer,float,number,digit,xdigit,alpha,upper,lower,alnum,space,time"
vText := ""

Loop Parse, vList, % ","
{
	vType := A_LoopField
	if vText is %vType%
		vOutput .= "y`t" vType "`r`n"
	else
		vOutput .= "n`t" vType "`r`n"
}
MsgBox, % Clipboard := vOutput
return

;blank yields positive:
;digit,xdigit,alpha,upper,lower,alnum,space

;blank yields negative:
;integer,float,number,time

Code: Select all

q:: ;for each 'if var is type', how many characters return positive
;note: 'number', not 'numeric'
vList := "integer,float,number,digit,xdigit,alpha,upper,lower,alnum,space,time"

vOutput := ""
VarSetCapacity(vOutput, 10000*2)
Loop Parse, vList, % ","
{
	vType := A_LoopField
	vCount := 0
	vChars := ""
	VarSetCapacity(vChars, 10000*2)
	Loop 65535
	{
		vChar := Chr(A_Index)
		if vChar is %vType%
			vCount++, vChars .= vChar
	}
	vOutput .= vCount "`t" vType "`t" vChars "`r`n"
}
MsgBox, % Clipboard := vOutput
return

;10	integer
;0	float
;10	number
;3328	digit
;5632	xdigit
;52	alpha
;26	upper
;26	lower
;62	alnum
;25	space
;0	time

Code: Select all

;understanding custom sort functions:

;if want a1 to be earlier in the new list return a negative number
;if want a2 to be earlier in the new list return a positive number
;if want a1 to be later in the new list return a positive number
;if want a2 to be later in the new list return a negative number
;if offset is negative, a2 was earlier in the original list
;if offset is positive, a1 was earlier in the original list

;to reverse order: return offset
;to maintain order: return -offset

;example from the documentation
MyVar = 1,2,3,4
Sort, MyVar, F ReverseDirection D,  ; Reverses the list so that it contains 4,3,2,1
ReverseDirection(a1, a2, offset)
{
    return offset  ; Offset is positive if a2 came after a1 in the original list; negative otherwise.
}

Code: Select all

;unstable v. stable sort:

;example from the documentation (unstable sort)
MyVar = def`nabc`nmno`nFGH`nco-op`ncoop`ncop`ncon`n
Sort, MyVar, F StringSort
StringSort(a1, a2)
{
    return a1 > a2 ? 1 : a1 < a2 ? -1 : 0  ; Sorts alphabetically based on the setting of StringCaseSense.
}

;example from the documentation (edited) (stable sort)
MyVar = def`nabc`nmno`nFGH`nco-op`ncoop`ncop`ncon`n
Sort, MyVar, F StringSort
StringSortStable(a1, a2, offset)
{
    return a1 > a2 ? 1 : a1 < a2 ? -1 : -offset  ; Sorts alphabetically based on the setting of StringCaseSense.
}
==================================================

>>>binary data
>>NumGet/NumPut
>>VarSetCapacity
>>(also: StrGet/StrPut)

[LIMIT] NumGet/NumPut: There is no recommended example function for moving memory, use RtlMoveMemory (DllCall).
[WARNING] NumGet/NumPut: For NumGet/NumPut the default parameter used to be UInt, it is now UPtr.
[NOTE] NumGet/NumPut: Read/write numbers in little endian form, e.g. 0x01020304 gets written as 0x04030201.

Code: Select all

q:: ;move memory
vData1 := "ABCDE"
vData2 := "abcde"
vSize := 4
;note: RtlMoveMemory parameter order is: 'dest, source' [NOT 'source, destination']
DllCall("kernel32\RtlMoveMemory", "Ptr",&vData2, "Ptr",&vData1, "UPtr",vSize)
MsgBox, % vData2
return

Code: Select all

JEE_HexToBinData(vHex, ByRef vSize:="")
{
	vChars := StrLen(vHex)
	;CRYPT_STRING_HEX := 0x4
	;CRYPT_STRING_HEXRAW := 0xC ;(not supported by Windows XP)
	DllCall("crypt32\CryptStringToBinary", "Ptr",&vHex, "UInt",vChars, "UInt",0x4, "Ptr",0, "UInt*",vSize, "Ptr",0, "Ptr",0)
	VarSetCapacity(vData, vSize, 0)
	DllCall("crypt32\CryptStringToBinary", "Ptr",&vHex, "UInt",vChars, "UInt",0x4, "Ptr",&vData, "UInt*",vSize, "Ptr",0, "Ptr",0)
	return &vData
}

;==================================================

JEE_BinDataToHex(vAddr, vSize)
{
	;CRYPT_STRING_HEX := 0x4 ;to return space/CRLF-separated text
	;CRYPT_STRING_HEXRAW := 0xC ;to return raw hex (not supported by Windows XP)
	DllCall("crypt32\CryptBinaryToString", "Ptr",vAddr, "UInt",vSize, "UInt",0x4, "Ptr",0, "UInt*",vChars)
	VarSetCapacity(vHex, vChars*2, 0)
	DllCall("crypt32\CryptBinaryToString", "Ptr",vAddr, "UInt",vSize, "UInt",0x4, "Str",vHex, "UInt*",vChars)
	vHex := StrReplace(vHex, "`r`n")
	vHex := StrReplace(vHex, " ")
	return vHex
}

;==================================================

JEE_BinDataToHex2(vAddr, vSize)
{
	;CRYPT_STRING_HEXRAW := 0xC ;to return raw hex (not supported by Windows XP)
	DllCall("crypt32\CryptBinaryToString", "Ptr",vAddr, "UInt",vSize, "UInt",0xC, "Ptr",0, "UInt*",vChars)
	VarSetCapacity(vHex, vChars*2, 0)
	DllCall("crypt32\CryptBinaryToString", "Ptr",vAddr, "UInt",vSize, "UInt",0xC, "Str",vHex, "UInt*",vChars)
	return vHex
}
==================================================

>>>dates
>>DateAdd/DateDiff
>>FormatTime
>>(also: A_Now, A_NowUTC, A_MSec, A_TickCount)

[WARNING] FormatTime:

Code: Select all

FormatTime, vWDay, % vDate, WDay
gives 2 even when the date is invalid.
[NOTE] A_Now: The A_Now variable is of the form 'yyyyMMddHHmmss'.
[NOTE] DateAdd: add (or *subtract*) an amount of time from a date.
[NOTE] DateDiff: get the amount of time between 2 dates.
[NOTE] DateDiff: rounds down.

The Winapi uses 2 main time structures:
FILETIME, intervals since 01/01/1601, 1 interval = 100 nanoseconds = 0.1 microseconds. 1 second = 10000000 intervals. 1 millisecond = 10000 intervals.
SYSTEMTIME, 'friendly', Y/M/WDay/D/H/M/S/MS
GetLocalTime (local time as SYSTEMTIME)
GetSystemTime (UTC time as SYSTEMTIME)
(no handy function?) (local time as FILETIME)
GetSystemTimeAsFileTime (UTC time as FILETIME)
Time Functions (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx

Code: Select all

q:: ;'vDate := A_Now A_MSec' is unreliable (as are any combination of individual AHK date/time variables e.g. A_YYYY, A_Sec)
vOutput := ""
vCount := 0
vCount2 := 0
Loop
{
	if (vCount = 3) || (vCount2 = 1000)
		break
	vDate := A_Now " " A_MSec
	vPfx := (vDate < vDate2) ? ("x", vCount++) : ""
	if (vDate = vDate2)
		continue
	vOutput .= vPfx "`t" vDate "`r`n"
	vDate2 := vDate
	vCount2++
}
MsgBox, % "errors: " vCount
MsgBox, % Clipboard := vOutput
return

;==================================================

w:: ;'vDate := A_Now A_MSec' is unreliable (as are any combination of individual AHK date/time variables e.g. A_YYYY, A_Sec)
;in this example, A_MSec is retrieved before A_Now is
vOutput := ""
vCount := 0
vCount2 := 0
Loop
{
	if (vCount = 3) || (vCount2 = 1000)
		break
	vMSec := A_MSec
	vDate := A_Now " " vMSec
	vPfx := (vDate < vDate2) ? ("x", vCount++) : ""
	if (vDate = vDate2)
		continue
	vOutput .= vPfx "`t" vDate "`r`n"
	vDate2 := vDate
	vCount2++
}
MsgBox, % "errors: " vCount
MsgBox, % Clipboard := vOutput
return

Code: Select all

q:: ;reliable alternative to 'vDate := A_Now A_MSec'
vIntervalsUTC := 0
DllCall("kernel32\GetSystemTimeAsFileTime", "Int64*",vIntervalsUTC)
vDateUTC := 1601
EnvAdd, vDateUTC, % Floor(vIntervalsUTC/10000000), Seconds
vMSec := Mod(Floor(vIntervalsUTC/10000), 1000)

vIntervalsLocal := 0
;DllCall("kernel32\GetSystemTimeAsFileTime", Int64P,vIntervalsUTC)
DllCall("kernel32\FileTimeToLocalFileTime", "Int64*",vIntervalsUTC, "Int64*",vIntervalsLocal)
vDateLocal := 1601
EnvAdd, vDateLocal, % Floor(vIntervalsLocal/10000000), Seconds
vMSec := Mod(Floor(vIntervalsLocal/10000), 1000)

MsgBox, % vDateUTC " " vMSec "`r`n" vDateLocal " " vMSec "`r`n`r`n" A_NowUTC " " A_MSec "`r`n" A_Now " " A_MSec
return

Code: Select all

q:: ;DateDiff rounds down
MsgBox, % DateDiff(19990101, 19990101, "D") ;0
MsgBox, % DateDiff(1999010103, 19990101, "D") ;0
MsgBox, % DateDiff(1999010121, 19990101, "D") ;0
MsgBox, % DateDiff(19990102, 19990101, "D") ;1

MsgBox, % DateDiff(19990101, 19990101, "H") ;0
MsgBox, % DateDiff(199901010003, 19990101, "H") ;0
MsgBox, % DateDiff(199901010057, 19990101, "H") ;0
MsgBox, % DateDiff(1999010101, 19990101, "H") ;1
return

Code: Select all

q:: ;get weekday and month in English
;note: AutoHotkey uses 1-7 for Sun-Mon (not 0-6)
oMonth := StrSplit("January,February,March,April,May,June,July,August,September,October,November,December", ",")
oMonth3 := StrSplit("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", ",")
oDay := StrSplit("Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", ",")
oDay3 := StrSplit("Sun,Mon,Tue,Wed,Thu,Fri,Sat", ",")

MsgBox, % oMonth[A_MM] "`r`n" oMonth3[A_MM]
MsgBox, % oDay[A_WDay] "`r`n" oDay3[A_WDay]

vDate := A_Now
FormatTime, vWDay, % vDate, WDay
FormatTime, vMM, % vDate, MM
FormatTime, vDate, % vDate, % "'" oDay3[vWDay] "' dd '" oMonth3[vMM] "' yyyy HH:mm:ss"
MsgBox, % vDate
return
==================================================

>>>Internet
>>Download (previously: UrlDownloadToFile)

>>>mathematics
>>Abs
>>ASin/ACos/ATan
>>Ceil/Round/Floor
>>Exp/Ln/Log
>>Format
>>Max/Min
>>Mod
>>Random/RandomSeed
>>Sin/Cos/Tan
>>Sqrt

[WARNING] Mod: In theory the Mod function could be used to truncate a number to n decimal places, however it uses a curious definition of Mod.
[NOTE] Mod: If the dividend is negative, the output is negative.
[NOTE] Random: To return a random integer, both range values should be integers, otherwise at least one range value should have a decimal point.

Mod function returning wrong value? - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=14&t=29762

Code: Select all

q:: ;Dec2Hex and Hex2Dec
;e.g. Dec2Hex:
vNum := 255
MsgBox, % vHex := Format("{:X}", 255) ;FF
MsgBox, % vHex := Format("0x{:X}", 255) ;0xFF

;e.g. Hex2Dec
vHex := 0xFF
MsgBox, % vNum := vHex + 0 ;255

vHex := "FF"
vHex := "0x" vHex
MsgBox, % vNum := vHex + 0 ;255

vHex := "FF"
MsgBox, % vHex := Format("{:i}", "0x" vHex) ;255
return
See 'FORMAT FUNCTION EXAMPLES' at:
jeeswg's characters tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=26486

==================================================

>>>keyboard/mouse
>>BlockInput/SendXXX (also: ControlClick, ControlSend)
>>Click/MouseXXX (also: A_CaretX/A_CaretY, A_Cursor)
>>GetKeyXXX/Hotkey/Input/KeyWait
>>(also: CoordMode, A_CoordModeXXX, SetXXX)

[WARNING] A_CaretX/A_CaretY: don't work correctly when multiple characters are selected.
[LIMIT] Hotkey: Not all hotkeys can be defined: Fn key, reserved Windows hotkeys, three-key hotkeys, not every key can act as a modifier key. LAlt can cause issues e.g. with menu bars.
[LIMIT] Hotkey: There is no 'Hotstring' command to create hotstrings dynamically (cf. Hotkey command).
[LIMIT] Hotkey: Not all hotstrings containing a colon (in the abbreviation/output) are possible.
[NOTE] Hotkey: A semicolon hotkey: '`;::' or 'SC027::', a ctrl+semicolon hotkey: '^;::' or '^SC027::'.
[NOTE] Click: Click's parameters can make it awkward to use.
[LIMIT] ControlSend: is a bit unreliable.
[NOTE] ControlSend: If ControlSend by itself doesn't work, sometimes doing a prior ControlFocus, before the ControlSend, does work. Note: using ControlFocus on an inactive window, does not mean that the current active window will lose focus.
[WARNING] ControlClick: is a bit unreliable, e.g. test on MS Paint, it can send clicks to all points between the current cursor position and the specified point, like dragging the mouse would.
[NOTE] SendXXX: Be aware of the {Raw} option, to send text, and avoid treating special characters like +^#!{} differently.
[NOTE] SendXXX: Be aware that sending CRLF (i.e. '`r`n' in AutoHotkey) will send 2 enters, not one.

Code: Select all

;e.g. click without moving the cursor
q:: ;4 methods to send a click
CoordMode, Mouse, Screen
vPosX := A_ScreenWidth/2, vPosY := A_ScreenHeight/2

;method 1 (moves cursor)
MouseClick,, % vPosX, % vPosY

;method 2 (moves cursor)
Click, % vPosX ", " vPosY ;moves mouse

;method 3 (doesn't move cursor)
WinGetPos, vWinX, vWinY,,, A
ControlClick, % "x" -vWinX+vPosX " y" -vWinY+vPosY, A

;method 4 (doesn't move cursor)
;if !hWnd := DllCall("WindowFromPoint", Int,vPosX, Int,vPosY, Ptr)
if !hWnd := DllCall("user32\WindowFromPoint", "UInt64",(vPosX&0xFFFFFFFF)|(vPosY<<32), "Ptr")
	return
PostMessage, 0x201, 0, % (vPosX & 0xFFFF)|(vPosY<<16),, % "ahk_id " hWnd ;WM_LBUTTONDOWN := 0x201
PostMessage, 0x202, 0, % (vPosX & 0xFFFF)|(vPosY<<16),, % "ahk_id " hWnd ;WM_LBUTTONUP := 0x202
return

Code: Select all

;e.g. hover without moving the cursor
Home:: ;start menu (recent items menu) - focus menu item
End:: ;start menu (recent items menu) - focus menu item
if !(hWnd := WinExist("ahk_class BaseBar"))
	return
if InStr(A_ThisHotkey, "Home")
	PostMessage, 0x200, 0, % (10 & 0xFFFF)|(10<<16), ToolbarWindow321, % "ahk_id " hWnd ;WM_MOUSEMOVE := 0x200
else
{
	WinGetPos,,,, vPosH, % "ahk_id " hWnd
	PostMessage, 0x200, 0, % (10 & 0xFFFF)|((vPosH-10)<<16), ToolbarWindow321, % "ahk_id " hWnd ;WM_MOUSEMOVE := 0x200
}
return
==================================================

>>>AutoHotkey control flow statements
>>Break/Continue
>>For/Loop/Until/While
>>Gosub/Goto
>>If/Else
>>Return
>>Throw
>>Try/Catch/Finally

[LIMIT] Break/Continue/Return: You cannot use Break/Continue/Return in a multi-statement expression, e.g. not possible: oMyObj := "", return
[WARNING] Loop: File loops do not handle long filenames.
[LIMIT] Loop: Registry loops return keys and values in reverse alphabetical order.
[LIMIT] Loop: There is no recommended example in the documentation for a traditional For loop function.

[traditional for loop via functions][for i = a to b (step c)]
Traditional For loop (i.e., step through a sequence) - Suggestions - AutoHotkey Community
https://autohotkey.com/board/topic/71225-traditional-for-loop-ie-step-through-a-sequence/

[traditional for loop via objects][for i = a to b (step c)]
For loop question - Ask for Help - AutoHotkey Community
https://autohotkey.com/board/topic/66916-for-loop-question/#entry423515
enum type and while loop - Ask for Help - AutoHotkey Community
https://autohotkey.com/board/topic/78869-enum-type-and-while-loop/

==================================================

>>>AutoHotkey main window menu items
>>Reload/Edit/Pause/Suspend/ExitApp
>>ListLines/ListVars/ListHotkeys/KeyHistory

[LIMIT] ListXXX/KeyHistory: The 'ListXXX'/'KeyHistory' information cannot be retrieved programmatically, although there are workarounds (see ScriptInfo and DebugVars).
[WARNING] Reload: When the Reload command is used, lines underneath it can be still be executed (unlike with return/Exit/ExitApp), therefore it is recommended to put a 'return' line underneath it.

If KeyHistory (View, Key history and script info) is not showing any key presses, and #KeyHistory is not set to 0, consider using #InstallKeybdHook, or:
#InstallKeybdHook - Syntax & Usage | AutoHotkey
https://www.autohotkey.com/docs/commands/_InstallKeybdHook.htm
the keyboard hook is normally installed only when the script contains one of the following:
1) hotstrings;
2) one or more hotkeys that require the keyboard hook (most do not);
3) SetCaps/Scroll/NumLock AlwaysOn/AlwaysOff;
4) the Input command, for which the hook is installed upon first actual use.
[AutoHotkey script information direct to variable]
ScriptInfo(): Get ListLines/ListVars/ListHotkeys/KeyHistory text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=9656
[get variable text from other scripts]
DebugVars - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=24984
[get ScriptInfo() from other scripts]
test whether another script's hotkeys are still working (trigger hotkeys in another script) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=27839

==================================================

>>>AutoHotkey modes/settings
>>CoordMode/DetectHiddenXXX/SetXXX/StringCaseSense
>>Critical/Thread
>>(also: #NoTrayIcon, #UseHook, A_IsAdmin)

[WARNING/LIMIT] DetectHiddenWindows/StringCaseSense: In functions, if you change the setting for DetectHiddenWindows or StringCaseSense, you should change it back again before the function returns.
[WARNING] DetectHiddenWindows: 'bug'.
[NOTE] SetRegView: Be aware of the differences between the x64/x32 versions of the registry. Basically on x64 PCs, there are sometimes special x32 registry keys called Wow6432Node, for use with x32 programs.
[NOTE] #UseHook: makes some hotkeys that would work on Admin windows, no longer work.

DetectHiddenWindows bug? - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=14&t=30010

==================================================

>>>AutoHotkey itself (further commands/functions)
>>EnvGet/EnvSet
>>EnvXXX
>>Exit
>>Func
>>IsByRef/IsFunc/IsLabel
>>OnClipboardChange/OnExit/OnMessage
>>OutputDebug
>>RegisterCallback
>>SetTimer
>>Sleep
>>(also: #Include, #Persistent, #SingleInstance, A_Args)

[LIMIT] #Include: has limited flexibility e.g. you cannot use A_Desktop. [Fixed in 1.1.28.00 - February 11, 2018]
[NOTE] Exit: On a 'return' control flow statement, the script will return to the last sub (if any) that it came from, but with an 'Exit' command, the thread is ended immediately.
[NOTE] OutputDebug: One way to use OutputDebug: download DebugView, run Dbgview.exe, any time an OutputDebug line is executed, the text appears in the DebugView window.
[NOTE] EnvAdd/EnvSub: the var/value parameters should be numbers, but they are flexible: if they *start* with a number, subsequent characters are ignored.
[NOTE] SendMessage/SetTimer/Sleep: are unusual in accepting values in milliseconds (not seconds).

#SingleInstance options:
- #SingleInstance [force|ignore|off]
- force (default AHK v2): terminate existing instance, start new instance
- ignore: if another instance exists, do nothing, else, start new instance (e.g. useful to avoid interrupting downloads)
- off: start new instance (alongside other existing instances)
- (blank) (default AHK v1): if another instance exists, user is prompted to 'force' OR 'ignore', else, start new instance (in AHK v2, the 'blank' option no longer exists)

#Persistent: ways to invoke persistence other than via #Persistent:
- hotkeys
- hotstrings
- Gui (even if not executed)
- OnMessage (even if not executed)
- #InstallKeybdHook
- #InstallMouseHook
- BlockInput: MouseMove subcommand (if the script is not already persistent: causes 'temporary persistence' once executed, until Suspend/Hotkey commands)
- Input (if the script is not already persistent: causes persistence once executed)

Code: Select all

;a function that will run on script startup (due to 'static')
MyFunc()
{
	static vDummy := MyFunc()
	SoundBeep
	MsgBox, % "hello world"
}

;also mentioned here:
;GeekDude's tips and tricks - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=7&t=7190
;Static init functions (was: Goto Eof) - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=13&t=4172&p=23235#p23235
==================================================

>>>(A_ variables)

A_ variables are essentially functions, and can be a little slow to retrieve information, so if repeatedly using an A_ variable whose contents you do not expect to change, it may be faster to retrieve the contents once and store it in a custom variable.
E.g. very slow: A_IPAddress1/2/3/4.
E.g. quite slow: A_IsAdmin, A_UserName.
There are more details here:
jeeswg's benchmark tests - Page 3 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=74&t=37876&p=221802#p221802

==================================================

>>>(commands)
- the comma separating the command name from its parameters is optional, except when the first parameter is blank, see:
Scripting Language | AutoHotkey
https://autohotkey.com/docs/Language.htm#commands

==================================================

>>>(updated functions)
(functions that have had major changes since AHK v1.0, 'AutoHotkey Basic')

(ahk_exe): specify process name/path, cf. ahk_class/ahk_id/ahk_pid/ahk_group
(A_OSVersion): more OSes added, but it is deprecated
(Icon Support): 'Negative icon numbers may be used to identify a group icon resource within an executable file'
CoordMode: 'Window' preferred over 'Relative' for coordinates relative to the active window.
DllCall: WStr/AStr/UPtr/Ptr introduced ('Str' depends on whether AHK version is Unicode/ANSI)
IniRead/IniWrite/IniDelete: 'Read, write or delete entire sections, or retrieve a list of all section names'
InStr: 'Searches for a given occurrence of a string, from the left or the right'
Loop: Files ('FDR' style) [cf. 'Loop, FilePattern']
Loop: Reg ('RootKey\SubKey' style) [cf. 'Loop, RootKey']
NumGet/NumPut: default type parameter is now UPtr [cf. UInt]
RegRead/RegWrite/RegDelete: 'RootKey\SubKey' style
SoundSet/SoundGet: 'improved support for Windows Vista and later'
SoundSetWaveVolume/SoundGetWaveVolume: 'improved support for Windows Vista and later'
WinGet: get process path via 'ProcessPath'

affected by whether AHK version is Unicode/ANSI:
Chr/Asc/Ord, FileRead/FileAppend, Transform

see also:
AutoHotkey_L New Features
https://autohotkey.com/docs/AHKL_Features.htm
Script Compatibility
https://autohotkey.com/docs/Compat.htm

==================================================

>>>(limits)
- a custom function can have at most 255 parameters
- when defining an object via [] or Array(), it can have at most 255 keys (more keys can be added later) (StrSplit could be used instead)
- when defining an object via {} or Object(), it can have at most 127 keys (more keys can be added later)

see also:
[Variable Capacity and Memory]
Variables and Expressions
https://autohotkey.com/docs/Variables.htm#cap

Code: Select all

q:: ;range -0x8000000000000000 to 0x7FFFFFFFFFFFFFFF

MsgBox, % 0x7FFFFFFFFFFFFFFF+0 ;9223372036854775807 ;max
MsgBox, % 0x7FFFFFFFFFFFFFFF+1 ;-9223372036854775808 ;wraps around

MsgBox, % -0x8000000000000000+0 ;-9223372036854775808 ;min
MsgBox, % -0x8000000000000000-1 ;9223372036854775807 ;wraps around
return
==================================================

>>>(AutoHotkey v2)
- ClipWait: the function returns 0 if it timed out, otherwise 1.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
TheBeginner
Posts: 91
Joined: 19 Oct 2018, 12:05

Re: jeeswg's documentation extension tutorial

02 Dec 2019, 01:53

Looks like some of these things could be very useful in the documentation, have you considered adding it?
apollos
Posts: 2
Joined: 21 Dec 2019, 07:21

Re: jeeswg's documentation extension tutorial

21 Dec 2019, 07:41

Hi, thanks for sharing this is really very useful.

Return to “Tutorials (v1)”

Who is online

Users browsing this forum: No registered users and 34 guests