2013-09-19 6 views
4

Я пытаюсь использовать API для Windows в C++ и SetWindowsHookExWH_KEYBOARD_LL не похоже, чтобы получить события от сдвига правой клавиши (на Shift, клавишу на правой стороне клавиатуры QWERTY, ниже Введите ключ). Он работает с левыми Shift ключ. Как устранить эту проблему?SetWindowsHookEx WH_KEYBOARD_LL не реагирует на сдвиг вправо

#include "stdafx.h" 
#include <cstdlib> 
#include <fstream> 
#include <iostream> 
#include <string> 
#include <windows.h> 
#include <string> 
#include <shlobj.h> 
#include <Shlwapi.h> 
#include <stdio.h> 
#include <aclapi.h> 
#include <tchar.h> 
#include <iostream> 
#include <fstream> 
#include <future> 
#include <stdlib.h> 
#include <random> 
#include <ctime> 
#include <time.h>  
#include <Lmcons.h> 



HHOOK kbdhook; /* Keyboard hook handle */ 
bool running; /* Used in main loop */ 


__declspec(dllexport) LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp) 
{ 
     static bool capslock = false; 
     static bool shift = false; 
     char tmp[0xFF] = {0}; 
     std::string str; 
     DWORD msg = 1; 
     KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp); 



     msg += (st_hook.scanCode << 16); 
     msg += ((st_hook.flags & LLKHF_EXTENDED) << 24); 
     GetKeyNameText(msg, tmp, 0xFF); 
     str = std::string(tmp); 


    if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN)) { 
     MessageBox(NULL,str.c_str(),NULL,MB_OK); 
} 
return CallNextHookEx(kbdhook, code, wp, lp); 
} 

LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 
{ 
    switch (msg) { 
     case WM_CLOSE: case WM_DESTROY: 
      running = false; 
      break; 
     default: 
      /* Call default message handler */ 
      return DefWindowProc(hwnd, msg, wp, lp); 
    } 

    return 0; 
} 

int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance, 
     LPSTR cmdline, int ncmdshow) 
{ 


    HWND  hwnd; 
    HWND  fgwindow = GetForegroundWindow(); 
    MSG  msg; 
    WNDCLASSEX windowclass; 
    HINSTANCE modulehandle; 

    modulehandle = GetModuleHandle(NULL); 
    kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, NULL); 
    running = true; 






    while (running) { 

     if (!GetMessage(&msg, NULL, 0, 0)) 
      running = false; 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 0; 
} 

Смещение вправо показывает строку бланко в предупреждении. Однако сдвиг влево показывает строку «SHIFT» в предупреждении. Кто-нибудь подскажет ???

PS:

Если удалить строку с "MSG + = ((st_hook.flags & LLKHF_EXTENDED) < < 24);" -> «RIGHT SHIFT» теперь отображается, но при нажатии «Windows key»

+0

@paulm сдвига вправо показывает Бланко строку в боевой готовности. Однако сдвиг влево показывает строку «SHIFT» в предупреждении. – user10056

+1

Это причуда в GetKeyNameText(). Клавиши смены немного особенные, они генерируют один и тот же виртуальный ключевой код, но имеют разные коды сканирования. Он просто неправильно обрабатывает код сканирования для правой клавиши переключения. Вам придется обойти это ограничение. –

+1

@ HansPassant Как ??? – user10056

ответ

1

Левая и правая смена отображаются в поле vkCodeKBDLLHOOKSTRUCT. Вы используете ключ имя scancode; правая клавиша сдвига называется «Shift», точно так же, как на клавиатуре.

Видимо, сдвиг вправо заканчивается расширенным набором флагов, что вызывает появление GetKeyNameText в неправильной таблице. Удаление расширенного флага заканчивается ключевым именем «правого сдвига».

msg += (st_hook.scanCode << 16); 
    if (st_hook.scanCode != 0x3a) 
    { 
     msg += ((st_hook.flags & LLKHF_EXTENDED) << 24); 
    } 
    GetKeyNameText(msg, tmp, 0xFF); 
+0

A « blanco ", как в неопределенном символе, или как в результате NULL. – user10056

+0

Однако ... Если я удалю строки, связанные с" msg + = ((st_hook.flags & LLKHF_EXTENDED) << 24);" -> "RIGHT SHIFT" теперь отображается, но не определено появляется при нажатии клавиши «Windows». И это смешение вверх, слева, справа, внизу стрелок и «вставка», «удаление», «конец» с цифрами (1,2,3,4,5,6 , 7,8,9,0) .... Кстати, как вы знаете эти вещи Windows API? – user10056

+0

@ user10056 Итак, ответ был * специально * игнорировать расширенный флаг для сдвига вправо (код сканирования 0x3a). ключи (вставка, удаление и т. д.) нуждаются в расширенном флаге, чтобы получить правильное поведение. Я знаю эти вещи API b ecause я работаю в Windows. –

1

Это решение не зависит от конкретного кода

if (st_hook.vkCode != VK_RSHIFT) 
    msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);