send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey) Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)

01 Apr 2017, 00:31

How can you send keys to a GUI without causing beeps?

E.g. if you send Ctrl+D to the window in 'Simple text editor with menu bar'. Available here (the example at the very bottom of the page):
GUI
https://autohotkey.com/docs/commands/Gui.htm#Examples
then it triggers a beep.

If you try this on Notepad, there are no beeps. [EDIT: in Notepad there are beeps, I had a script running that was interfering]

WARNING: be careful when using the 'Simple text editor with menu bar' script, if you want to open a text file for testing, use a dummy file. The way the script is written, it is easy to accidentally overwrite the file and lose data.

(Apologies if this question has been asked before, I didn't find any search results, if so, please post a link/some links, including to any non-AHK sites because it might be a common problem.)

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

Btw, what is the proper way to define hotkeys for within an AutoHotkey GUI?

E.g. to make Ctrl+D, duplicate the line above (or rather, to paste the line above, after the caret):

Code: Select all

^d:: ;copy line above (duplicate line above)
WinGet, hWnd, ID, A
ControlGet, vLineNum, CurrentLine, , % "Edit1", % "ahk_id " hWnd
ControlGet, vText, Line, % vLineNum-1, % "Edit1", % "ahk_id " hWnd
Control, EditPaste, % vText, % "Edit1", % "ahk_id " hWnd
return
Some guesses. Should we use OnMessage and WM_KEYDOWN? RegisterHotkey? Use a hotkey label? Something else? What do most non-AutoHotkey GUIs, that use the Winapi, use?

I probably wouldn't want to use an AHK hotkey label, because I'd want my and other people's AHK scripts to be able to easily override the hotkey, if they wanted to.
Cheers.
Last edited by jeeswg on 14 Apr 2017, 23:06, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4664
Joined: 17 Jul 2016, 01:02
Contact:

Re: send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)

14 Apr 2017, 16:59

jeeswg wrote: Btw, what is the proper way to define hotkeys for within an AutoHotkey GUI?
Hi, I'd do it as any other context sensitive hotkey, eg,

Code: Select all

#If WinActive("ahk_id " guiHwnd) ; Maybe check control focus too.
^d:: ;copy line above (duplicate line above)
WinGet, hWnd, ID, A ; You wouldn't need this in this case.
ControlGet, vLineNum, CurrentLine, , % "Edit1", % "ahk_id " hWnd
ControlGet, vText, Line, % vLineNum-1, % "Edit1", % "ahk_id " hWnd
Control, EditPaste, % vText, % "Edit1", % "ahk_id " hWnd
return
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)

14 Apr 2017, 17:05

Thank you very much Helgef, your example code is useful, I suppose an ahk_group is another possibility.

But for example, how would say, Notepad, define Ctrl+O as Open. Cheers.

Is it RegisterHotkey maybe?

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

[EDIT]

I just remembered, I think Notepad uses accelerators which it stores as a resource.
For example, use Resource Hacker to inspect:
E.g. Windows XP:
C:\Windows\System32\notepad.exe
E.g. Windows 7:
C:\Windows\System32\en-US\notepad.exe.mui

And so it probably loads up this resource and assigns the 'hotkeys' accordingly.

Keyboard Accelerators (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
TranslateAccelerator function (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
The function translates a WM_KEYDOWN or WM_SYSKEYDOWN message to a WM_COMMAND or WM_SYSCOMMAND message
This makes it look like 'accelerator keys' are not something like AutoHotkey's hotkeys, but actually a special way of handling standard Windows (keypress related) messages, and one could instead handle the messages manually.

I first looked into this years ago, around when I first started using AutoHotkey's GUIs. I wanted a GUI to have a 'soft' or traditional 'shortcut key' ... not using an AutoHotkey hotkey, so that the user could override it ... using AutoHotkey.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)

14 Apr 2017, 19:55

My script isn't working so far, I'm not sure what the problem is, if someone knows what's awry. [EDIT: It's almost there now.]

I have managed to handle the keypress messages manually, but so far TranslateAccelerator appears only to be working with WM_CHAR with Shift+E, but not Ctrl+Q or Alt+W. Also, it seems to be triggered incorrectly by Shift+Q.

I've added ACCEL and MSG here:
list of structs with parameters (sizes and types) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 59#p142659

Code: Select all

#SingleInstance force

OnMessage(0x111, "WM_COMMAND")
OnMessage(0x112, "WM_SYSCOMMAND")
;OnMessage(0x100, "WM_KEYDOWN")
;OnMessage(0x104, "WM_SYSKEYDOWN")
OnMessage(0x102, "WM_CHAR")
OnMessage(0x106, "WM_SYSCHAR")

;Virtual-Key Codes (Windows)
;https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx

;A-Z 0x41-0x5A (65-90)
;ctrl+q should launch command 123
;alt+w should launch command 124
;shift+e should launch command 125

;FALT := 0x10
;FCONTROL := 0x8
;FSHIFT := 0x4
vCount := 3
VarSetCapacity(ACCEL, 6*vCount, 0)
vOffset := 0 ;Ctrl+Q
NumPut(0x8, ACCEL, vOffset, "UChar") ;fVirt
NumPut(0x51, ACCEL, vOffset+2, "UShort") ;key
NumPut(123, ACCEL, vOffset+4, "UShort") ;cmd
vOffset += 6 ;Alt+W
NumPut(0x10, ACCEL, vOffset, "UChar") ;fVirt
NumPut(0x57, ACCEL, vOffset+2, "UShort") ;key
NumPut(124, ACCEL, vOffset+4, "UShort") ;cmd
vOffset += 6 ;Shift+E
NumPut(0x4, ACCEL, vOffset, "UChar") ;fVirt
NumPut(0x45, ACCEL, vOffset+2, "UShort") ;key
NumPut(125, ACCEL, vOffset+4, "UShort") ;cmd

hAccel := DllCall("CreateAcceleratorTable", Ptr,&ACCEL, Int,vCount, Ptr)

Gui, Add, Text,, Please enter your name:
Gui, Add, Edit
Gui, Show
return

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

WM_COMMAND(wParam, lParam, uMsg, hWnd)
{
	wParam2 := 0xFFFF & wParam
	if wParam2 in 123,124,125
		MsgBox, % "[" wParam2 "] " wParam " " lParam " " uMsg
	wParam := "0x" Format("{:X}", wParam)
	lParam := "0x" Format("{:X}", lParam)
	uMsg := "0x" Format("{:X}", uMsg)
	;MsgBox, % wParam " " lParam " " uMsg
}

WM_SYSCOMMAND(wParam, lParam, uMsg, hWnd)
{
	wParam2 := 0xFFFF & wParam
	if wParam2 in 123,124,125
		MsgBox, % "[" wParam2 "] " wParam " " lParam " " uMsg
	wParam := "0x" Format("{:X}", wParam)
	lParam := "0x" Format("{:X}", lParam)
	uMsg := "0x" Format("{:X}", uMsg)
	;MsgBox, % wParam " " lParam " " uMsg
}

WM_KEYDOWN(wParam, lParam, uMsg, hWnd)
{
	global hAccel
	;MsgBox, % wParam " " lParam " " uMsg
	VarSetCapacity(MSG, A_PtrSize=8?48:28, 0)
	NumPut(hWnd, MSG, 0, "Ptr") ;hwnd
	NumPut(uMsg, MSG, A_PtrSize=8?8:4, "UInt") ;message
	NumPut(wParam, MSG, A_PtrSize=8?16:8, "UPtr") ;wParam
	NumPut(lParam, MSG, A_PtrSize=8?24:12, "Ptr") ;lParam
	DllCall("TranslateAccelerator", Ptr,A_ScriptHwnd, Ptr,hAccel, Ptr,&MSG)

	vCtrlIsDown := GetKeyState("Ctrl", "p")
	vAltIsDown := GetKeyState("Alt", "p")
	vShiftIsDown := GetKeyState("Shift", "p")
	DetectHiddenWindows, On
	if vCtrlIsDown && (wParam = 0x51) ;Ctrl+Q
		PostMessage, 0x111, 123, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
	if vAltIsDown && (wParam = 0x57) ;Alt+W
		PostMessage, 0x111, 124, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
	if vShiftIsDown && (wParam = 0x45) ;Shift+E
		PostMessage, 0x111, 125, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
}

WM_SYSKEYDOWN(wParam, lParam, uMsg, hWnd)
{
	global hAccel
	;MsgBox, % wParam " " lParam " " uMsg
	VarSetCapacity(MSG, A_PtrSize=8?48:28, 0)
	NumPut(hWnd, MSG, 0, "Ptr") ;hwnd
	NumPut(uMsg, MSG, A_PtrSize=8?8:4, "UInt") ;message
	NumPut(wParam, MSG, A_PtrSize=8?16:8, "UPtr") ;wParam
	NumPut(lParam, MSG, A_PtrSize=8?24:12, "Ptr") ;lParam
	DllCall("TranslateAccelerator", Ptr,A_ScriptHwnd, Ptr,hAccel, Ptr,&MSG)

	vCtrlIsDown := GetKeyState("Ctrl", "p")
	vAltIsDown := GetKeyState("Alt", "p")
	vShiftIsDown := GetKeyState("Shift", "p")
	DetectHiddenWindows, On
	if vCtrlIsDown && (wParam = 0x51) ;Ctrl+Q
		PostMessage, 0x111, 123, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
	if vAltIsDown && (wParam = 0x57) ;Alt+W
		PostMessage, 0x111, 124, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
	if vShiftIsDown && (wParam = 0x45) ;Shift+E
		PostMessage, 0x111, 125, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
}

WM_CHAR(wParam, lParam, uMsg, hWnd)
{
	global hAccel
	;MsgBox, % wParam " " lParam " " uMsg
	VarSetCapacity(MSG, A_PtrSize=8?48:28, 0)
	NumPut(hWnd, MSG, 0, "Ptr") ;hwnd
	NumPut(uMsg, MSG, A_PtrSize=8?8:4, "UInt") ;message
	NumPut(wParam, MSG, A_PtrSize=8?16:8, "UPtr") ;wParam
	NumPut(lParam, MSG, A_PtrSize=8?24:12, "Ptr") ;lParam
	DllCall("TranslateAccelerator", Ptr,A_ScriptHwnd, Ptr,hAccel, Ptr,&MSG)

;	vCtrlIsDown := GetKeyState("Ctrl", "p")
;	vAltIsDown := GetKeyState("Alt", "p")
;	vShiftIsDown := GetKeyState("Shift", "p")
;	DetectHiddenWindows, On
;	if vCtrlIsDown && (wParam = 0x51) ;Ctrl+Q
;		PostMessage, 0x111, 123, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
;	if vAltIsDown && (wParam = 0x57) ;Alt+W
;		PostMessage, 0x111, 124, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
;	if vShiftIsDown && (wParam = 0x45) ;Shift+E
;		PostMessage, 0x111, 125, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
}

WM_SYSCHAR(wParam, lParam, uMsg, hWnd)
{
	global hAccel
	;MsgBox, % wParam " " lParam " " uMsg
	VarSetCapacity(MSG, A_PtrSize=8?48:28, 0)
	NumPut(hWnd, MSG, 0, "Ptr") ;hwnd
	NumPut(uMsg, MSG, A_PtrSize=8?8:4, "UInt") ;message
	NumPut(wParam, MSG, A_PtrSize=8?16:8, "UPtr") ;wParam
	NumPut(lParam, MSG, A_PtrSize=8?24:12, "Ptr") ;lParam
	DllCall("TranslateAccelerator", Ptr,A_ScriptHwnd, Ptr,hAccel, Ptr,&MSG)

;	vCtrlIsDown := GetKeyState("Ctrl", "p")
;	vAltIsDown := GetKeyState("Alt", "p")
;	vShiftIsDown := GetKeyState("Shift", "p")
;	DetectHiddenWindows, On
;	if vCtrlIsDown && (wParam = 0x51) ;Ctrl+Q
;		PostMessage, 0x111, 123, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
;	if vAltIsDown && (wParam = 0x57) ;Alt+W
;		PostMessage, 0x111, 124, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
;	if vShiftIsDown && (wParam = 0x45) ;Shift+E
;		PostMessage, 0x111, 125, , , % "ahk_id " A_ScriptHwnd ;WM_COMMAND
}

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

;OnExit
;DllCall("DestroyAcceleratorTable", Ptr,hAccel)
Last edited by jeeswg on 15 Apr 2017, 08:21, edited 6 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)

14 Apr 2017, 22:38

Re. beeps: OK, finally with the keywords 'gui disable beep' I found a good result:

c++ - How to turn off beeping when pressing ENTER on a single-line EDIT control under Windows CE? - Stack Overflow
http://stackoverflow.com/questions/3588 ... trol-under

Code: Select all

vFunc := "BeepDelay"
;vFunc := "BlockChars"
;vFunc := "BlockCtrlAndAlt"
OnMessage(0x102, vFunc) ;WM_CHAR
OnMessage(0x106, vFunc) ;WM_SYSCHAR

Gui, Add, Text,, Please enter your name:
Gui, Add, Edit
Gui, Show
return

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

;delayed beep
BeepDelay(wParam, lParam, uMsg, hWnd)
{
	if GetKeyState("Ctrl", "p") || GetKeyState("LAlt", "p")
		Sleep 3000
}

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

;disabled beep
;typing characters into control is blocked
BlockChars(wParam, lParam, uMsg, hWnd)
{
	return 0
}

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

;letters by themselves are let through
;ctrl+letter/alt+letter are blocked (prevent beeps)
BlockCtrlAndAlt(wParam, lParam, uMsg, hWnd)
{
	if GetKeyState("Ctrl", "p") || GetKeyState("LAlt", "p")
		return 0
}
E.g. in Notepad. to trigger a beep, press Ctrl+E, because in English language versions of Notepad, Ctrl+E is not defined to do anything. Although it might be used for something in some other languages.

Of course, you could block Ctrl+E in Notepad, using AutoHotkey, like so, to avoid the beep:

Code: Select all

#IfWinActive, ahk_class Notepad
^e::
return
#IfWinActive
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)  Topic is solved

01 Jun 2018, 16:05

- OK, I've finally got this working, it only took a year.
- I'm very surprised that I couldn't find any information for this on the AutoHotkey forums. The distinction between what I call 'hard hotkeys' and 'soft hotkeys' is fundamental.
- There are system-wide hotkeys like Win+R ('hard hotkeys'), but there are also per-process accelerator keys like Ctrl+S to save a file in Notepad ('soft hotkeys').
- AutoHotkey hotkeys are hard hotkeys, if you create a GUI, you could create a hard hotkey to add in functionality like Ctrl+O/S (open/save), and Ctrl+X/C/V (cut/copy/paste) when the GUI is the active window. However, if you then create another AutoHotkey script, which you would like to use to override the hotkeys of your GUI, you can have a problem of clashing hotkeys, and which script takes priority.
- This is why it's good to create soft hotkeys, as Notepad would do, this way there is no clash. You make your GUI AutoHotkey-friendly, with no clash of hotkeys.
- You can create a list of accelerator keys for the process one by one via CreateAcceleratorTable, or you can load a list from a resource via LoadAccelerators. E.g. if you look at
C:\Windows\System32\en-US\notepad.exe.mui (Windows 7)
or
C:\Windows\System32\notepad.exe (Windows XP)
you will see various resources. The example below uses CreateAcceleratorTable. There is then an accelerator table for the process, a list of accelerator keys (soft hotkeys), and a command ID for each one.
- We create a function, and use OnMessage to tell the tell script to run that function any time a WM_KEYDOWN or WM_SYSKEYDOWN message is detected, the information that the function receives is passed on to TranslateAccelerator. If the details passed to TranslateAccelerator match an accelerator key in the accelerator table, a WM_COMMAND message is sent to the script, that message will contain the command ID. Note also that if a match is found, TranslateAccelerator returns a nonzero value, if no match is found, it returns zero.
- (Thus some key presses were sent, the script has detected this, and so an action can be taken.)
- Those key presses will still be sent to the window unless we block them, we can block them by using 'return 0' within the functions (or function) that handle(s) WM_KEYDOWN and WM_SYSKEYDOWN.

Code: Select all

;create accelerator keys ('soft hotkeys' that AutoHotkey can override)

#SingleInstance force

;oArray expects a hotkey: any combination of ^ ! + followed by an upper/lower case letter
;oArray expects an ID: e.g. the ID in a context menu tells the program what action to perform
oArray := []
oArray.Push(["^q", 123]) ;Ctrl+Q should launch command 123
oArray.Push(["!w", 124]) ;Alt+W should launch command 124
oArray.Push(["+e", 125]) ;Shift+E should launch command 125

OnExit("ExitFunc")
OnMessage(0x111, "WM_COMMAND")
OnMessage(0x100, "KeyDown") ;WM_KEYDOWN := 0x100
OnMessage(0x104, "KeyDown") ;WM_SYSKEYDOWN := 0x104

;Virtual-Key Codes (Windows)
;https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
;FCONTROL := 0x8 ;FSHIFT := 0x4
;FALT := 0x10 ;FVIRTKEY := 0x1
vCount := oArray.Length()
VarSetCapacity(ACCEL, 6*vCount, 0)
vOffset := 0
oID := []
for _, oValue in oArray
{
	vKey := oValue.1
	vID := oValue.2
	oID[vID] := 1
	vMod := 0x1 | 0x8*!!InStr(vKey, "^") | 0x4*!!InStr(vKey, "+") | 0x10*!!InStr(vKey, "!")
	vLetter := Format("{:U}", SubStr(vKey, StrLen(vKey)))
	NumPut(vMod, &ACCEL, vOffset, "UChar") ;fVirt
	NumPut(Ord(vLetter), &ACCEL, vOffset+2, "UShort") ;key
	NumPut(vID, &ACCEL, vOffset+4, "UShort") ;cmd
	vOffset += 6
}

hAccel := DllCall("user32\CreateAcceleratorTable", Ptr,&ACCEL, Int,vCount, Ptr)
Gui, Add, Text,, Please enter your name:
Gui, Add, Edit
Gui, Show
return

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

WM_COMMAND(wParam, lParam, uMsg, hWnd)
{
	global oID
	wParam2 := 0xFFFF & wParam
	if oID.HasKey(wParam2)
		MsgBox, % A_ThisFunc "`r`n" "[" wParam2 "] " wParam " " lParam " " uMsg
}

KeyDown(wParam, lParam, uMsg, hWnd)
{
	global hAccel
	VarSetCapacity(MSG, A_PtrSize=8?48:28, 0)
	NumPut(hWnd, &MSG, 0, "Ptr") ;hwnd
	NumPut(uMsg, &MSG, A_PtrSize=8?8:4, "UInt") ;message
	NumPut(wParam, &MSG, A_PtrSize=8?16:8, "UPtr") ;wParam
	NumPut(lParam, &MSG, A_PtrSize=8?24:12, "Ptr") ;lParam
	if DllCall("user32\TranslateAccelerator", Ptr,A_ScriptHwnd, Ptr,hAccel, Ptr,&MSG)
		return 0
}

ExitFunc()
{
	global hAccel
	DllCall("user32\DestroyAcceleratorTable", Ptr,hAccel)
}

;==================================================
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey)

01 Jun 2018, 16:54

Various bits of information that I found.

IS HACCEL PTR OR INT?
- This suggests Int (32-bit):
About Keyboard Accelerators (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
A unique 32-bit handle (HACCEL) identifies each table.
- This suggests Ptr (64-bit/32-bit depending on the process), since hAccel and hWnd are both of type HANDLE, and hWnd is known to be a Ptr:
Windows Data Types (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
HACCEL
A handle to an accelerator table.
This type is declared in WinDef.h as follows:
typedef HANDLE HACCEL;
...
HWND
A handle to a window.
This type is declared in WinDef.h as follows:
typedef HANDLE HWND;
HANDLING KEY UP/DOWN AND HANDLING ALT
- WM_KEYDOWN is used to detect most key presses, but WM_SYSKEYDOWN is needed if Alt is involved.
- When the function that handled WM_KEYDOWN/WM_SYSKEYDOWN, passed information to TranslateAccelerator, WM_COMMAND was sent to the script if a matching accelerator key was found.
- When the function that handled WM_KEYUP/WM_SYSKEYUP, passed information to TranslateAccelerator, WM_COMMAND was never sent to the script.
- Btw combinations with the Alt key sent WM_COMMAND messages, not WM_SYSCOMMAND messages.

HANDLING WM_KEYDOWN
- MSDN says this:
WM_KEYDOWN message (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
An application should return zero if it processes this message.
- For the script above, a function that receives a WM_KEYDOWN/WM_SYSKEYDOWN message, should return 0, to prevent those keys being sent to the window.

THE VALUE OF FVIRTKEY AND ITS EFFECT
- MSDN says this:
ACCEL structure (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
FVIRTKEY
TRUE
The key member specifies a virtual-key code. If this flag is not specified, key is assumed to specify a character code.
- I tried FVIRTKEY := 0x1, and that worked, but TRUE could be interpreted as -1 i.e. 0xFFFFFFFF or 0xFFFFFFFFFFFFFFFF.
- You use FVIRTKEY to specify a VK code not a Unicode character code. This has relevance re. upper/lower case. E.g. the 'A/a' key has a VK code of 0x41, but a character code of 0x41 ('A') or 0x61 ('a').
- Another quote on the same issue:
About Keyboard Accelerators (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
Thus, using the ASCII "C" character defines the accelerator as ALT+C rather than ALT+c.
TIDYING UP
- My script destroys the accelerator table at the end, but maybe it doesn't have to:
About Keyboard Accelerators (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
The system automatically destroys accelerator tables loaded by LoadAccelerators or created by CreateAcceleratorTable. However, an application can free resources while it is running by destroying accelerator tables no longer needed by calling the DestroyAcceleratorTable function.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Smile_, teadrinker and 55 guests