【问题标题】:C/C++ Get key pressed without pollingC/C++ 无需轮询即可按下按键
【发布时间】:2014-05-12 02:50:26
【问题描述】:

我正在学习 C/C++,我最近创建了一个键盘记录器,主要是因为它是一个简单的学习项目。所以我要做的是在循环中运行GetAsynKeyState() 来检查密钥的状态。当我检查 CPU 时,它的周期会飙升,因为很好;我一直在运行一个带有条件的循环。

在我看来做这种事情很浪费,我敢肯定更大更高级的软件不会使用这种技术。

问题:当按键被按下时,内核会创建一个中断来处理。我的程序可以像内核一样被“唤醒”,还是唯一的解决方案是不断检查按键?专业应用程序会做什么?

此外,编程语言实现了事件侦听器,它们如何实现这一点,轮询或其他一些魔法?

【问题讨论】:

  • 哪个操作系统?我假设这是 Windows。
  • 当您使用GetAsyncKeyState 进行投票时,您是否在两次检查之间睡觉?
  • @minitech 是的,我让它睡着了。我的问题仍然是关于应用程序将使用的程序类型,因为在我看来,持续循环有点疯狂,你不觉得吗?
  • 根据我的经验,在那里稍作睡眠将 CPU 使用率降低到几乎为零。无论如何,钩子会给你一个基于事件的解决方案。
  • @boompow,有很多信息:msdn.microsoft.com/en-us/library/windows/desktop/… 低级键盘挂钩是最容易开始使用键盘输入的全局类型,因为它不需要 DLL。

标签: c++ c io kernel polling


【解决方案1】:

钩子是一种在事件到达应用程序之前拦截事件(例如鼠标操作或击键)的机制。接收这些事件的函数称为过滤函数(参见下面的MyKbHook。)为了被调用,过滤函数必须附加到 Windows 挂钩(参见下面的 SetWindowHookEx)。

如果挂钩附加了多个过滤器函数,Windows 会维护一系列过滤器函数。最后安装的函数在链的开头,第一个安装的函数在链的末尾。

LRESULT CALLBACK MyKbHook( int nId, WPARAM wParam, LPARAM lParam )
{
   char keyPressed;

   KBDLLHOOKSTRUCT *pHook = (KBDLLHOOKSTRUCT *)lParam;
   switch( wParam )
   {
       case WM_KEYUP: 
       {
          //get the key code
          keyPressed= (char)pHook->vkCode;
       }
       break;
       default:
           return CallNextHookEx( NULL, nId, wParam, lParam );
       break;
   }


   //Each function implementing a hook must call the next hook in chain before return
   return CallNextHookEx( NULL, nId, wParam, lParam);
}


// somewhere in your code where you want start tracking
    HHOOK hookKB = SetWindowHookEx(WH_KEYBOARD,(HOOKPROC)MyKbHook,hInst,0);

// when you do not need it anymore you SHOULD uninstall it
 UnhookWindowsHookEx(hookKB);

【讨论】:

    【解决方案2】:

    专业方法因操作系统而异。在 Windows 上,您只需使用 Windows 消息。根据您的具体需要,您通常会使用WM_CHARWM_KEYDOWN。比钩子容易得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-04
      • 2016-12-05
      • 2018-09-04
      • 2013-12-15
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多