我正在尝试通过
PostMessage()
合成击键,我需要生成相应的 lParam
。
KeyStrokeMessage
结构。
这是代码:
///-------------------------------------------------------------------------------------------
/// KeystrokeMessage/KeyLParam struct
///-------------------------------------------------------------------------------------------
typedef struct KeystrokeMessage
{
unsigned RepeatCount : 16;
unsigned ScanCode : 8;
unsigned ExtendedFlag : 1;
unsigned Reserved : 4;
unsigned ContextCode : 1;
unsigned PreviousKeyState : 1;
unsigned TransitionState : 1;
} KeyLParam;
///-------------------------------------------------------------------------------------------
/// GetKeyMessageLPARAM:
/// Creates an LPARAM for key messages.
///-------------------------------------------------------------------------------------------
LPARAM GetKeyMessageLPARAM(unsigned aVKey, bool aIsDown, bool aIsSystem)
{
KeyLParam lp;
UINT sc = MapVirtualKeyA(aVKey, MAPVK_VK_TO_VSC_EX);
lp.RepeatCount = 1;
lp.ScanCode = LOBYTE(sc);
lp.ExtendedFlag = (HIBYTE(sc) == 0xE0 || HIBYTE(sc) == 0xE1) ? 1 : 0;
lp.Reserved = 0;
lp.ContextCode = aIsSystem ? 1 : 0;
lp.PreviousKeyState = aIsDown ? 0 : 1;
lp.TransitionState = aIsDown ? 0 : 1;
return *(LPARAM*)&lp;
}
我还拦截了真正的击键来了解我做错了什么。
具体来说,我正在尝试合成一个“向上箭头”按键,即
VK_UP
。
“向上箭头”的真实消息将
wParam
设置为 VK_UP
,并且 lParam
具有设置了扩展标志的扫描码 0x48
。
正品按键参考:
扫描码应为
0xE048
(带有扩展标志)。
但是,
MapVirtualKey()
返回 72 (0x48
),因此它不会设置 ExtendedFlag
。
MSDN 上的文档指出它将返回扩展标志。
我已经尝试过
MapVirtualKey()
和MapVirtualKeyEx()
。
在
Ex
版本中,我尝试了实际的键盘布局,以及将其保留为 0。
我使用了正确的地图类型
MAPVK_VK_TO_VSC_EX
,但我也尝试了MAPVK_VK_TO_VSC
,看看结果是否有不同。
我什至尝试走相反的路线,从实际的扫描码开始,将其转换为虚拟按键,然后再转换回扫描码。 我得到了正确的
VK_UP
但再次尝试从中获取扫描码时返回了错误的密钥。
无论输入如何,我都不会返回扩展标志,即使它应该有一个。我还通过 https://kbdlayout.info 交叉引用了我的键盘布局,它应该是
0xE048
。
如何接收来自
MapVirtualKeyA()
的扩展标志?
回答我自己的问题,以防其他人偶然发现这种行为:
返回值在技术上是正确的,因为MapVirtualKey
默认为非扩展版本,并且
VK_UP
由“向上箭头”(
0xE048
)键和小键盘8(
0x48
)共享。其他一些按键也共享相同的虚拟按键代码,例如
VK_RETURN
。供参考,
VK_NUMPAD8
存在,并且其他一些布局可能正在使用它,但在本例中不是。