I have uploaded a test build with some long-awaited experimental features, based on v1.1.19.
Functions and Objects as Labels
- Hotkey, SetTimer, Gui g-labels, Menu and OnExit have been retro-fitted to accept functions and objects.
- Functions can be defined instead of labels for Gui events like GuiClose (and 2GuiClose, etc.).
- OnClipboardChange is unaffected due to rarity of need and potential conflict with the OnClipboardChange() function in AutoHotkey v2.
Code: Select all
Gui Add, Button, w75 , Implied
Gui Add, Button, w75 gButton, Explicit
Gui Add, Button, w75 , Bound object
fn := bind("Button", 42) ; Bind parameters to a function.
GuiControl +g, Bound object, %fn%
ButtonImplied() { ; Implicitly used by Button "TEST".
MsgBox %A_GuiControl%
}
Button(s:="") {
MsgBox %A_GuiControl%`n%s%
}
/*
GuiClose: ; This line doesn't stop execution, so script will exit.
ExitApp
*/
GuiClose() {
ExitApp
}
Gui Show ; Still in the auto-execute section.
Code: Select all
fn := bind("Timer", 1)
SetTimer %fn%, -1000
SetTimer %fn%, -2000 ; Change interval of existing timer
fn := bind("Timer", 2)
SetTimer %fn%, -1000 ; Create separate timer
Sleep 3000
; Result: Timer 2, followed by Timer 1.
Timer(n) {
ToolTip Timer %n%
Sleep 950
ToolTip
}
Code: Select all
bind(fn, args*) { ; bind v1.2
try bound := fn.bind(args*) ; Func.Bind() not yet implemented.
return bound ? bound : new BoundFunc(fn, args*)
}
class BoundFunc {
__New(fn, args*) {
this.fn := IsObject(fn) ? fn : Func(fn)
this.args := args
}
__Call(callee, args*) {
if (callee = "" || callee = "call" || IsObject(callee)) { ; IsObject allows use as a method.
fn := this.fn, args.Insert(1, this.args*)
return %fn%(args*)
}
}
}
Code: Select all
mi := new MenuItem(1)
Menu M, Add, Hello, %mi%
mi := new MenuItem("A")
Menu M, Add, World, %mi%
Menu M, Show
class MenuItem {
__New(name) {
this.name := name
}
Call() {
MsgBox % "Called menu item " this.name
}
}
For Gui buttons, you can define ButtonOK() as you would define a label, or you can use +gFuncName. To use an object, you need to use GuiControl with the third parameter being a single %variable% deref (the object):
Code: Select all
GuiControl +g, Button1, %fn%
For hotkeys, Suspend Permit works with labels and functions. It cannot work with other objects, as it is not known which line (if any) will be executed first when the object is called.
Added on 2015-01-13: Hotkey functions, as demonstrated below.
Code: Select all
^a::
^b::
pressing_ctrl_a_or_b_calls_this_function() {
MsgBox %A_ThisHotkey%
}
Localized Key Characters
This affects GetKeyName, Hotkey Gui controls, A_PriorKey, KeyHistory and Input (when ErrorLevel is EndKey:).
In prior releases, the VK codes 'A' (vk41) to 'Z' (vk5A) were always named using their ASCII counterparts (at least on systems with US keyboard as the default, even if some other layout is in use). This is apparently due to some quirky behaviour of MapVirtualKey. All other keys, including those that produce letters, were already converted to the appropriate character depending on the script's current keyboard layout.
So for example, if I switch from US to Russian layout and press Ctrl+й, the Hotkey control produces ^Q even though the Hotkey command refuses to register that hotkey (because Q doesn't exist in the Russian layout).
This change may break some scripts. It may also fix some scripts. Note that for backward-compatibility, the Input command's ErrorLevel returns EndKey:A rather than EndKey:a even though non-ASCII letters are returned in lower-case. Also note that while ^q:: and ^Q:: perform identically, ^Q is actually equivalent to ^+q when used with Send.
The Input command has a new option E, which causes single-character EndKeys to be handled by character rather than by VK or SC. This allows Input to adapt to the keyboard layout of the active window when multiple layouts are in use. It also prevents the end key from being triggered if that character isn't actually typed (such as if the Alt or Ctrl keys are held down).
Other Changes
There are some other changes in later updates. Look for "Update" in later posts.
Download