2011-05-04 21 views
2

我正在一個項目中需要識別物理鍵的位置,控制,Shift和Winkey。我需要知道鍵盤中的每個Left或Right的位置。如何使用Qt和X11events識別KeyPress事件?

爲此,我需要使用Qt處理X11events和WinEvents。我在Windows中做得非常好,忘記了關於Alt Gr的可怕部分,我還無法處理。在Linux中我試圖做同樣的:

#include "mainwindow.h" 
#include "ui_mainwindow.h" 
#if WIN32 
#include <windows.h> 
#else 
#include <X11/XKBlib.h> 
#ifdef KeyPress 
const int XKeyPress = KeyPress; 
#undef KeyPress 
#endif  
#endif 

#include "main.h" 
#include <QFile> 
#include <QDebug> 
#include <QX11Info> 


#if WIN32 
bool MainWindow::winEvent(MSG* msg, long* result) 
{ 
    if(msg->message == WM_KEYDOWN || msg->message == WM_HOTKEY) 
    { 
     SHORT state; 
     switch(msg->wParam) 
     { 

     case VK_CONTROL: 
      // the Alt Gr is handled using Ctrl+Alt+Shift (I Guess) 
      state = GetKeyState(VK_SHIFT); 
      if(state == TRUE) 
       keyPressEvent(msg->wParam, "Key_AltGr"); 
      else{ 
       state = GetKeyState(VK_LCONTROL); 
       if(state & VK_LCONTROL) 
        keyPressEvent(msg->wParam, "Key_ControlL"); 
       else 
        keyPressEvent(msg->wParam, "Key_ControlR"); 
      } 
      break;    
     case VK_SHIFT: 
      state = GetKeyState(VK_LSHIFT); 
      if(state & VK_LSHIFT) 
       keyPressEvent(msg->wParam, "Key_ShiftL"); 
      else 
       keyPressEvent(msg->wParam, "Key_ShiftR"); 
      break;    
     case VK_MENU:// alt 
      state = GetKeyState(VK_SHIFT); 
      if(state == TRUE) 
       keyPressEvent(msg->wParam, "Key_AltGr"); 
      break; 

     case VK_SNAPSHOT: 
      keyPressEvent(msg->wParam, "Key_Print"); 
      break; 

     default: 
      return false; 
     } 

     return true;   
    } 
    return false; 
} 
#else 
bool MainWindow::x11Event(XEvent *xe) 
{ 
    switch(xe->type) 
    { 
    case XKeyPress: 
     switch (xe->xkey.keycode) 
     { 
     case 37://Control_L 
      keyPressEvent(xe->xkey.keycode, "Key_ControlL"); 
      break; 
     case 105://Control_R 
      keyPressEvent(xe->xkey.keycode, "Key_ControlR"); 
      break; 
     case 50://Shift_L 
      keyPressEvent(xe->xkey.keycode, "Key_ShiftL"); 
      break; 
     case 62://Shift_R 
      keyPressEvent(xe->xkey.keycode, "Key_ShiftR"); 
      break; 
     case 133://Super_L 
      keyPressEvent(xe->xkey.keycode, "Key_SuperL"); 
      break; 
     case 134://Super_R 
      keyPressEvent(xe->xkey.keycode, "Key_SuperR"); 
      break; 
     default: 
      return false; 
     } 
     return true; 
     break; 
    } 
    return false; 
} 
#endif 

的方法x11Event的情況下XKeyPress(在調試模式下,它的2)是永遠不會滿意,但如果你看看:

grep KeyPress /usr/include/X11/X.h 
#define KeyPressMask   (1L<<0) 
#define KeyPress  2 

常數是正確的但類型永遠不會相等2.如果我將常量XKeyPress更改爲28,看起來像

[email protected]:release$ grep 28 /usr/include/X11/X.h 
#define PropertyNotify  28 
#define FirstExtensionError 128 

很好。

Thx

+0

有時你會說'KeyPress'(沒有X),有時候你會說'XKeyPress' - 你確定你在正確的地方有正確的名字嗎? – alanc 2011-05-04 23:50:52

+0

我不理解你的評論。我在需要的地方使用XKeyPress。 #ifdef KeyPress const int XKeyPress = KeyPress; #undef KeyPress //(在這個undef後我不能單獨使用KeyPress) – MaikoID 2011-05-06 19:34:35

回答

1

我不知道爲什麼它不起作用。沒有x11事件在KeyPress之後被調用,只有當我移動鼠標時纔會調用它,然後所有未激發的事件被觸發。爲此,我收到了同一類型的所有事件,我無法比較每種類型,因爲它是垃圾。

要解決此我實現了QAbstractEventDispatcher在這mainwindow.cpp的所有者(這是從我的按鍵事件接收器) 的main.cpp

QAbstractEventDispatcher *evInstance = QAbstractEventDispatcher::instance(0); 
    evInstance->setEventFilter((QAbstractEventDispatcher::EventFilter) MainWindow::customEventFilter); 

    MainWindow *w = new MainWindow(program.getLayoutFile(), program.getUnicode()); 
    w->show(); 
    a.exec(); 

但該方法customEventFilter中的main.cpp需要是靜態的。我改變了我的所有代碼,但工作,customEventFilter可以接收所有系統範圍的事件,在Linux或Windows。

再見。