Ок, так что мне удалось решить это, хотя я не совсем доволен решением. По крайней мере, нет никакой тайны, и это работает:).
Причина, по которой я не получил горячие клавиши Ctrl + Alt + F11 и Ctrl + Alt + F12
Они были зарегистрированы как глобальные горячие клавиши. Мне удалось выяснить это с помощью программы ActiveHotkeys , которую он получил от участника stackoverflow moodforaday (большое спасибо за это!). По-видимому, не существует документированного способа узнать , какая программа зарегистрировала конкретную горячую клавишу (и она ничего не сделала в моей системе). См. Ветку 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);
Код хука (в основном из ответа эфотиниса):
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 проверяются на
Следует отметить , что когда вы вызываете функцию из ловушки, цикл обработки событий Qt только что начал обработку. Это означает, что до тех пор, пока вы не вернетесь из своей функции, он будет блокировать пользовательский интерфейс (останавливая его на несколько секунд). Если вы хотите показать диалог, как я, вместо exec()
, вызовите raise, activateWindow
и show
, в то время как для модальности окна диалога задайте модальное значение (возможно, в его конструкторе).
Вы можете отменить регистрацию ловушки с помощью UnHookWindowsHookEx , если хотите (что происходит, когда модуль, содержащий ловушку, выгружается). Для этого сохраните возвращаемое значение вызова SetWindowsHookEx.