Qt鼠标键盘事件监听

ops/2024/9/20 7:26:04/ 标签: qt, 计算机外设, stm32

普通的程序中. 鼠标事件监听
要监听鼠标事件,你可以使用QMouseEvent类,它提供了多种类型的鼠标事件,如QMouseEvent::MouseButtonPress、QMouseEvent::MouseButtonRelease、QMouseEvent::MouseMove等。
但是离开程序后就很难监听到,这里就需要用到系统api来监听
请添加图片描述

#include "globalkeyevent.h"
#if defined(Q_OS_WIN)
#include "Windows.h"
#include <QDebug>
#include <QKeyEvent>enum WindowsNativeModifiers {ShiftLeft            = 0x00000001,ControlLeft          = 0x00000002,AltLeft              = 0x00000004,MetaLeft             = 0x00000008,ShiftRight           = 0x00000010,ControlRight         = 0x00000020,AltRight             = 0x00000040,MetaRight            = 0x00000080,CapsLock             = 0x00000100,NumLock              = 0x00000200,ScrollLock           = 0x00000400,ExtendedKey          = 0x01000000,// Convenience mappingsShiftAny             = 0x00000011,ControlAny           = 0x00000022,AltAny               = 0x00000044,MetaAny              = 0x00000088,LockAny              = 0x00000700
};// 值的含义:
// 0           = 字符输出键,需要键盘驱动程序映射
// Key_unknown = 未知虚拟密钥,无法转换,忽略
// Windows 到 Qt::Key映射表,在"D:\Qt\Qt5.12.5\5.12.5\Src\qtbase\src\plugins\platforms\windows\qwindowskeymapper.cpp"中有
static const uint KeyTbl[] = { // Keyboard mapping table// Dec |  Hex | Windows Virtual keyQt::Key_unknown,    //   0   0x00Qt::Key_unknown,    //   1   0x01   VK_LBUTTON          | Left mouse buttonQt::Key_unknown,    //   2   0x02   VK_RBUTTON          | Right mouse buttonQt::Key_Cancel,     //   3   0x03   VK_CANCEL           | Control-Break processingQt::Key_unknown,    //   4   0x04   VK_MBUTTON          | Middle mouse buttonQt::Key_unknown,    //   5   0x05   VK_XBUTTON1         | X1 mouse buttonQt::Key_unknown,    //   6   0x06   VK_XBUTTON2         | X2 mouse buttonQt::Key_unknown,    //   7   0x07   -- unassigned --Qt::Key_Backspace,  //   8   0x08   VK_BACK             | BackSpace keyQt::Key_Tab,        //   9   0x09   VK_TAB              | Tab keyQt::Key_unknown,    //  10   0x0A   -- reserved --Qt::Key_unknown,    //  11   0x0B   -- reserved --Qt::Key_Clear,      //  12   0x0C   VK_CLEAR            | Clear keyQt::Key_Return,     //  13   0x0D   VK_RETURN           | Enter keyQt::Key_unknown,    //  14   0x0E   -- unassigned --Qt::Key_unknown,    //  15   0x0F   -- unassigned --Qt::Key_Shift,      //  16   0x10   VK_SHIFT            | Shift keyQt::Key_Control,    //  17   0x11   VK_CONTROL          | Ctrl keyQt::Key_Alt,        //  18   0x12   VK_MENU             | Alt keyQt::Key_Pause,      //  19   0x13   VK_PAUSE            | Pause keyQt::Key_CapsLock,   //  20   0x14   VK_CAPITAL          | Caps-LockQt::Key_unknown,    //  21   0x15   VK_KANA / VK_HANGUL | IME Kana or Hangul modeQt::Key_unknown,    //  22   0x16   -- unassigned --Qt::Key_unknown,    //  23   0x17   VK_JUNJA            | IME Junja modeQt::Key_unknown,    //  24   0x18   VK_FINAL            | IME final modeQt::Key_unknown,    //  25   0x19   VK_HANJA / VK_KANJI | IME Hanja or Kanji modeQt::Key_unknown,    //  26   0x1A   -- unassigned --Qt::Key_Escape,     //  27   0x1B   VK_ESCAPE           | Esc keyQt::Key_unknown,    //  28   0x1C   VK_CONVERT          | IME convertQt::Key_unknown,    //  29   0x1D   VK_NONCONVERT       | IME non-convertQt::Key_unknown,    //  30   0x1E   VK_ACCEPT           | IME acceptQt::Key_Mode_switch,//  31   0x1F   VK_MODECHANGE       | IME mode change requestQt::Key_Space,      //  32   0x20   VK_SPACE            | SpacebarQt::Key_PageUp,     //  33   0x21   VK_PRIOR            | Page Up keyQt::Key_PageDown,   //  34   0x22   VK_NEXT             | Page Down keyQt::Key_End,        //  35   0x23   VK_END              | End keyQt::Key_Home,       //  36   0x24   VK_HOME             | Home keyQt::Key_Left,       //  37   0x25   VK_LEFT             | Left arrow keyQt::Key_Up,         //  38   0x26   VK_UP               | Up arrow keyQt::Key_Right,      //  39   0x27   VK_RIGHT            | Right arrow keyQt::Key_Down,       //  40   0x28   VK_DOWN             | Down arrow keyQt::Key_Select,     //  41   0x29   VK_SELECT           | Select keyQt::Key_Printer,    //  42   0x2A   VK_PRINT            | Print keyQt::Key_Execute,    //  43   0x2B   VK_EXECUTE          | Execute keyQt::Key_Print,      //  44   0x2C   VK_SNAPSHOT         | Print Screen keyQt::Key_Insert,     //  45   0x2D   VK_INSERT           | Ins keyQt::Key_Delete,     //  46   0x2E   VK_DELETE           | Del keyQt::Key_Help,       //  47   0x2F   VK_HELP             | Help key0,                  //  48   0x30   (VK_0)              | 0 key0,                  //  49   0x31   (VK_1)              | 1 key0,                  //  50   0x32   (VK_2)              | 2 key0,                  //  51   0x33   (VK_3)              | 3 key0,                  //  52   0x34   (VK_4)              | 4 key0,                  //  53   0x35   (VK_5)              | 5 key0,                  //  54   0x36   (VK_6)              | 6 key0,                  //  55   0x37   (VK_7)              | 7 key0,                  //  56   0x38   (VK_8)              | 8 key0,                  //  57   0x39   (VK_9)              | 9 keyQt::Key_unknown,    //  58   0x3A   -- unassigned --Qt::Key_unknown,    //  59   0x3B   -- unassigned --Qt::Key_unknown,    //  60   0x3C   -- unassigned --Qt::Key_unknown,    //  61   0x3D   -- unassigned --Qt::Key_unknown,    //  62   0x3E   -- unassigned --Qt::Key_unknown,    //  63   0x3F   -- unassigned --Qt::Key_unknown,    //  64   0x40   -- unassigned --0,                  //  65   0x41   (VK_A)              | A key0,                  //  66   0x42   (VK_B)              | B key0,                  //  67   0x43   (VK_C)              | C key0,                  //  68   0x44   (VK_D)              | D key0,                  //  69   0x45   (VK_E)              | E key0,                  //  70   0x46   (VK_F)              | F key0,                  //  71   0x47   (VK_G)              | G key0,                  //  72   0x48   (VK_H)              | H key0,                  //  73   0x49   (VK_I)              | I key0,                  //  74   0x4A   (VK_J)              | J key0,                  //  75   0x4B   (VK_K)              | K key0,                  //  76   0x4C   (VK_L)              | L key0,                  //  77   0x4D   (VK_M)              | M key0,                  //  78   0x4E   (VK_N)              | N key0,                  //  79   0x4F   (VK_O)              | O key0,                  //  80   0x50   (VK_P)              | P key0,                  //  81   0x51   (VK_Q)              | Q key0,                  //  82   0x52   (VK_R)              | R key0,                  //  83   0x53   (VK_S)              | S key0,                  //  84   0x54   (VK_T)              | T key0,                  //  85   0x55   (VK_U)              | U key0,                  //  86   0x56   (VK_V)              | V key0,                  //  87   0x57   (VK_W)              | W key0,                  //  88   0x58   (VK_X)              | X key0,                  //  89   0x59   (VK_Y)              | Y key0,                  //  90   0x5A   (VK_Z)              | Z keyQt::Key_Meta,       //  91   0x5B   VK_LWIN             | Left Windows  - MS Natural kbdQt::Key_Meta,       //  92   0x5C   VK_RWIN             | Right Windows - MS Natural kbdQt::Key_Menu,       //  93   0x5D   VK_APPS             | Application key-MS Natural kbdQt::Key_unknown,    //  94   0x5E   -- reserved --Qt::Key_Sleep,      //  95   0x5F   VK_SLEEPQt::Key_0,          //  96   0x60   VK_NUMPAD0          | Numeric keypad 0 keyQt::Key_1,          //  97   0x61   VK_NUMPAD1          | Numeric keypad 1 keyQt::Key_2,          //  98   0x62   VK_NUMPAD2          | Numeric keypad 2 keyQt::Key_3,          //  99   0x63   VK_NUMPAD3          | Numeric keypad 3 keyQt::Key_4,          // 100   0x64   VK_NUMPAD4          | Numeric keypad 4 keyQt::Key_5,          // 101   0x65   VK_NUMPAD5          | Numeric keypad 5 keyQt::Key_6,          // 102   0x66   VK_NUMPAD6          | Numeric keypad 6 keyQt::Key_7,          // 103   0x67   VK_NUMPAD7          | Numeric keypad 7 keyQt::Key_8,          // 104   0x68   VK_NUMPAD8          | Numeric keypad 8 keyQt::Key_9,          // 105   0x69   VK_NUMPAD9          | Numeric keypad 9 keyQt::Key_Asterisk,   // 106   0x6A   VK_MULTIPLY         | Multiply keyQt::Key_Plus,       // 107   0x6B   VK_ADD              | Add keyQt::Key_unknown,    // 108   0x6C   VK_SEPARATOR        | Separator key (locale-dependent)Qt::Key_Minus,      // 109   0x6D   VK_SUBTRACT         | Subtract keyQt::Key_unknown,    // 110   0x6E   VK_DECIMAL          | Decimal key (locale-dependent)Qt::Key_Slash,      // 111   0x6F   VK_DIVIDE           | Divide keyQt::Key_F1,         // 112   0x70   VK_F1               | F1 keyQt::Key_F2,         // 113   0x71   VK_F2               | F2 keyQt::Key_F3,         // 114   0x72   VK_F3               | F3 keyQt::Key_F4,         // 115   0x73   VK_F4               | F4 keyQt::Key_F5,         // 116   0x74   VK_F5               | F5 keyQt::Key_F6,         // 117   0x75   VK_F6               | F6 keyQt::Key_F7,         // 118   0x76   VK_F7               | F7 keyQt::Key_F8,         // 119   0x77   VK_F8               | F8 keyQt::Key_F9,         // 120   0x78   VK_F9               | F9 keyQt::Key_F10,        // 121   0x79   VK_F10              | F10 keyQt::Key_F11,        // 122   0x7A   VK_F11              | F11 keyQt::Key_F12,        // 123   0x7B   VK_F12              | F12 keyQt::Key_F13,        // 124   0x7C   VK_F13              | F13 keyQt::Key_F14,        // 125   0x7D   VK_F14              | F14 keyQt::Key_F15,        // 126   0x7E   VK_F15              | F15 keyQt::Key_F16,        // 127   0x7F   VK_F16              | F16 keyQt::Key_F17,        // 128   0x80   VK_F17              | F17 keyQt::Key_F18,        // 129   0x81   VK_F18              | F18 keyQt::Key_F19,        // 130   0x82   VK_F19              | F19 keyQt::Key_F20,        // 131   0x83   VK_F20              | F20 keyQt::Key_F21,        // 132   0x84   VK_F21              | F21 keyQt::Key_F22,        // 133   0x85   VK_F22              | F22 keyQt::Key_F23,        // 134   0x86   VK_F23              | F23 keyQt::Key_F24,        // 135   0x87   VK_F24              | F24 keyQt::Key_unknown,    // 136   0x88   -- unassigned --Qt::Key_unknown,    // 137   0x89   -- unassigned --Qt::Key_unknown,    // 138   0x8A   -- unassigned --Qt::Key_unknown,    // 139   0x8B   -- unassigned --Qt::Key_unknown,    // 140   0x8C   -- unassigned --Qt::Key_unknown,    // 141   0x8D   -- unassigned --Qt::Key_unknown,    // 142   0x8E   -- unassigned --Qt::Key_unknown,    // 143   0x8F   -- unassigned --Qt::Key_NumLock,    // 144   0x90   VK_NUMLOCK          | Num Lock keyQt::Key_ScrollLock, // 145   0x91   VK_SCROLL           | Scroll Lock key// Fujitsu/OASYS kbd --------------------0, //Qt::Key_Jisho, // 146   0x92   VK_OEM_FJ_JISHO     | 'Dictionary' key ///              VK_OEM_NEC_EQUAL  = key on numpad on NEC PC-9800 kbdQt::Key_Massyo,     // 147   0x93   VK_OEM_FJ_MASSHOU   | 'Unregister word' keyQt::Key_Touroku,    // 148   0x94   VK_OEM_FJ_TOUROKU   | 'Register word' key0, //Qt::Key_Oyayubi_Left,//149   0x95  VK_OEM_FJ_LOYA  | 'Left OYAYUBI' key0, //Qt::Key_Oyayubi_Right,//150  0x96  VK_OEM_FJ_ROYA  | 'Right OYAYUBI' keyQt::Key_unknown,    // 151   0x97   -- unassigned --Qt::Key_unknown,    // 152   0x98   -- unassigned --Qt::Key_unknown,    // 153   0x99   -- unassigned --Qt::Key_unknown,    // 154   0x9A   -- unassigned --Qt::Key_unknown,    // 155   0x9B   -- unassigned --Qt::Key_unknown,    // 156   0x9C   -- unassigned --Qt::Key_unknown,    // 157   0x9D   -- unassigned --Qt::Key_unknown,    // 158   0x9E   -- unassigned --Qt::Key_unknown,    // 159   0x9F   -- unassigned --Qt::Key_Shift,      // 160   0xA0   VK_LSHIFT           | Left Shift keyQt::Key_Shift,      // 161   0xA1   VK_RSHIFT           | Right Shift keyQt::Key_Control,    // 162   0xA2   VK_LCONTROL         | Left Ctrl keyQt::Key_Control,    // 163   0xA3   VK_RCONTROL         | Right Ctrl keyQt::Key_Alt,        // 164   0xA4   VK_LMENU            | Left Menu keyQt::Key_Alt,        // 165   0xA5   VK_RMENU            | Right Menu keyQt::Key_Back,       // 166   0xA6   VK_BROWSER_BACK     | Browser Back keyQt::Key_Forward,    // 167   0xA7   VK_BROWSER_FORWARD  | Browser Forward keyQt::Key_Refresh,    // 168   0xA8   VK_BROWSER_REFRESH  | Browser Refresh keyQt::Key_Stop,       // 169   0xA9   VK_BROWSER_STOP     | Browser Stop keyQt::Key_Search,     // 170   0xAA   VK_BROWSER_SEARCH   | Browser Search keyQt::Key_Favorites,  // 171   0xAB   VK_BROWSER_FAVORITES| Browser Favorites keyQt::Key_HomePage,   // 172   0xAC   VK_BROWSER_HOME     | Browser Start and Home keyQt::Key_VolumeMute, // 173   0xAD   VK_VOLUME_MUTE      | Volume Mute keyQt::Key_VolumeDown, // 174   0xAE   VK_VOLUME_DOWN      | Volume Down keyQt::Key_VolumeUp,   // 175   0xAF   VK_VOLUME_UP        | Volume Up keyQt::Key_MediaNext,  // 176   0xB0   VK_MEDIA_NEXT_TRACK | Next Track keyQt::Key_MediaPrevious, //177 0xB1   VK_MEDIA_PREV_TRACK | Previous Track keyQt::Key_MediaStop,  // 178   0xB2   VK_MEDIA_STOP       | Stop Media keyQt::Key_MediaPlay,  // 179   0xB3   VK_MEDIA_PLAY_PAUSE | Play/Pause Media keyQt::Key_LaunchMail, // 180   0xB4   VK_LAUNCH_MAIL      | Start Mail keyQt::Key_LaunchMedia,// 181   0xB5   VK_LAUNCH_MEDIA_SELECT Select Media keyQt::Key_Launch0,    // 182   0xB6   VK_LAUNCH_APP1      | Start Application 1 keyQt::Key_Launch1,    // 183   0xB7   VK_LAUNCH_APP2      | Start Application 2 keyQt::Key_unknown,    // 184   0xB8   -- reserved --Qt::Key_unknown,    // 185   0xB9   -- reserved --0,                  // 186   0xBA   VK_OEM_1            | ';:' for US0,                  // 187   0xBB   VK_OEM_PLUS         | '+' any country0,                  // 188   0xBC   VK_OEM_COMMA        | ',' any country0,                  // 189   0xBD   VK_OEM_MINUS        | '-' any country0,                  // 190   0xBE   VK_OEM_PERIOD       | '.' any country0,                  // 191   0xBF   VK_OEM_2            | '/?' for US0,                  // 192   0xC0   VK_OEM_3            | '`~' for USQt::Key_unknown,    // 193   0xC1   -- reserved --Qt::Key_unknown,    // 194   0xC2   -- reserved --Qt::Key_unknown,    // 195   0xC3   -- reserved --Qt::Key_unknown,    // 196   0xC4   -- reserved --Qt::Key_unknown,    // 197   0xC5   -- reserved --Qt::Key_unknown,    // 198   0xC6   -- reserved --Qt::Key_unknown,    // 199   0xC7   -- reserved --Qt::Key_unknown,    // 200   0xC8   -- reserved --Qt::Key_unknown,    // 201   0xC9   -- reserved --Qt::Key_unknown,    // 202   0xCA   -- reserved --Qt::Key_unknown,    // 203   0xCB   -- reserved --Qt::Key_unknown,    // 204   0xCC   -- reserved --Qt::Key_unknown,    // 205   0xCD   -- reserved --Qt::Key_unknown,    // 206   0xCE   -- reserved --Qt::Key_unknown,    // 207   0xCF   -- reserved --Qt::Key_unknown,    // 208   0xD0   -- reserved --Qt::Key_unknown,    // 209   0xD1   -- reserved --Qt::Key_unknown,    // 210   0xD2   -- reserved --Qt::Key_unknown,    // 211   0xD3   -- reserved --Qt::Key_unknown,    // 212   0xD4   -- reserved --Qt::Key_unknown,    // 213   0xD5   -- reserved --Qt::Key_unknown,    // 214   0xD6   -- reserved --Qt::Key_unknown,    // 215   0xD7   -- reserved --Qt::Key_unknown,    // 216   0xD8   -- unassigned --Qt::Key_unknown,    // 217   0xD9   -- unassigned --Qt::Key_unknown,    // 218   0xDA   -- unassigned --0,                  // 219   0xDB   VK_OEM_4            | '[{' for US0,                  // 220   0xDC   VK_OEM_5            | '\|' for US0,                  // 221   0xDD   VK_OEM_6            | ']}' for US0,                  // 222   0xDE   VK_OEM_7            | ''"' for US0,                  // 223   0xDF   VK_OEM_8Qt::Key_unknown,    // 224   0xE0   -- reserved --Qt::Key_unknown,    // 225   0xE1   VK_OEM_AX           | 'AX' key on Japanese AX kbdQt::Key_unknown,    // 226   0xE2   VK_OEM_102          | "<>" or "\|" on RT 102-key kbdQt::Key_unknown,    // 227   0xE3   VK_ICO_HELP         | Help key on ICOQt::Key_unknown,    // 228   0xE4   VK_ICO_00           | 00 key on ICOQt::Key_unknown,    // 229   0xE5   VK_PROCESSKEY       | IME Process keyQt::Key_unknown,    // 230   0xE6   VK_ICO_CLEAR        |Qt::Key_unknown,    // 231   0xE7   VK_PACKET           | Unicode char as keystrokesQt::Key_unknown,    // 232   0xE8   -- unassigned --// Nokia/Ericsson definitions ---------------Qt::Key_unknown,    // 233   0xE9   VK_OEM_RESETQt::Key_unknown,    // 234   0xEA   VK_OEM_JUMPQt::Key_unknown,    // 235   0xEB   VK_OEM_PA1Qt::Key_unknown,    // 236   0xEC   VK_OEM_PA2Qt::Key_unknown,    // 237   0xED   VK_OEM_PA3Qt::Key_unknown,    // 238   0xEE   VK_OEM_WSCTRLQt::Key_unknown,    // 239   0xEF   VK_OEM_CUSELQt::Key_unknown,    // 240   0xF0   VK_OEM_ATTNQt::Key_unknown,    // 241   0xF1   VK_OEM_FINISHQt::Key_unknown,    // 242   0xF2   VK_OEM_COPYQt::Key_unknown,    // 243   0xF3   VK_OEM_AUTOQt::Key_unknown,    // 244   0xF4   VK_OEM_ENLWQt::Key_unknown,    // 245   0xF5   VK_OEM_BACKTABQt::Key_unknown,    // 246   0xF6   VK_ATTN             | Attn keyQt::Key_unknown,    // 247   0xF7   VK_CRSEL            | CrSel keyQt::Key_unknown,    // 248   0xF8   VK_EXSEL            | ExSel keyQt::Key_unknown,    // 249   0xF9   VK_EREOF            | Erase EOF keyQt::Key_Play,       // 250   0xFA   VK_PLAY             | Play keyQt::Key_Zoom,       // 251   0xFB   VK_ZOOM             | Zoom keyQt::Key_unknown,    // 252   0xFC   VK_NONAME           | ReservedQt::Key_unknown,    // 253   0xFD   VK_PA1              | PA1 keyQt::Key_Clear,      // 254   0xFE   VK_OEM_CLEAR        | Clear key0
};static inline quint32 winceKeyBend(quint32 keyCode)
{return KeyTbl[keyCode];
}/*** @brief  获取是否按下键盘修饰键,例如Ctrl、shirt等* @return*/
static inline Qt::KeyboardModifiers queryKeyboardModifiers()
{Qt::KeyboardModifiers modifiers = Qt::NoModifier;if (GetKeyState(VK_SHIFT) < 0)modifiers |= Qt::ShiftModifier;if (GetKeyState(VK_CONTROL) < 0)modifiers |= Qt::ControlModifier;if (GetKeyState(VK_MENU) < 0)modifiers |= Qt::AltModifier;if (GetKeyState(VK_LWIN) < 0 || GetKeyState(VK_RWIN) < 0)modifiers |= Qt::MetaModifier;return modifiers;
}static uchar g_buffer[256];
/*** @brief            将VK转换为Qt键代码或unicode字符* @param vk* @param scancode* @param g_buffer* @param isDeadkey* @return*/
static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, bool *isDeadkey = nullptr)
{Q_ASSERT(vk > 0 && vk < 256);GetKeyboardState(g_buffer);   // // 将 256 个虚拟密钥的状态复制到指定的缓冲区。
//    qDebug() <<"vk " << (g_buffer[vk] & 0x80);g_buffer[VK_LWIN    ] = 0;g_buffer[VK_RWIN    ] = 0;g_buffer[VK_CAPITAL ] = 0;g_buffer[VK_NUMLOCK ] = 0;g_buffer[VK_SCROLL  ] = 0;// 始终为0,因为我们只会更改其他版本g_buffer[VK_RSHIFT  ] = 0;g_buffer[VK_RCONTROL] = 0;g_buffer[VK_LMENU   ] = 0;   // 使用右Alt,因为左Ctrl+右Alt被视为AltGraphg_buffer[VK_CONTROL ] = 0;   // 需要将ctrl键清空,否则按住Ctrl + 字母键会出现无法返回正确值的情况quint32 code = 0;QChar unicodeBuffer[5];int res = ToUnicode(vk, scancode, g_buffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);// 使用Ctrl修饰符时,ToUnicode不会返回正确的值。为了分配右键,如果上一次调用失败,则仅删除该函数的控制修饰符。if (res == 0 && g_buffer[VK_CONTROL]){const unsigned char controlState = g_buffer[VK_CONTROL];g_buffer[VK_CONTROL] = 0;res = ToUnicode(vk, scancode, g_buffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);g_buffer[VK_CONTROL] = controlState;}if (res){code = unicodeBuffer[0].toUpper().unicode();   // 将字符转换位Qt::Key值}// Qt::Key_*的编码不低于0x20,因此请重试,DEL键(0x7f)使用正确的Qt::Key_ codeif (code < 0x20 || code == 0x7f) // Handles res==0 too{code = winceKeyBend(vk);}if (isDeadkey){*isDeadkey = (res == -1);}return code == Qt::Key_unknown ? 0 : code;
}static uchar g_keyState[256];
/*** @brief           获取当前按下键的字符* @param vk        要转换的虚拟密钥代码* @param scancode  要转换的密钥的硬件扫描代码* @return*/
static inline QString getKeyText(quint32 vk, quint32 scancode)
{GetKeyboardState(g_keyState);                                     // 将 256 个虚拟密钥的状态复制到指定的缓冲区。wchar_t newKey[3] = {0};// 将指定的虚拟键代码和键盘状态转换为相应的一个或多个 Unicode 字符。int ret = ToUnicode(vk,           // 要转换的虚拟密钥代码scancode,     // 要转换的密钥的硬件扫描代码g_keyState,   // 指向包含当前键盘状态的 256 字节数组的指针。数组中的每个元素(字节)都包含一个键的状态。newKey,       // 接收转换后的一个或多个 Unicode 字符的缓冲区3,            // 参数指向的缓冲区的大小(以字符为单位)0);           // 函数的行为。0:则菜单处于活动状态; 2,则不会更改键盘状态(Windows 10 版本 1607 及更高版本)if (ret == 1)      // 1:一个字符被写入 newKey{QChar uch = QChar(newKey[0]);return  uch;}else        // 无法获取到字符{return QString();}
}/*** @brief        获取本机修改器值* @param flags* @return*/
static quint32 getNativeModifiers(quint32 flags)
{quint32 nModifiers = 0;// 将本机修改器映射到某些位表示nModifiers |= (GetKeyState(VK_LSHIFT  ) & 0x80 ? ShiftLeft : 0);nModifiers |= (GetKeyState(VK_RSHIFT  ) & 0x80 ? ShiftRight : 0);nModifiers |= (GetKeyState(VK_LCONTROL) & 0x80 ? ControlLeft : 0);nModifiers |= (GetKeyState(VK_RCONTROL) & 0x80 ? ControlRight : 0);nModifiers |= (GetKeyState(VK_LMENU   ) & 0x80 ? AltLeft : 0);nModifiers |= (GetKeyState(VK_RMENU   ) & 0x80 ? AltRight : 0);nModifiers |= (GetKeyState(VK_LWIN    ) & 0x80 ? MetaLeft : 0);nModifiers |= (GetKeyState(VK_RWIN    ) & 0x80 ? MetaRight : 0);// 将锁定键添加到相同的位nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0);nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0);nModifiers |= (GetKeyState(VK_SCROLL  ) & 0x01 ? ScrollLock : 0);if (flags & LLKHF_EXTENDED)   // 使用扩展键,例如:Home End pgUP pgDn{nModifiers |= ExtendedKey;}return nModifiers;
}static HHOOK g_hook = nullptr;
/*** @brief           处理鼠标事件的回调函数,由于这不是一个成员函数,所以需要通过中间单例类mouseEvent将鼠标信号传递出来*                  具体内容看https://learn.microsoft.com/zh-cn/previous-versions/windows/desktop/legacy/ms644986(v=vs.85)* @param nCode     挂钩过程用于确定如何处理消息的代码。如果nCode小于零,则挂钩过程必须将消息传递给 CallNextHookEx 函数而不进行进一步处理,并且应返回CallNextHookEx返回的值* @param wParam    信号类型:WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN或WM_SYSKEYUP* @param lParam    MSLLHOOKSTRUCT结构体指针* @return*/
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{KBDLLHOOKSTRUCT * kbdll = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);bool isDeadKey                  = false;Qt::KeyboardModifiers modifiers = queryKeyboardModifiers();int                   key       = int(toKeyOrUnicode(kbdll->vkCode, kbdll->scanCode, &isDeadKey));QString               text      = getKeyText(kbdll->vkCode, kbdll->scanCode);quint32         nativeModifiers = getNativeModifiers(kbdll->flags);bool                  autorep   = (g_buffer[kbdll->vkCode] & 0x80);switch (wParam){case WM_KEYDOWN:      // 按下非系统键, 非系统键是未按下 ALT 键时按下的键{emit GlobalKeyEvent::getInstance()->keyEvent(new QKeyEvent(QEvent::KeyPress, key, modifiers, kbdll->scanCode, kbdll->vkCode, nativeModifiers, text, autorep));break;}case WM_KEYUP:        // 当释放非系统键emit GlobalKeyEvent::getInstance()->keyEvent(new QKeyEvent(QEvent::KeyRelease, key, modifiers, kbdll->scanCode, kbdll->vkCode, nativeModifiers, text, !autorep));break;case WM_SYSKEYDOWN:   // 当用户按下 F10 键 (激活菜单栏) 或按住 Alt 键,然后按另一个键时,发布到具有键盘焦点的窗口qDebug() << "按下系统键 Alt";emit GlobalKeyEvent::getInstance()->keyEvent(new QKeyEvent(QEvent::KeyPress, key, modifiers, kbdll->scanCode, kbdll->vkCode, nativeModifiers, text, autorep));break;case WM_SYSKEYUP:     // 当用户释放按下 Alt 键时按下的键qDebug() << "释放系统键 Alt";emit GlobalKeyEvent::getInstance()->keyEvent(new QKeyEvent(QEvent::KeyRelease, key, modifiers, kbdll->scanCode, kbdll->vkCode, nativeModifiers, text, !autorep));break;default:break;}return CallNextHookEx(nullptr, nCode, wParam, lParam);   // 注意这一行一定不能少,否则会出大问题
}/*** @brief  安装全局鼠标事件监听器* @return*/
bool GlobalKeyEvent::installKeyEvent()
{if(g_hook) return true;     // 避免重复安装/*** WH_KEYBOARD_LL 为全局键盘钩子, WH_MOUSE_LL 为全局鼠标钩子* 详细说明看官方文档:https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setwindowshookexw*/g_hook = SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandleW(nullptr), 0);return g_hook;
}/*** @brief   卸载全局鼠标事件监听器* @return*/
bool GlobalKeyEvent::removeKeyEvent()
{if(!g_hook) return true;   // 避免重复卸载bool ret = UnhookWindowsHookEx(g_hook);if(ret){g_hook = nullptr;return true;}return false;
}#endif

http://www.ppmy.cn/ops/97238.html

相关文章

x264 编码器 AArch64汇编系列:帧内预测函数

x264 汇编介绍 关于 x264 汇编介绍可以参考:x264 编码器汇编模块介绍关于 x264 AArch64汇编函数介绍可以参考:x264 编码器 AArch64 汇编函数模块关系分析帧内预测AArch64 汇编函数 在进行帧内预测编码过程,需要对各种分块模式进行模式预测。汇编函数关系和原理图:【Plane 模…

如何在Spring Boot应用中加载和使用TensorFlow模型

在Spring Boot应用中加载和使用TensorFlow模型&#xff0c;‌可以通过以下步骤实现&#xff1a;‌ ‌创建Spring Boot项目‌&#xff1a;‌首先&#xff0c;‌使用Spring Initializr创建一个新的Spring Boot项目&#xff0c;‌并添加Spring Web依赖。‌‌添加TensorFlow依赖‌…

asp.net MVC 根据菜单树类别不同,动态加载视图

在 ASP.NET MVC 中&#xff0c;根据菜单树的类别动态加载不同的视图&#xff0c;可以通过以下步骤实现&#xff1a; 目录 1. 创建菜单模型 2. 构建菜单树 3. 动态加载视图 4. 创建部分视图 5. 根据类别动态加载部分视图 6. 使用 Ajax 动态加载&#xff08;可选&#xff…

【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(十四)

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

算法的学习笔记—栈的压入、弹出序列(牛客JZ31)

&#x1f600;前言 栈&#xff08;Stack&#xff09;是一种常见的数据结构&#xff0c;具有“后进先出”的特性。在实际应用中&#xff0c;我们常常需要验证一组操作是否符合栈的特性。本文将探讨如何通过编程判断一个给定的弹出序列是否可以由另一个给定的压入序列生成&#x…

如何将 Windows 11/10/8/7 克隆到另一台计算机

为什么需要将 Windows克隆到新计算机 “我有一台新笔记本电脑来替换我的旧电脑&#xff0c;因为它运行几年后变得越来越慢。我现在面临的问题是如何让 Windows 10、程序和文件与旧 PC 保持相同。我不想重新安装 Windows 和应用程序。有没有快速简便的方法可以做到这一点&#…

PyTorch 基础学习

文章索引&#xff1a; PyTorch 基础学习&#xff08;1&#xff09; - 快速入门 PyTorch 基础学习&#xff08;2&#xff09;- 张量 Tensors PyTorch 基础学习&#xff08;3&#xff09; - 张量的数学操作 PyTorch 基础学习&#xff08;4&#xff09;- 张量的类型 PyTorch 基础学…

汽车EDI: NAVISTAR EDI对接

Navistar International Corporation 是一家美国商用车辆制造公司&#xff0c;总部位于伊利诺伊州的Lisle。公司以生产中型和重型卡车、公共汽车、柴油发动机和底盘闻名&#xff0c;其产品广泛应用于运输、建筑、和农业等行业。Navistar 的历史可以追溯到1831年&#xff0c;由国…

初识spring security (一),一文弄懂默认配置

一、简单导入依赖 1、导入pom <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version></parent><modelVersion>4.0.0</modelVersion&g…

定制开发AI智能名片商城小程序:融合销售策略与个人魅力的营销新路径

摘要&#xff1a;在数字化时代&#xff0c;营销策略的创新与个性化成为企业脱颖而出的关键。本文探讨了如何通过定制开发AI智能名片商城小程序&#xff0c;结合销售策略与个人魅力&#xff0c;实现用户心甘情愿购买产品的目标。通过分析用户行为、心理需求及市场趋势&#xff0…

django之反向关系查询<related_model>_set/related_name

假设有两个模型&#xff1a;Author和Post&#xff0c;其中Post模型通过ForeignKey字段与Author模型相关联。 模型定义 from django.db import modelsclass Author(models.Model):first_name models.CharField(max_length30)last_name models.CharField(max_length30)class …

src资产收集心得

src平台的收录公告 ● 有的src平台公告中写着不要哪些站的洞得看清楚不然白忙活 ● 给你的是根域还是业务范围 收集方法/工具 ● oneforall(功能强大你需要配置api能配就配下&#xff0c;比较耗时) ● 灯塔&#xff08;本人不用&#xff09; ● layer ● fofa、quake、hunte…

EmguCV学习笔记 C# 5.2 仿射变换

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

vba自动发送邮件的基础步骤?有哪些流程?

vba自动发送邮件如何设置&#xff1f;vba自动发送邮件的技巧&#xff1f; 如果你想节省时间&#xff0c;提高工作效率&#xff0c;学会如何使用VBA自动发送邮件是一个非常有用的技能。AokSend将为你介绍VBA自动发送邮件的基础步骤&#xff0c;并通过简单的分段来详细讲解。 v…

[数据集][目标检测]夜间老鼠检测数据集VOC+YOLO格式316张1类别+视频文件1个

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;316 标注数量(xml文件个数)&#xff1a;316 标注数量(txt文件个数)&#xff1a;316 标注类别…

精益管理|介绍一本专门研究防错法(Poka-Yoke)的书

在现代制造业中&#xff0c;如何确保产品在每个生产环节中不出现错误是企业追求的目标之一。而实现这一目标的关键技术之一就是防错法&#xff08;Poka-Yoke&#xff09;。作为一种简单而有效的精益管理、六西格玛管理工具&#xff0c;防错法帮助企业避免因人为错误或工艺不当导…

共享打印机修复工具哪个好_2024年共享打印机修复工具推荐

共享打印机修复工具哪个好&#xff1f;最近几年使用过共享打印机的小伙伴遇到各种共享错误&#xff0c;出现0x00000709和0x0000011b访问共享打印机问题&#xff0c;各种打印机修复工具也有&#xff0c;下面小编就给大家介绍共享打印机修复工具哪个好用分析。 共享打印机修复工具…

用Python实现生信分析——序列搜索和比对工具详解

1. 什么是序列搜索和比对工具&#xff1f; 序列搜索和比对工具在生物信息学中用于在大型序列数据库中搜索与查询序列相似的序列&#xff0c;并进行比对分析。这些工具可以帮助研究人员识别与目标序列相关的已知序列&#xff0c;从而推测其功能、结构和进化关系。 常见的序列搜…

2024零基础转行做程序员,选什么语言更好就业?

零基础转行做程序员&#xff0c;选什么语言更好就业&#xff0c;未来的发展前景更好&#xff1f; 这个问题困扰了不少想转行的同学。有人说Python简单好上手&#xff0c;有人说Java就业机会多&#xff0c;有人说C薪资高&#xff0c;到底该怎么选&#xff1f; 其实各个语言的发…

安泰电压放大器的设计要求是什么样的

电压放大器的设计要求是一个广泛而复杂的领域&#xff0c;它在电子工程中扮演着至关重要的角色。电压放大器是一种电子电路&#xff0c;用于将输入信号的电压增大&#xff0c;而不改变其波形&#xff0c;通常用于放大微弱的信号以便进行后续处理或传输。下面将详细介绍电压放大…