Search notes:

autohotkey

By default, a script adds an icon in the tray and has a main window (See A_ScriptHwnd).
The title of the main window is used to determine if a script is already running in conjunction with #SingleInstance
Variable names and function names are not case senstitive.
Comments are introduced with a ; (semicolon).
Implicit string concatenation (aka auto-concat):
"some text" a_var
There is a #include.

Simple example

Put the following script into a file, for example named j-msgBox.ahk:
#requires autoHotkey v2.0

^j:: {
    msgBox("Hello, World!")
}
Then start the script (double clicking, or from the command line)
Press ctrl-j.

Running scripts on startup

An .ahk script can be placed under C:\Users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup so that it is automatically started.

Variables

Three types (compare Type function)
A variable itself is not typed.
Built-in variables:
A value is assigned with :=
Environment variables can be queried with EnvGet(…).
ListVars

Functions

Some functions are

Defining functions

DoWhatIWant(par_1, byRef par_2, par_3 := "")
{
  …
  return 42
}

Statements

Some statements are:

Operators

Some operators are:

Objects

Some objects are

Hotkeys

A hotkey can be used to trigger actions.
Key modifiers:
Prepending the hotkey with a dollar sign ($) seems to prevent the hotkey from being (possibly recursively) invoked if a hotkey sends the hotkey.
Prepending the hotkey with a tilde (~) seems to not intercept the bound hotkey but rather to let it go to the underlying application.

Labels

A label identifies a line of code. There are three types of labels:

Misc

c:\> autohotkey.exe /Debug
c:\> autohotkey.exe /Debug=server:port

Identifying windows

Functions that need to identify windows to operate on (usually?) have a winTitle parameter. The value of this parameter can be

TODO

Version 1 vs version 2

What's the deal with Auhohotkey version 2, the #requires autoHotkey v2.0 directive and the .ahk2 suffix?
The documentation allows to switch from V1 to V2 in the blue title bar.
The version of the interpreter can be set in tha script with the #requires directive, for example:
 #requires autoHotKey v2

Message Box

#requires autoHotkey v2

; msgBox "no paranthesis    quotes"  ; error because no parantheses
; msgBox(    paranthesis no quotes ) ; msgBox, but no text
msgBox("A string")

var       := "The value of a variable"
nameOfVar := "var"

msgBox( var       ) ; The value of a variable
msgBox(%nameOfVar%) ; The value of a variable
Github repository temp-AutoHotKey, path: /msgBox.ahk

Variable concatenation

#requires autoHotkey v2

var_1 := 'hello"
var_2 := 'world'

msgBox(var_1   " "   var_2) ; implicit concatenation
msgBox(var_1 . " " . var_2) ; explicit concatenation

One liner

One of the arguably simplest Autohotkey scripts: As soon as hi, followed by a space, is typed, the hi is replaced with Hello World:
#requires autoHotkey v2
::hi::Hello World
Github repository temp-AutoHotKey, path: /one-liner.ahk

Command line parameters

#requires autoHotkey v2

msgBox("count of parameters: " a_args.length)

for paramNo, paramValue in a_args {
    msgBox("Parameter " paramNo " is " paramValue)
}

Getting text with input()

;
;             L5     : max length
;                T3  : timeout
;
txt := input("L5 T3", "{enter}")


;
; possible Values for errorLevel:
;    Max
;    Timeout
;    EndKey:Enter
;
msgBox("txt = " txt ", errorLevel = " errorLevel)
Github repository temp-AutoHotKey, path: /input.ahk2

Stopping a script

A running autohotkey script can be stopped with exitApp().
#requires autoHotkey v2

loop (10) {

  if a_index = 4 {

    msgBox('a_index reached 4, stopping script')
    exitApp()

  }
  msgBox('a_index = ' . a_index . ' - not yet stopping this script')
}
Github repository temp-AutoHotKey, path: /exitApp.ahk

Sleep

#requires autoHotkey v2

msgBox('Going to sleep for 2 seconds')
sleep(2000)
msgBox('I woke up')
Github repository temp-AutoHotKey, path: /sleep.ahk

Dynamically create a hotkey

Hotkeys are either created by a (double colon) hotkey label (such as i::…) or the hotkey(…) function.
The function hotkey allows to dynamically create a hotkey.
#requires autoHotkey v2

; hotkey_trigger  := '^a'
; hotkey_function := 'ctrl_a'


hotkey '^a', f ; ctrl-a and
hotkey '!q', f ; Alt-q calls function f

f(p) {
   msgBox(p ' was pressed')

   if (p == '!q') {
      ExitApp()
   }
}


Github repository temp-AutoHotKey, path: /hotkey.ahk

Classes and objects (instances)

Autohotkey allows to declare classes.
The name of a class's constructur is __new.
Member functions are declared like ordinary functions.
#requires autoHotkey v2

class cls {
;
;    The constructur
;
   __new(foo, bar, baz) {
         this.foo := foo
         this.bar := bar
         this.baz := baz
   }

;
;    A member procedure / function:
;
   msg() {

      msgBox('foo = ' . this.foo . 
           '`nbar = ' . this.bar . 
           '`nbaz = ' . this.baz)

   }
}

obj_1 := cls(   1,     2,       3 )
obj_2 := cls('one', 'two', 'three')
 
obj_1.msg()
obj_2.msg()
Github repository temp-AutoHotKey, path: /class-new.ahk

__get / __set

A class can be implemented with dynamic setters and getters: the name of the attribute to be set or get is passed as a string to __get(attr) or __set(attr, val):
#requires autoHotkey v2

class C {

  __get(attr, params) {
     msgBox('Someone attempted to get the value of ' . attr)
     return 21
  }

  __set(attr, params, val) {
     msgBox('Someone attempted to set the value of ' . attr . ' to ' . val)
;    msgBox('Someone attempted to set the value of')
  }

}

obj := C()

obj.v1 :=  12345
msgBox(obj.v1)  ; 21

obj.v2 := obj.v2*2
msgBox(obj.v2)  ; 21
Github repository temp-AutoHotKey, path: /class-__get-__set.ahk

__call

Similarly to __get and __set, __call receives the name (and parameters) of a method whose name is not explicitly implemented.
#requires autoHotkey v2

class C {

   __call(method_name, params) {

     param_str := ''
     for ix, nam in params {
        param_str := param_str . ' - param_' . ix . '=' . nam
     }

     msgBox('Someone tried to call ' . method_name . param_str)
   }
}

obj := C()

obj.a_func()

obj.another_func('foo', 'bar', 'baz')
Github repository temp-AutoHotKey, path: /class-__call.ahk

a_tickCount

a_tickCount is a counter of milli seconds with limited precision (Approx. 10 ms?). Better precision can be achieved with DllCall("QueryPerformanceCounter", "Int64*", ms).
#requires autoHotkey v2

tcBegin := a_tickCount
sleep 1000
tcEnd   := a_tickCount

msgBox('Sleep took approximately ' . (tcEnd - tcBegin) . ' ms')
Github repository temp-AutoHotKey, path: /a_tickCount.ahk

Variables that point to directories

Some a_ variables point to known directories
#requires autoHotkey v2

g := gui()

g.onEvent('close', (*) => exitApp())

lst := g.add(
   'listView',
   'r13 w600' , ; 13rows, 600 pixels wide. Add' vLV' to the string to give the control the name LV ?
  ['readonly', 'Variable|Value']

)

g.show()

lst.add('', 'a_winDir'          , a_winDir         )
lst.add('', 'a_programFiles'    , a_programFiles   )
lst.add('', 'a_appData'         , a_appData        )
lst.add('', 'a_appDataCommon'   , a_appDataCommon  )
lst.add('', 'a_desktop'         , a_desktop        )
lst.add('', 'a_desktopCommon'   , a_desktopCommon  )
lst.add('', 'a_startMenu'       , a_startMenu      )
lst.add('', 'a_startMenuCommon' , a_startMenuCommon)
lst.add('', 'a_startUp'         , a_startUp        )
lst.add('', 'a_startUpCommon'   , a_startUpCommon  )
lst.add('', 'a_programs'        , a_programs       )
lst.add('', 'a_programsCommon'  , a_programsCommon )
lst.add('', 'a_myDocuments'     , a_myDocuments    )

;
; Autofit column header:
;
lst.modifyCol
Github repository temp-AutoHotKey, path: /a_directories.ahk

a_comSpec

The a_comSpec variable contains the path to cmd.exe (for example C:\Windows\System32\cmd.exe).
#requires autoHotkey v2

msgBox(a_comSpec)
Github repository temp-AutoHotKey, path: /a_comSpec.ahk
Compare with the environment variable %ComSpec%.

Screen dimensions (a_screenWidth, a_screenHeight)

The width and height of the screen are stored in a_width and a_height.
If using multiple monitors, only the dimensions of a single monitor (the primary one?) are reported. gh|temp-AutoHotKey|/screen-dimensions.ahk|

Determine version (a_ahkVersion)

#requires autoHotkey v2

msgBox(a_ahkVersion)
Github repository temp-AutoHotKey, path: /version.ahk

Run exe or switch to application

#requires autoHotkey v2

; msgBox "hot string"
; IfWinExist     ahk_exe excel.exe

:*:gtexcel:: {

   if (pid_excel := processExist("excel.exe")) {
      msgBox("excel found, pid_excel = " pid_excel)
      winActivate("ahk_pid " pid_excel)
   
   }
   else {
      msgBox("excel not found found, starting")
      run("C:\Program Files (x86)\Microsoft Office\Root\Office16\excel.exe")
      WinWait    ('ahk_exe excel.exe')
      WinActivate('ahk_exe excel.exe')
    ; msgBox('Excel should now be ready') ; Not true, unfortunately
   }
}

Read a file line by line

The following script iterates over each line of a given file:
#requires autoHotkey v2

loop read 'read-file-line-by-line.ahk' {
   msgBox(a_loopReadLine)
}

noTrayIcon

With the #noTrayIcon directive, no tray icon is shown. The (in-)visibility of the tray icon is stored in the variable a_iconHidden.
#requires autoHotkey v2

 #noTrayIcon

msgBox("do you see a tray icon?\nThe value of a_iconHidden is: " a_iconHidden)
Github repository temp-AutoHotKey, path: /noTrayIcon.ahk

singleInstance

#singleInstance force

a_coordMode variables

#requires autoHotkey v2

msgBox (  'a_coordModeToolTip = ' . a_coordModeToolTip .
        '`na_coordModePixel = '   . a_coordModePixel   .
        '`na_coordModeMouse = '   . a_coordModeMouse   .
        '`na_coordModeCaret = '   . a_coordModeCaret   .
        '`na_coordModeMenu = '    . a_coordModeMenu
      )
Github repository temp-AutoHotKey, path: /a_coordMode.ahk

coordMode

coordMode can be used (among others) to specifiy if the mouse coordinates (mouseGetPos) are reported relative to the active window or the screen.
#requires autoHotkey v2

coordMode('mouse', 'window')
mouseGetPos(&mouseX, &mouseY)
msgBox('mouse position relative to active window:`nX: ' . mouseX . ', Y: ' . mouseY)

coordMode('mouse', 'screen')
mouseGetPos(&mouseX, &mouseY)
msgBox('mouse position relative to screen:`nX: ' . mouseX . ', Y: ' . mouseY)
Github repository temp-AutoHotKey, path: /coordMode.ahk

Variables

#requires autoHotkey v2

num :=  42
txt := "The answer is " num

msgBox(txt  )      ; The message box shows the content of the variable txt: «The answer is 42»

varValue := txt    ; Assign value of variable txt to another variable
varName  :="txt"   ; Assign literal string to a variable

msgBox(varValue )  ; The message Box shows the value of varValue: «The answer is 42»
msgBox(varName  )  ; The message box shows the value of varName : «txt»
msgBox(%varName%)  ; The message box shows the value of the variable txt: «The answer is 42»
Github repository temp-AutoHotKey, path: /variables.ahk

null value

Autohotkey defines the special null value.
Apparently, a variable that hasn't been assigned a value is null and indistingishable from a variable that was explicitly assigned null.
TODO: The following example does not work enymore:
#requires autoHotkey v2

check_if_null(var) {
  if(var === null) {
     msgBox('var = null')
  }
  else {
     msgBox(var . ' != null')
   }
}

; var_1 := 42
var_2 := null

; check_if_null(var_1) ; 42 != null
check_if_null(var_2) ; var = null
check_if_null(var_3) ; var = null
Github repository temp-AutoHotKey, path: /null.ahk
The type of null is String.

Types

type(…) reveals the type of an expression.
#requires autoHotkey v2

i :=  42
f :=  99.9
s := 'hello world'

msgBox (
  'type(i)    = ' . type(i) . '`n' .   ; Integer
  'type(f)    = ' . type(f) . '`n' .   ; Float
  'type(s)    = ' . type(s) . '`n'
)
Github repository temp-AutoHotKey, path: /type.ahk

Arrays

Arrays can be created with […, … ].
The type of an array is Object.
The number of elements in an array is reported with .length.
Arrays can be nested.
#requires autoHotkey v2

someArray   := [42, 'text', 99]
nestedArray := ['xyz', someArray]

msgBox(type(someArray)) ; Object

msgBox('count of items in someArray: '   . someArray.length  ) ; 3
msgBox('count of items in nestedArray: ' . nestedArray.length) ; 2

iterateOverObject(nestedArray)

iterateOverObject(obj) {

  for ix, val in obj {
     if (type(val) == 'Array') {
        iterateOverObject(val)
     }
     else {
       msgBox (ix . ': ' . val)
     }
  }
}
Github repository temp-AutoHotKey, path: /array.ahk

Associative Arrays (Dictionaris, Hashes)

#requires autoHotkey v2

someDictionary := Map(
  'greeting', 'Hello world',
  'fruit'   , 'apple'      ,
  '^%@'     , 'chrüsimüsi' ,
)

; msgBox(someDictionary.fruit) ; Error: This value of type "Map" has no property named "fruit".

msg(i) {
   msgBox(someDictionary[i])
}

msg("greeting")
Github repository temp-AutoHotKey, path: /dictionary.ahk

Checking if a key exists

An associative array defines the method hasKey(k) that determines if the key k exists.
#requires autoHotkey v2

dict := Map(
  'num', 42,
  'txt','Hello world'
)

if (dict.has('num')) {
    msgBox('num exists')
}
else {
    msgBox('num does not exists')
}

if (dict.has('unobtainium')) {
    msgBox('unobtainium exists')
}
else {
    msgBox('unobtainium does not exists')
}
Github repository temp-AutoHotKey, path: /hasKey.ahk

Warn

TODO: The #warn directive

envGet

envGet returns the value of a environment variable.
#requires autoHotkey v2

msgBox(envGet("USERPROFILE")) ; Show the user's home directory
Github repository temp-AutoHotKey, path: /envGet.ahk

setKeyDelay

As per the documentation, setKeyDelay sets the delay that will occur after each keystroke sent by send and controlSend.
However, I was unable to figure out exactly what it is supposed to delay.
#requires autoHotkey v2

setKeyDelay ( 100, 100  )
send        ("some text")
Github repository temp-AutoHotKey, path: /setKeyDelay.ahk

keyWait

#requires autoHotkey v2
;
; D: wait for pressing Down
; T: Specify wait time in seconds
;
res := keyWait("k", "D T2.5")

if (res == 0) {
   msgBox("You didn't press k for two and a halve seconds")
   return
}
msgBox("You pressed k within two and a halve seconds")
Github repository temp-AutoHotKey, path: /keyWait.ahk

hot keys

#requires autoHotkey v2

;
;  Detect the simultaneous pressing of two keys (f and j)
;

f & j:: {
;
; Note: pressing f (even if not followed by j) won't
; put it into the message queue of the current process, it
; is consumed (or swallowed)
;

   msgBox('f and j simultaneously')

   exitApp()

}
Github repository temp-AutoHotKey, path: /hotkeys-f_and_j_1.ahk
#requires autoHotkey v2
;
;  The following hot key detects if an f is pressed, released and
;  followed by a j that is pressed.
;
;  As soon as the f is pressed, it will be sent to the receiving
;  application. If AHK detects the following j, the f is erased.
;  
;
:*:fj:: {
   msgBox('f followed by j')
   exitApp()
}
Github repository temp-AutoHotKey, path: /hotkeys-f_and_j_2.ahk
This does not work how it was intended:
#requires autoHotkey v2
;
; Use $ so that the »send('f')« does not
; retrigger the hot key
;
$f:: {

  res := keyWait('j', 'D T0.5')
  msgBox('waiting ended, res = ' . res)

  if (res == 0) { ; f was not followed by j
     send 'f'
  }

; msgBox('f followed by j')

}
Github repository temp-AutoHotKey, path: /hotkeys-f_and_j_3.ahk

tilde

A hot key can be prepended with a tilde in which case the triggering hot key is passed to the receiving application.
Without tilde, the hotkey is «swallowed» by AutoHotKey.
 #requires autoHotkey v2

 g::msgBox('g was pressed')
~f::msgBox('f was pressed')
 q::exitApp()
Github repository temp-AutoHotKey, path: /tilde.ahk

dollar sign

A hot key can be prepended with a dollar sign in which case the hot key is not invoked if the body of the hotkey causes the triggering hot key to be sent again.
$a:: {

  msgBox('a was pressed - sleep a second, then send key a')
  sleep 1000
  send('a')

}
q::exitApp()
Github repository temp-AutoHotKey, path: /dollar.ahk

Run application and wait for it to become active

#requires autoHotkey v2

;
;  Run notepad and store its process
;  identifier in notepadPid (note the ampersand as
;  indication for out-parameter)
;
run('notepad.exe' ,,, &notepadPid)

;
;  Wait until Window with given pid
;  becomes active
;
winWait('ahk_pid ' . notepadPid)

;
;  Write something into the new window.
;
sendInput ('hello world')
Github repository temp-AutoHotKey, path: /run-winWait.ahk

fileAppend

fileAppend appends some text to an existing file or creates a file with the given line.
#requires autoHotkey v2

fileAppend("a line`n"      , "fileAppend.txt")
fileAppend("another line`n", "fileAppend.txt")
Github repository temp-AutoHotKey, path: /fileAppend.ahk

order of definition

A function can be called even if it is defined later.
#requires autoHotkey v2

f()

f() {
  msgBox('f was called')
}
Github repository temp-AutoHotKey, path: /orderOfDefinition.ahk

if

#requires autoHotkey v2

num_1 := 10
num_2 := 32

if (num_1 + num_2 = 42) {
   msgBox("num_1 + num_2 = 42")
}
else {
   msgBox("num_1 + num_2 ≠ 42")
}


if (1 = 3) {
   msgBox("1 = 3 statement 1")
   msgBox("1 = 3 statement 2")
}
else if (1 = 2) {
   msgBox("1 = 2 statement 1")
   msgBox("1 = 2 statement 2")
}
else {
   msgBox("else statement 1")
   msgBox("else statement 2")
}
Github repository temp-AutoHotKey, path: /if.ahk

Gui

gui allows to create an «ordinary» window.
#requires autoHotkey v2

opts := 
   '+caption '    . 
   '+border '     .
   '+toolWindow ' . ; +toolWindow avoids a taskbar button and an alt-tab menu item
   '+alwaysOnTop'

g := gui(opts)

g.backColor := 'ffcc88'

g.marginX   :=  30
g.marginY   :=  18


g.addText(''    , 'HWND of g is ' . g.hwnd) ; First parameter is options.
g.addText(''    , 'Enter some text: ')      
g.addEdit('vTxt'                     )      ; Note the v that apparently indicates the name to later retrieve the value entered.

b := g.addButton('default', 'Go')
b.onEvent('click', (*) => clicked(g))

g.show(
   'x30 ' .
   'y10 '
)

; winSetTransColor ('ffcc88', 'gui.ahk2')
; winSetTransparent(    200 , 'gui.ahk2')

clicked(this) {
;
; submit()
;    save the contents of the
;    controls into an associative array.
;
  ctrls := this.submit()

  msgBox('txt = ' . ctrls.txt)
  this.destroy()

}
Github repository temp-AutoHotKey, path: /gui.ahk

Edit control

An edit control might be used for debugging purposes. The following example writes the mouse position every second:
gh|temp-AutoHotKey|/gui-addEdit.ahk|

Positioning controls with the section option

When creation a control, the option of a control can include section. This allows subsequently created controls to be added on the same y coordinate by including ys in their option.
#requires autoHotkey v2

g := gui()

g.onEvent('close', (*) => exitApp())

      ;         type ,  options     ,  caption
      ;         ---- ,  ----------- ,  -------
txt_1 := g.add('text', 'w50'        , 'txt 1'  )
txt_2 := g.add('text', 'w50'        , 'txt 2'  ) ; control added below previous one
txt_3 := g.add('text', 'w50 section', 'txt 3'  ) ; control added below previous one - new section started
txt_6 := g.add('text', 'w50'        , 'txt 6'  ) ; contral added below previous one
txt_4 := g.add('text', 'w50 ys'     , 'txt 4'  ) ; Using ys to place control with same y as previous section, as left as possible
txt_5 := g.add('text', 'w50 ys'     , 'txt 5'  ) ; Using ys to place control with same y as previous section, as left as possible

g.show()

Optional parameters

#requires autoHotkey v2

fnc(p_one, p_two := 42, p_three := 'hello world') {
  msgBox('p_one =   ' . p_one   . '`n' .
         'p_two =   ' . p_two   . '`n' .
         'p_three = ' . p_three . '`n')
}

fnc('use all defaults')

;
; In the following call, the second parameter (p_two)
; will have the value 42.
;
fnc('override 3rd param', , 'overridden')

;
; In the following call, the p_three does not
; name a parameter. In fact, within the
; function p_two will have the value 'x'
; and p_three the value 'hello world'
;
fnc('override 3rd param', p_three := 'x')

Function references

#requires autoHotkey v2

saySomething(txt) {
   msgBox(txt)
}

funcName := 'saySomething'
funcRef := %funcName%

msgBox('type(funcRef) = ' type(funcRef)) ; Func

funcRef('Calling func ref with %')

funcRef.call('calling func ref with call()')

funcRefParam := funcRef.bind('bound parameter')
funcRefParam()
Github repository temp-AutoHotKey, path: /functionReference.ahk

Closures

#requires autoHotkey v2

globalVar := 'one'

createClosure(txt) {

  f() {
    msgBox('txt = ' . txt)
  }
  return f

}

closure_one := createClosure('one')
closure_two := createClosure('two')

closure_one.call()
closure_two.call()
Github repository temp-AutoHotKey, path: /closures.ahk

sysGet

sysGet() seems to call the Windows API function GetSystemMetrics().
#requires autoHotkey v2
SM_CMONITORS := 80 ; The number of display monitors on a desktop. Counts visible displays only (Compare with EnumDisplayMonitors)
SM_CXHTHUMB  := 10 ; Pixel-Width of the thumb box in a horizontal scrool bar.

nofMonitors  := sysGet(SM_CMONITORS)
thumbWidth   := sysGet(SM_CXHTHUMB )

msgBox('nofMonitors: ' . nofMonitors . '`n' .
       'thumbWidth:  ' . thumbWidth)
Github repository temp-AutoHotKey, path: /sysGet.ahk

regexReplace

Autohotkey also supports regular expressions.
#requires autoHotkey v2

txt := 'The num is 42.'

;
;  Find consecutive digits (\d+) and
;  replace them with fixed string NUMBER.
;
res := regexReplace(txt, '\d+', 'NUMBER')
msgBox(res) ; The num is NUMBER

;
;  Find anything, but non-greedy (.*?), then
;  find consecutive digits and capture them
;  in parantheses, then match rest. Replace
;  with captured digits ($1):
;
num := regexReplace(txt, '.*?(\d+).*', '$1')
msgBox('num = ' . num)
Github repository temp-AutoHotKey, path: /regexReplace.ahk

Say something

The following example uses comObjCreate to create an COM instance of the Microsoft Speech Object Library and then to say Hello World:
sapi := comObject('sapi.spVoice')
sapi.speak('Hello world')
Github repository temp-AutoHotKey, path: /say-hello-world.ahk

winGetList

The following snippet gets all top level(?) Windows and writes their HWND and title into a list view:
#requires autoHotkey v2

g := gui()

g.onEvent('close', (*) => exitApp())

lst := g.add('listView',
   'r50 '  . ;  50 rows
   'w600 ' . ; 600 pixels wide
   'vEdt ' . ; Name of edit is Edt
   'readonly',
  ['Index','HWND', 'Title']
)

g.show()

allWindows := winGetList()

lst.modifyCol(1, 'integer')
lst.modifyCol(2, 'integer')

for i, hwnd in allWindows {
; edt.text := edt.text  . i . ': ' . hwnd . winGetTitle('ahk_id ' . hwnd) . "`r`n"
  lst.add(, i, hwnd, winGetTitle('ahk_id ' . hwnd))
}

;
; Autofit column header:
;
lst.modifyCol
Github repository temp-AutoHotKey, path: /winGetList-all.ahk
winGetList can also be used to find windows by their title:
;
;  WinGetList() by default searches case sensitively. 
;
;  By setting the match mode to regEx and using i), the
;  behaviour can be changed to searching case insenstive.
;

setTitleMatchMode('regEx')
l := winGetList('i)prompt')

for i, hwnd in l {
  msgBox(
   'hwnd   = ' . hwnd                                .
  '`ntitle = ' . winGetTitle      ('ahk_id ' . hwnd) .
  '`nclass = ' . winGetClass      ('ahk_id ' . hwnd) .
  '`nProc  = ' . winGetProcessName('ahk_id ' . hwnd)
 )
}
Github repository temp-AutoHotKey, path: /winGetList-title.ahk2

winGetControls

#requires autoHotkey v2

run('notepad.exe',,,&notepadPid)  ; Start notepad, store PID in notepadPid
winWait('ahk_pid ' . notepadPid)  ; Wait until active

sendInput ('hello world')         ; Type something

sendInput ('!{f4}')

; sleep(1000)

winTitleSaveConfirmation := 'ahk_pid ' . notepadPid . ' ahk_class #32770'

winWait(winTitleSaveConfirmation)

h := winGetID(winTitleSaveConfirmation)
; msgBox('hwnd = ' . h)

  ctrls      := winGetControls(winTitleSaveConfirmation)
; ctrls      := winGetControls('ahk_id ' . h)
  ctrls_hwnd := winGetControlsHwnd(winTitleSaveConfirmation)

; msgBox('type: ' . type(ctrls))
; msgBox(ctrls)
; msgBox('cnts: ' . ctrls.length() . ' / ' . ctrls_hwnd.length())

for i, ctrl in (ctrls) {
    msgBox (i . ': ' . ctrl . ': ' . ctrls_hwnd[i] . ' | ' . winGetTitle('ahk_id ' . ctrls_hwnd[i]))
;   msgBox (i . ': ' . ctrl . ': ' . ctrls_hwnd[i])
}
Github repository temp-AutoHotKey, path: /winGetControls.ahk

Escape characters and Carriage return / line feed

The default escape character in autohotkey is the back-tick. If followed by an n, it produces a new line (ASCII 10), if followed by an r, it produces a carriage return (ASCII 13).
Thus, it is possible to insert line breaks into strings.
#requires autoHotkey v2

msgBox('line one`nline two`nAsc(``n) = ' . ord('`n') . '`nord(``r) = ' . ord('`r'))
Github repository temp-AutoHotKey, path: /new-line.ahk

Calling a function in a dll

dllCall allows to call a function in a DLL.
The first argument specifies the DLL and the function, separated by a backslash. In case of a WinAPI function (more specifically: if the function is in one of the four DLLs user32.dll, kernel32.dll, comctl32.dll or gdi32.dll), the name of the DLL may be omitted.
The following parameters come in pairs of which the first argument specifies the data type and the second argument the valuer to be passed to the DLL.
Note: the data type Str is equivalent to WStr and specifies a wide character string. An ASCII string is specified by AStr. (See also WinAPI: A and W functions)
#requires autoHotkey v2

MB_YESNO := 4
IDYES    := 6
IDNO     := 7

yes_or_no := dllCall('MessageBoxW',
                      'Int', "0"         ,
                      'Str', 'Yes or no?',
                      'Str', 'Confess!'  ,
                      'Int', MB_YESNO)

if      yes_or_no = IDYES
        msgBox 'You confessed'

else if yes_or_no = IDNO
        msgBox 'You did not confess'

else
        msgBox 'Unexpected answer'
Github repository temp-AutoHotKey, path: /dllCall.ahk

Fat arrow / lambda expressions

The => operater is apparently known by the expression fat arrow and seems to make lambda expressions possible.
Lambda functions are useful to define callback-functions where they're used.
Apparently, only one statement is possible in a lambda expression.
sumFuncResultOnArray(ary, f) {
   s := 0 

   for idx, itm in ary {
     s := s + f.call(itm)
   }

   return s
}

msgbox (sumFuncResultOnArray([3, 6, 7], (e) => 2*e )) ; 32   (= 2*3 + 2*6 + 2*7 = 6+12+14)
Github repository temp-AutoHotKey, path: /lambda-1.ahk2
#requires autoHotkey v2

;
;  Why does this compile?
;
;  Found @ https://www.autohotkey.com/boards/viewtopic.php?t=46150 
;

() => {
  lambda:
  dllCall('one')
  dllCall('two')
}

() => [
	DllCall( 1 )
	DllCall( 2 )
	DllCall( 2 )
]
Github repository temp-AutoHotKey, path: /todo-lambda.ahk

Anonymous event handlers

#requires autoHotkey v2

g := gui()

txt := g.add('text', 'w200 r1')
txt.text := 'Hello!'

;
; This does not work (https://stackoverflow.com/questions/56849007)
;
; g.onEvent('close', (*) => function() {
;   msgBox('Going to exit application')
;   exitApp()
; })

;
;  Any of the following do (https://stackoverflow.com/a/60476070/180275)
;
g.onEvent('close', (*) => (
  msgBox('Going to exit application')
  exitApp()
))

; g.onEvent('close', (*) => (
;   msgBox('Going to exit application'),
;   exitApp()
; ))

; g.onEvent('close', (*) => (msgBox('Going to exit application') exitApp()))

; g.onEvent('close', (*) => (msgBox('Going to exit application'), exitApp()))

g.show()

See also

AutoHotKey sources

Index

Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 8 attempt to write a readonly database in /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php:78 Stack trace: #0 /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php(78): PDOStatement->execute(Array) #1 /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php(30): insert_webrequest_('/notes/tools/au...', 1756326787, '216.73.216.101', 'Mozilla/5.0 App...', NULL) #2 /home/httpd/vhosts/renenyffenegger.ch/httpsdocs/notes/tools/autohotkey/index(1482): insert_webrequest() #3 {main} thrown in /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php on line 78