Qtフレームワークはクロスプラットフォーム開発を可能にしますが、キーボードフックのようなプラットフォーム固有の機能を実装する場合、条件付きコンパイルによる対応が必要となります。WindowsプラットフォームではSetWindowsHookExなどのAPIを使用できますが、macOSでは同等の機能が提供されていません。
条件付きコンパイルを実現するための主要なポイント:
- プロジェクトファイルにおけるシステムライブラリの指定 Windowsシステムでのみuser32.libをリンクするため、.proファイルに以下の記述を追加します:
win32: LIBS += -luser32
- プラットフォーム判定によるヘッダーインクルード Qtが提供する定義マクロを使用してシステムを判別します:
#ifdef Q_OS_WIN
#include <windows.h>
#endif
- フック機能の実装をWindows環境に限定 フックの初期化と解放処理をプラットフォーム条件で囲います:
#ifdef Q_OS_WIN
// Windows専用のフック処理実装
#endif
実装例:
KeyHook.h
#ifndef KEYHOOK_H
#define KEYHOOK_H
#include <QObject>
#ifdef Q_OS_WIN
#include <windows.h>
class KeyHook
{
public:
KeyHook();
bool setupKeyboardHook();
void removeKeyboardHook();
};
#endif
#endif // KEYHOOK_H
KeyHook.cpp
#include "keyhook.h"
#include <QDebug>
#ifdef Q_OS_WIN
static HHOOD keyboardHookHandle = nullptr;
LRESULT CALLBACK keyboardCallback(int code, WPARAM wparam, LPARAM lparam)
{
KBDLLHOOKSTRUCT* keyData = (KBDLLHOOKSTRUCT*)lparam;
if (code == HC_ACTION) {
if (keyData->vkCode == VK_ESCAPE) {
if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
qDebug() << "Ctrl+Esc detected";
return 1; // メッセージを処理済みとして伝播を停止
}
}
}
return CallNextHookEx(keyboardHookHandle, code, wparam, lparam);
}
KeyHook::KeyHook() {}
bool KeyHook::setupKeyboardHook()
{
keyboardHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardCallback, nullptr, 0);
return keyboardHookHandle != nullptr;
}
void KeyHook::removeKeyboardHook()
{
if (keyboardHookHandle) {
UnhookWindowsHookEx(keyboardHookHandle);
keyboardHookHandle = nullptr;
}
}
#endif