【问题标题】:GLUT key down and key up on CTRL keyGLUT 键按下并按下 CTRL 键
【发布时间】:2010-08-26 19:16:38
【问题描述】:

我找到了很多关于使用 GLUT 来检测是否使用 GLUT_ACTIVE_CTRL 宏按下了 Ctrl 键的信息。显然,这个宏只在键盘或鼠标回调函数中有效。我需要知道在我的主循环中的某个点是否按下了 Ctrl 键,但是 GLUT_ACTIVE_CTRL 在这种情况下似乎不起作用。

那么,有没有一种方法可以以独立于平台的 GLUT 方式检测 Ctrl 键上的键向上和向下键事件(无需键入任何其他键)?

编辑:当按下 Ctrl 键时,不会触发键盘回调(至少对于默认设置)。这是基本问题,我只能测试在按下另一个键时是否按下了 Ctrl 键,从而触发键盘回调。

我的设置是这样的:

// ... in main function:
glutKeyboardFunc(keyboard);

//later in the code: 

void keyboard(unsigned char key, int _x, int _y)
{
    printf("keydown \n");

    if (glutGetModifiers() == GLUT_ACTIVE_CTRL) {
            printf("control key is pressed.\n");
    }
    //etc.

当我按下任何普通字符时,“keydown”会打印到标准输出。当我按下 Ctrl 键时,什么也没有发生。如果我按 Ctrl+C,“keydown 控制键被按下”。被打印出来了。

但是,在我的主循环中,我添加了:

if (glutGetModifiers() == GLUT_ACTIVE_CTRL) {
    printf("Control key down.\n");
} else {
    printf("Control key up.\n");
}

它总是打印“控制键向上”。不管我是否按下 Ctrl 键。

【问题讨论】:

    标签: opengl glut keyboard-events


    【解决方案1】:

    不使用 GLUT as specced。您不妨查看GLFW

    【讨论】:

      【解决方案2】:

      我在我的 GLUT 应用程序中使用了一个临时工具来解决问题。 GLUT 的问题在于它只实现了 CtrlShiftAlt 按下 together 与另一个键。但是,该解决方法模拟了一个在后台运行的连续按下的键,GLUT 可以使用修饰键拾取该键。

      您可以通过使用windows.h 库中的SendInput 来实现这个想法。

      UINT WINAPI SendInput(_In_  UINT nInputs, _In_  LPINPUT pInputs, _In_  int cbSize); 
      

      模拟硬件按键。这与glutGetModifiers() 回调一起使用。您可以在循环的背景中运行模拟的击键,例如在您的 idlefunc 中,您需要选择一个在程序中不经常使用的密钥。

      要了解它是如何工作的,首先在您的 GLUT 代码中使用标准回调,以通过 glutGetModifiers() 识别 Ctrl 键。

      bool CTRLpress=0;
      
      int checkModifiers(void)
          {
          int mod_key = glutGetModifiers();
          if (mod_key!= 0)
              {
              if (mod_key == GLUT_ACTIVE_CTRL)
                  {
                  CTRLpress=1;
                  }
              return 1;
              }
          else if (CTRLpress)
              {
              CTRLpress=0;
              return 1;
              }
          return 0;
          }
      

      声明并定义变量 bool CTRLpress 全局或在您自己的键盘类中作为 CTRL 键被按下 (1) 或释放 (0) 的指示器。然后确保像往常一样从您的glutKeyboardFunc 中调用函数 checkModifiers()。

      现在在您的主代码中启动一个 INPUT 对象:

      #define WINVER 0x0500  // Note: This needs to be put in here as SendInput is compatible from Windows 2000 onwards
      #include <windows.h>
      
      INPUT permkey; //optionally you could also use a pointer to INPUT with *premkey here
      
      int main (int argc, char **argv)
            {
            permkey.type = INPUT_KEYBOARD;
            permkey.ki.wVk = 0x42; // keystroke 'b' but check out all ASCII codes 
            permkey.ki.time = 0;
            permkey.ki.dwFlags = 0; 
      
            //your code here
            }
      

      最后,在您的glutIdleFunc 中添加一个模拟连续按下按键的常规调用:

      void idle()
          {
          SendInput(1, &permkey, sizeof(INPUT));
          // your other code here
          }
      

      当单独按下 Ctrl 而不按下任何其他键时,代码触发 CTRLpressed 为 1。或者,当释放 CTRLpressed 时(您可能希望进一步扩展自己的修饰符类以克服其他 GLUT缺点 - 例如难以检测 Ctrl +Number。)

      这对我很有效,除了必须牺牲一把钥匙之外,我没有遇到任何其他缺点。

      【讨论】:

        【解决方案3】:

        在事件处理程序中记录键的设置。然后,您可以公开该存储以从您的主循环中读取。

        【讨论】:

        • 这不适用于使用典型方法 (glutKeyboardFunc(callback)) 的 GLUT,因为不会为修饰键触发键盘回调。
        • 至少,它们在默认设置中不会被触发。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多