如何以编程方式切换大写字母锁或防止键盘切换它

How can I programmatically toggle CAPSLOCK or prevent it from being toggled by the keyboard?

本文关键字:键盘 大写字母 编程 方式切      更新时间:2023-10-16

我有一个用C++编写并在Windows上运行的程序。我允许用户键绑定 CAPSLOCK 键,所以如果他们每次按下它时,他们不会也切换他们的 CAPSLOCK 状态,那就太好了。

我发现没有办法"捕获"CAPSLOCK消息以防止它被Windows注册。似乎当我收到WM_KEYDOWN消息时,键盘上的指示灯已经切换。

我确实找到了这个建议的代码:

keybd_event( VK_CAPITAL, 0x3a, KEYEVENTF_EXTENDEDKEY, 0 );
keybd_event( VK_CAPITAL, 0x3a, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 );

但是,它不起作用。它有点导致指示灯闪烁,似乎根本不影响 CAPSLOCK 状态。

按相反的顺序尝试:

keybd_event( VK_CAPITAL, 0x3a, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 );
keybd_event( VK_CAPITAL, 0x3a, KEYEVENTF_EXTENDEDKEY, 0 );

虽然通过keybd_event的假键盘事件可以切换状态,但如果你真的想阻止capslock,你需要做一个键盘过滤器钩子,唉

   HHOOK hhkLowLevelKybd  = SetWindowsHookEx( WH_KEYBOARD_LL,
                                              LowLevelKeyboardProc,
                                              NULL,
                                              0 );

然后在你的钩子中,你寻找并且不传递你想要阻止的键,就像这样(片段改编自工作代码,但未经测试):

LRESULT CALLBACK LowLevelKeyboardProc( int nCode,
                                       WPARAM wParam,
                                       LPARAM lParam)
{
  int fEatKeystroke = 0;
  
  if (nCode == HC_ACTION) 
      {
      // Get hook struct
      PKBDLLHOOKSTRUCT p = ( PKBDLLHOOKSTRUCT ) lParam;
      switch (wParam)
         {
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
            if (p->vkCode == VK_CAPITAL)
                fEatKeystroke =1;
        }
    }
  // Did we trap a key??
   return( fEatKeystroke ? 1 : CallNextHookEx( NULL, nCode, wParam, lParam ));
}// End LowLevelKeyboardProc