根据MSDN wparam应该持有密钥代码.问题是,当按下shift时,代码为16(VK_SHIFT),但我需要区分VK_LSHIFT和VK_RSHIFT.
对于VK_CONTROL,似乎有一个解决方法:
if(wParam == VK_CONTROL) {
if ( lParam&EXTENDED_KEYMASK )
wParam = VK_RCONTROL;
else
wParam = VK_LCONTROL;
}
Run Code Online (Sandbox Code Playgroud)
但是,同样不适用于VK_SHIFT:
if(wparam == VK_SHIFT) {
if ( lParam&EXTENDED_KEYMASK )
wParam = VK_RSHIFT;
else
wParam = VK_LSHIFT;
}
Run Code Online (Sandbox Code Playgroud)
在后一个例子中,它将始终假设LSHIFT.
Mic*_*urr 14
要区分Shift,Ctrl或Alt键的左右版本,必须使用MapVirtualKey()
随虚拟键消息传递的lParam中的函数或"扩展键"位.以下函数将为您执行该转换 - 只需从消息中传入虚拟键代码和lParam,然后您将根据需要返回左/右特定虚拟键代码:
WPARAM MapLeftRightKeys( WPARAM vk, LPARAM lParam)
{
WPARAM new_vk = vk;
UINT scancode = (lParam & 0x00ff0000) >> 16;
int extended = (lParam & 0x01000000) != 0;
switch (vk) {
case VK_SHIFT:
new_vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
break;
case VK_CONTROL:
new_vk = extended ? VK_RCONTROL : VK_LCONTROL;
break;
case VK_MENU:
new_vk = extended ? VK_RMENU : VK_LMENU;
break;
default:
// not a key we map from generic to left/right specialized
// just return it.
new_vk = vk;
break;
}
return new_vk;
}
Run Code Online (Sandbox Code Playgroud)
如果传入的虚拟键码不是映射到左/右版本的虚拟键码,则原始键码将不加改变地传回.因此,只要需要区分左右变体,就可以通过函数运行WM_KEYDOWN
/ WM_KEYUP
/ WM_SYSKEYDOWN
/ WM_SYSKEYUP
message参数.
通过使用MapVirtualKey()
你不需要知道关于左移和右移扫描码的传说是0x2a和0x36 - API负责这个细节.如果他们确实发生了不同的事情(并非真正发生的事情),Windows将负责处理它,而不是你.
因此,在您的WM_KEYDOWN
/ WM_KEYUP
/ WM_SYSKEYDOWN
/ WM_SYSKEYUP
处理程序中,您只需添加一行代码,如下所示:
wparam = MapLeftRightKeys(wparam, lparam);
Run Code Online (Sandbox Code Playgroud)
并且其余的代码可以作用于左/右特定的VK代码,就好像系统消息首先将它们提供给您一样.
你的问题背后有古老的历史.原始IBM PC键盘没有正确的Alt和Ctrl键.它们稍后在扩展键盘布局上添加,键盘控制器将它们与0xe0前缀一起发送到扫描代码,以将它们区分为扩展键.但原始键盘布局总是有两个移位键,因此它们有自己的非扩展扫描码.这就是为什么你的代码不起作用的原因.
大卫的答案是解决问题的好方法.但实际上你可以从消息中得到它,那些扫描代码是由Windows徽标要求一成不变的.在lParam中可用,左移键具有扫描码42,右移键为54.不幸的是,在它们的windows标题中没有#define,这使得它变得难看.
呼叫GetKeyState
通过VK_LSHIFT
或VK_RSHIFT
.
归档时间: |
|
查看次数: |
4006 次 |
最近记录: |