Question about SC_RSHIFT in \source\keyboard_mouse.h

Discuss Autohotkey related topics here. Not a place to share code.
Forum rules
Discuss Autohotkey related topics here. Not a place to share code.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Question about SC_RSHIFT in \source\keyboard_mouse.h

30 May 2022, 07:27

Code: Select all

#define SC_RSHIFT 0x136 // Must be extended, at least on WinXP, or there will be problems, e.g. SetModifierLRState().
src
Why does it need to be extended? I couldn't find any direct reference to SC_RSHIFT in SetModifierLRState.

I ask because I get problem when calling GetKeyNameText. Example:

Code: Select all

GetKeyNameText getkeysc('RShift') ; fails

GetKeyNameText(sc) {
	static SC_RSHIFT := 0x136
	lParam := (sc << 16) 
	;if sc == SC_RSHIFT 
	;	lParam &= ~(1 << 24) ; doing this works
	
	varsetstrcapacity &lpString, cchSize := 512
	if !dllcall('User32.dll\GetKeyNameText', 'int', lParam, 'str', lpString, 'int', cchSize, 'int')
		throw oserror(,, 'GetKeyNameText failed.')
	return lpString
}
Edit, some more hints in :arrow: sc_to_vk

Code: Select all

// RShift doesn't have the 0xE0 prefix but has KBDEXT.  The US layout sample says
// "Right-hand Shift key must have KBDEXT bit set", so it's probably always set.
// KbdEdit seems to follow this rule when VK_RSHIFT is assigned to a non-ext key.
// It's definitely possible to assign RShift a different VK, but 1) it can't be
// done with MSKLC, and 2) KbdEdit clears the ext flag (so aSC != SC_RSHIFT).
case SC_RSHIFT:

Cheers.
lexikos
Posts: 9632
Joined: 30 Sep 2013, 04:07
Contact:

Re: Question about SC_RSHIFT in \source\keyboard_mouse.h

07 Jun 2022, 04:11

Having the 0x100 bit set won't work with any Win32 functions; that's just AutoHotkey's method of encoding the "extended" flag, and allowing scan codes to be used to index into certain internal arrays.

Code: Select all

	// MapVirtualKey() does *not* include 0xE0 in HIBYTE if key is extended.  In case it ever
	// does in the future (or if event.scanCode ever does), force sc to be an 8-bit value
	// so that it's guaranteed consistent and to ensure it won't exceed SC_MAX (which might cause
	// array indexes to be out-of-bounds).  The 9th bit is later set to 1 if the key is extended:
	sc &= 0xFF;
	// Change sc to be extended if indicated.  But avoid doing so for VK_RSHIFT, which is
	// apparently considered extended by the API when it shouldn't be.  Update: Well, it looks like
	// VK_RSHIFT really is an extended key, at least on WinXP (and probably be extension on the other
	// NT based OSes as well).  What little info I could find on the 'net about this is contradictory,
	// but it's clear that some things just don't work right if the non-extended scan code is sent.  For
	// example, the shift key will appear to get stuck down in the foreground app if the non-extended
	// scan code is sent with VK_RSHIFT key-up event:
	if ((event.flags & LLKHF_EXTENDED)) // && vk != VK_RSHIFT)
		sc |= 0x100;
The SC_ constants need to correspond to the values sc can have after this point, within the keyboard hook.

In other words, the real scan code and extended-key flag are translated into an AutoHotkey-SC value, so when you call any Win32 function generally you need to translate the AutoHotkey-SC value back to a real scan code and extended-key flag (although sometimes you just need to discard the flag).

I don't see anything in SetModifierLRState that would be dependent on the scan code or extended-key flag.

I think at the hardware or driver level, scan codes are always 8-bit plus a possible 0xE0 prefix, but for the keyboard hook there are some exceptions:

Code: Select all

// The system injects events with these scan codes:
//  - For Shift-up prior to a Numpad keydown or keyup if Numlock is on and Shift is down;
//    e.g. to translate Shift+Numpad1 to unshifted-NumpadEnd.
//  - For Shift-down prior to a non-Numpad keydown if a Numpad key is still held down
//    after the above; e.g. for Shift+Numpad1+Esc.
//  - For LCtrl generated by AltGr.
// Note that the system uses the normal scan codes (0x2A or 0x36) for Shift-down following
// the Numpad keyup if no other keys were pushed.  Our hook filters out the second byte to
// simplify the code, so these values can only be found in KBDLLHOOKSTRUCT::scanCode.
// Find "fake shift-key events" for older and more detailed comments.
// Note that 0x0200 corresponds to SCANCODE_SIMULATED in kbd.h (DDK).
#define SC_FAKE_FLAG 0x200
#define SC_FAKE_LSHIFT 0x22A
#define SC_FAKE_RSHIFT 0x236 // This is the actual scancode received by the hook, excluding the 0x100 we add for "extended" keys.
// Testing with the KbdEdit Demo preview mode indicates that AltGr will send this SC
// even if the VK assigned to 0x1D is changed.  It is a combination of SCANCODE_CTRL
// and SCANCODE_SIMULATED, which are defined in kbd.h (Windows DDK).
#define SC_FAKE_LCTRL 0x21D
You won't see these in KeyHistory because the hook code filters out the upper bytes early.

Also, VK_PACKET overloads the "scan code" field to contain a 16-bit character code.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Question about SC_RSHIFT in \source\keyboard_mouse.h

07 Jun 2022, 04:37

Thank you, that is interesting. It makes me appreciate the work which has been put into this program even more :)

I also conclude (again) that I will just handle SC_RSHIFT as a special case in my function above.

Cheers.
lexikos
Posts: 9632
Joined: 30 Sep 2013, 04:07
Contact:

Re: Question about SC_RSHIFT in \source\keyboard_mouse.h

07 Jun 2022, 21:33

Why? Shouldn't you be handling all extended keys the same way?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Question about SC_RSHIFT in \source\keyboard_mouse.h

08 Jun 2022, 01:52

For general purpose, I'd probably just take lParam as input, and leave it to the caller. But my use case only take input from getkeysc(...). I only found 'RShift' to be a problem. Compare,

Code: Select all


msgbox getkeynametext(GetKeySC('delete'))
msgbox getkeynametext(GetKeySC('NumpadDel'))
; Toggle lParam comment:
GetKeyNameText(sc) {
	lParam := (sc << 16) 
	
	; remove extended:
	;lParam &= ~(1 << 24) 
	
	varsetstrcapacity &lpString, cchSize := 512
	if !dllcall('User32.dll\GetKeyNameText', 'int', lParam, 'str', lpString, 'int', cchSize, 'int')
		throw oserror(,, 'GetKeyNameText failed.')
	return lpString
}
Cheers.
lexikos
Posts: 9632
Joined: 30 Sep 2013, 04:07
Contact:

Re: Question about SC_RSHIFT in \source\keyboard_mouse.h

08 Jun 2022, 03:53

Aha, the extended-key flag coincides with the 0x100 bit of the AutoHotkey "scancode". There are other APIs which aren't so convenient, so you need to "split" the scancode and set the flag explicitly. My point was that all extended keys need the flag set (not removed), but apparently I was wrong and GetKeyNameText needs it to be unset for RShift. I didn't interpret your previous comment the right way.

Code: Select all

	;if sc == SC_RSHIFT 
	;	lParam &= ~(1 << 24) ; doing this works

Return to “General Discussion”

Who is online

Users browsing this forum: No registered users and 11 guests