我在处理PostMessage()的参数LPARAM时遇到麻烦。
这是使用PostMessage()输入字母z的广泛示例:
PostMessage(handle, WM_KEYDOWN, 0x5A, 0x002C0001) // key down for z
PostMessage(handle, WM_KEYUP, 0x5A, 0xC02C0001) // key up for z
对于LPARAM,按下键时到达“ 0x002C0001”,而按下键时到达“ 0xC02C0001”的公式是什么?我想为所有密钥复制它。 是否可以创建两个函数,例如CreateLPARAM_KeyDown()和CreateLPARAM_KeyUp(),您只需在其中传递扫描代码(或者更好的是,独立于设备的虚拟密钥代码),然后它们返回LPARAM?
使用keybd_event()会容易得多,您只需将dwFlags参数保留为0即可,而将KEYEVENTF_KEYUP保留为向上键,但是该窗口必须具有焦点,而我要发送的窗口位于后台,因此keybd_event ()和SendInput()在我的情况下没有用。
答案 0 :(得分:3)
LPARAM
和WPARAM
的含义因要处理的特定消息而异。这就是为什么PostMessage
的文档不能太具体地说明这些参数,而仅说明:
其他特定于消息的信息。
在两者上。要确切了解每条消息的含义,您需要查看该消息的文档。
对于您要询问的消息,WM_KEYUP
和WM_KEYDOWN
,LPARAM
的值表示:
重复计数,扫描代码,扩展键标志,上下文代码,先前的键状态标志和过渡状态标志,如下表所示。 (来源#1,#2)
Bits Meaning
0-15 The repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key.
16-23 The scan code. The value depends on the OEM.
24 Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
25-28 Reserved; do not use.
29 The context code.
30 The previous key state.
31 The transition state.
让我们看看您的WM_KEYDOWN
LPARAM
的位:
0x002C0001
0b0000000000101100000000000001
设置的位分别是21、19、18和0。这告诉我们:
重复次数为1
其余位是z
的扫描代码,显然是0b00101100或0x2C。
WM_KEYUP
消息的LPARAM
值是0xC02C0001,仅在最高有效字节时有所不同,从而给我们:
0b1100000000101100000000000001
因此,这里唯一的区别是先前状态和过渡状态位均为1,无论如何,这保证了WM_KEYUP
消息。
关于您的其他问题:
是否可以创建两个函数,例如CreateLPARAM_KeyDown()和CreateLPARAM_KeyUp(),您只需在其中传递扫描代码?
好的。查看MapVirtualKey
以确定如何从键控代码中获取扫描代码,并使用位操作从中构造一个32位LPARAM
以及您从上表中了解的有关位的所有其他信息必须为这些消息设置。您将需要使用移位和其他位操作来完成此操作,因为扫描代码是作为8位字节LPARAM
的一部分存储的单个8位字节。
答案 1 :(得分:0)
我建议为此目的使用SendInput API。
因此,您只需要填写相应的KEYBDINPUT结构即可。
答案 2 :(得分:0)
是否可以创建两个函数,例如CreateLPARAM_KeyDown()和CreateLPARAM_KeyUp(),您只需在其中传递扫描代码(或者更好的是,独立于设备的虚拟密钥代码),然后它们返回LPARAM?
尝试这样的事情:
std::pair<USHORT, bool> VirtualKeyToScanCode(UINT VirtualKey)
{
USHORT ScanCode = (USHORT) MapVirtualKey(VirtualKey, MAPVK_VK_TO_VSC);
bool IsExtended = false;
// because MapVirtualKey strips the extended bit for some keys
switch (VirtualKey)
{
case VK_RMENU: case VK_RCONTROL:
case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys
case VK_PRIOR: case VK_NEXT: // page up and page down
case VK_END: case VK_HOME:
case VK_INSERT: case VK_DELETE:
case VK_DIVIDE: // numpad slash
case VK_NUMLOCK:
{
IsExtended = true;
break;
}
}
return std::make_pair(ScanCode, IsExtended);
}
LPARAM CreateLPARAM_KeyUpDown(UINT VirtualKey, USHORT RepeatCount, bool TransitionState, bool PreviousKeyState, bool ContextCode)
{
std::pair<USHORT, bool> ScanCode = VirtualKeyToScanCode(VirtualKey);
return (
(LPARAM(TransitionState) << 31) |
(LPARAM(PreviousKeyState) << 30) |
(LPARAM(ContextCode) << 29) |
(LPARAM(ScanCode.second) << 24) |
(LPARAM(ScanCode.first) << 16) |
LPARAM(RepeatCount)
);
}
LPARAM CreateLPARAM_KeyDown(UINT VirtualKey, USHORT RepeatCount = 1)
{
return CreateLPARAM_KeyUpDown(VirtualKey, RepeatCount, false, RepeatCount > 1, false);
}
LPARAM CreateLPARAM_KeyUp(UINT VirtualKey)
{
return CreateLPARAM_KeyUpDown(VirtualKey, 1, true, true, false);
}