Уу, так что мне удалось это решить, хотя я не совсем доволен решением. По крайней мере, тайны нет и работает :).
Причина, по которой я не получил горячие клавиши Ctrl + Alt + F11 и Ctrl + Alt + F12
Они были зарегистрированы как глобальные горячие клавиши. Мне удалось выяснить это с помощью программы ActiveHotkeys другого stackoverflow. настроение участника (большое за это спасибо!). По-видимому, не существует документированного способа узнать, какая программа зарегистрировала конкретную горячую клавишу (и она ничего не сделала в моей системе). См. Ветку moodforaday по этой проблеме.
Решение
Один из ответов в вышеупомянутой теме привел меня к другому вопросу < / а>. Ответ Эфотиниса мне идеально подошел. У меня не было опыта настройки низкоуровневых клавишных хуков, но это было не так сложно, как кажется. Ради будущего, вот как я сделал это в своем приложении Qt:
В моем mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// ... code
private:
void tryLogin();
friend LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparam, LPARAM lparam);
};
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparam, LPARAM lparam);
В моем mainwindow.cpp:
// setting up the hook in the constructor
SetWindowsHookEx(WH_KEYBOARD_LL,
LowLevelKeyboardProc,
NULL,
0);
Код ловушки (в основном из ответа efotinis):
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparam, LPARAM lparam)
{
KBDLLHOOKSTRUCT* kllhs = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
if (code == HC_ACTION)
{
if (wparam == WM_KEYDOWN && kllhs->vkCode == VK_F12 &&
(GetAsyncKeyState(VK_MENU) < 0 && GetAsyncKeyState(VK_CONTROL) < 0))
{
MainWindow* w = dynamic_cast<MainWindow*>(qApp->activeWindow());
if (NULL != w)
{
w->tryLogin(); // this should not be blocking!
return 1;
}
}
}
return CallNextHookEx(0, code, wparam, lparam);
}
Как видите, мы получаем указатель на окно приложения из глобального объекта QApplication. Мы используем dynamic_cast, чтобы в активном окне не было экземпляра MainWindow, мы получили бы указатель NULL.
Если вам интересно, почему вызовы GetAsyncKeyState проверяются на <0, это потому, что эта функция возвращается с установленным MSB, если ключ нажат. А когда установлен MSB, число SHORT отрицательное (на x86 / x64 и совместимых платформах). Если Windows когда-либо будет перенесена на платформу, где целые числа со знаком представлены по-другому, этот код может сломаться. Абсолютно правильный способ - создать 16-битную маску и использовать ее для проверки MSB, но мне лень это делать. :)
Следует обратить внимание на то, что когда вы вызываете функцию из своего обработчика, цикл событий Qt только что начал обработку. Это означает, что до тех пор, пока вы не вернетесь из своей функции, он заблокирует пользовательский интерфейс (заморозит его на несколько секунд). Если вы хотите показать диалоговое окно, как это сделал я, вместо exec()
вызовите raise, activateWindow
и show
, установив модальность окна диалогового окна как модальное (возможно, в его конструкторе).
Вы можете отменить регистрацию ловушки с помощью UnHookWindowsHookEx, если хотите (что происходит когда модуль, содержащий перехватчик, выгружен). Для этого сохраните возвращаемое значение вызова SetWindowsHookEx.
person
Tamás Szelei
schedule
29.03.2011
e->key()
- 16777249 (точнее, это значение поляk
в объекте QKeyEvent). Это значение неизменно одно и то же. Значение Qt :: Key_F11 - 16777274. - person Tamás Szelei   schedule 29.03.2011