mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-19 10:23:10 +08:00
[refactor] reorganize platform and wire sources
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
#include "device_controller_factory.h"
|
||||
|
||||
#include "keyboard_capturer.h"
|
||||
#include "mouse_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
DeviceController* DeviceControllerFactory::Create(Device device) {
|
||||
switch (device) {
|
||||
case Mouse:
|
||||
return new PlatformMouseController();
|
||||
case Keyboard:
|
||||
return new PlatformKeyboardCapturer();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace crossdesk
|
||||
@@ -0,0 +1,316 @@
|
||||
#include "keyboard_capturer.h"
|
||||
|
||||
#include <hidusage.h>
|
||||
|
||||
#include "rd_log.h"
|
||||
#include "windows_input_marker.h"
|
||||
|
||||
namespace crossdesk {
|
||||
namespace {
|
||||
|
||||
constexpr wchar_t kRawInputWindowClassName[] =
|
||||
L"CrossDeskKeyboardRawInputWindow";
|
||||
|
||||
bool PreferSideSpecificVkInjection(int key_code) {
|
||||
switch (key_code) {
|
||||
case VK_LSHIFT:
|
||||
case VK_RSHIFT:
|
||||
case VK_LCONTROL:
|
||||
case VK_RCONTROL:
|
||||
case VK_LMENU:
|
||||
case VK_RMENU:
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PlatformKeyboardCapturer::PlatformKeyboardCapturer() {}
|
||||
|
||||
PlatformKeyboardCapturer::~PlatformKeyboardCapturer() { Unhook(); }
|
||||
|
||||
int PlatformKeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) {
|
||||
if (capture_thread_.joinable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
on_key_action_ = on_key_action;
|
||||
user_ptr_ = user_ptr;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(capture_state_mutex_);
|
||||
capture_thread_id_ = 0;
|
||||
capture_start_complete_ = false;
|
||||
capture_start_succeeded_ = false;
|
||||
}
|
||||
|
||||
capture_thread_ = std::thread(&PlatformKeyboardCapturer::RawInputThreadMain, this);
|
||||
|
||||
std::unique_lock<std::mutex> lock(capture_state_mutex_);
|
||||
capture_start_condition_.wait(
|
||||
lock, [this] { return capture_start_complete_; });
|
||||
const bool capture_started = capture_start_succeeded_;
|
||||
lock.unlock();
|
||||
|
||||
if (!capture_started) {
|
||||
if (capture_thread_.joinable()) {
|
||||
capture_thread_.join();
|
||||
}
|
||||
on_key_action_ = nullptr;
|
||||
user_ptr_ = nullptr;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PlatformKeyboardCapturer::Unhook() {
|
||||
DWORD capture_thread_id = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(capture_state_mutex_);
|
||||
capture_thread_id = capture_thread_id_;
|
||||
}
|
||||
if (capture_thread_id != 0 &&
|
||||
!PostThreadMessageW(capture_thread_id, WM_QUIT, 0, 0)) {
|
||||
LOG_WARN("Failed to stop keyboard raw input thread, thread_id={}, error={}",
|
||||
capture_thread_id, GetLastError());
|
||||
}
|
||||
if (capture_thread_.joinable()) {
|
||||
capture_thread_.join();
|
||||
}
|
||||
|
||||
on_key_action_ = nullptr;
|
||||
user_ptr_ = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PlatformKeyboardCapturer::RawInputThreadMain() {
|
||||
const DWORD thread_id = GetCurrentThreadId();
|
||||
|
||||
MSG message{};
|
||||
PeekMessageW(&message, nullptr, WM_USER, WM_USER, PM_NOREMOVE);
|
||||
const bool capture_started = CreateRawInputWindow();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(capture_state_mutex_);
|
||||
capture_thread_id_ = thread_id;
|
||||
capture_start_succeeded_ = capture_started;
|
||||
capture_start_complete_ = true;
|
||||
}
|
||||
capture_start_condition_.notify_one();
|
||||
|
||||
if (!capture_started) {
|
||||
std::lock_guard<std::mutex> lock(capture_state_mutex_);
|
||||
capture_thread_id_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO("Keyboard raw input capture started, thread_id={}", thread_id);
|
||||
while (true) {
|
||||
const BOOL get_message_result = GetMessageW(&message, nullptr, 0, 0);
|
||||
if (get_message_result <= 0) {
|
||||
if (get_message_result < 0) {
|
||||
LOG_WARN("Keyboard raw input message loop failed, thread_id={}, "
|
||||
"error={}",
|
||||
thread_id, GetLastError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&message);
|
||||
DispatchMessageW(&message);
|
||||
}
|
||||
|
||||
DestroyRawInputWindow();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(capture_state_mutex_);
|
||||
capture_thread_id_ = 0;
|
||||
}
|
||||
LOG_INFO("Keyboard raw input capture stopped, thread_id={}", thread_id);
|
||||
}
|
||||
|
||||
bool PlatformKeyboardCapturer::CreateRawInputWindow() {
|
||||
const HINSTANCE instance = GetModuleHandleW(nullptr);
|
||||
WNDCLASSEXW window_class{};
|
||||
window_class.cbSize = sizeof(window_class);
|
||||
window_class.lpfnWndProc = &PlatformKeyboardCapturer::RawInputWindowProc;
|
||||
window_class.hInstance = instance;
|
||||
window_class.lpszClassName = kRawInputWindowClassName;
|
||||
|
||||
if (RegisterClassExW(&window_class) == 0) {
|
||||
const DWORD error = GetLastError();
|
||||
if (error != ERROR_CLASS_ALREADY_EXISTS) {
|
||||
LOG_WARN("Failed to register keyboard raw input window class, error={}",
|
||||
error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
raw_input_window_ = CreateWindowExW(
|
||||
0, kRawInputWindowClassName, L"", 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr,
|
||||
instance, this);
|
||||
if (!raw_input_window_) {
|
||||
LOG_WARN("Failed to create keyboard raw input window, error={}",
|
||||
GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
RAWINPUTDEVICE keyboard_device{};
|
||||
keyboard_device.usUsagePage = HID_USAGE_PAGE_GENERIC;
|
||||
keyboard_device.usUsage = HID_USAGE_GENERIC_KEYBOARD;
|
||||
keyboard_device.dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
|
||||
keyboard_device.hwndTarget = raw_input_window_;
|
||||
if (!RegisterRawInputDevices(&keyboard_device, 1,
|
||||
sizeof(keyboard_device))) {
|
||||
LOG_WARN("Failed to register keyboard raw input, error={}", GetLastError());
|
||||
DestroyWindow(raw_input_window_);
|
||||
raw_input_window_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_input_registered_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlatformKeyboardCapturer::DestroyRawInputWindow() {
|
||||
if (raw_input_registered_) {
|
||||
RAWINPUTDEVICE keyboard_device{};
|
||||
keyboard_device.usUsagePage = HID_USAGE_PAGE_GENERIC;
|
||||
keyboard_device.usUsage = HID_USAGE_GENERIC_KEYBOARD;
|
||||
keyboard_device.dwFlags = RIDEV_REMOVE;
|
||||
keyboard_device.hwndTarget = nullptr;
|
||||
if (!RegisterRawInputDevices(&keyboard_device, 1,
|
||||
sizeof(keyboard_device))) {
|
||||
LOG_WARN("Failed to unregister keyboard raw input, error={}",
|
||||
GetLastError());
|
||||
}
|
||||
raw_input_registered_ = false;
|
||||
}
|
||||
if (raw_input_window_) {
|
||||
DestroyWindow(raw_input_window_);
|
||||
raw_input_window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PlatformKeyboardCapturer::RawInputWindowProc(
|
||||
HWND window, UINT message, WPARAM w_param, LPARAM l_param) {
|
||||
PlatformKeyboardCapturer* capturer = reinterpret_cast<PlatformKeyboardCapturer*>(
|
||||
GetWindowLongPtrW(window, GWLP_USERDATA));
|
||||
if (message == WM_NCCREATE) {
|
||||
auto* create = reinterpret_cast<CREATESTRUCTW*>(l_param);
|
||||
capturer = static_cast<PlatformKeyboardCapturer*>(create->lpCreateParams);
|
||||
SetWindowLongPtrW(window, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(capturer));
|
||||
} else if (message == WM_INPUT && capturer) {
|
||||
capturer->HandleRawInput(reinterpret_cast<HRAWINPUT>(l_param));
|
||||
} else if (message == WM_NCDESTROY) {
|
||||
SetWindowLongPtrW(window, GWLP_USERDATA, 0);
|
||||
}
|
||||
return DefWindowProcW(window, message, w_param, l_param);
|
||||
}
|
||||
|
||||
void PlatformKeyboardCapturer::HandleRawInput(HRAWINPUT raw_input_handle) {
|
||||
RAWINPUT input{};
|
||||
UINT input_size = sizeof(input);
|
||||
const UINT bytes_read =
|
||||
GetRawInputData(raw_input_handle, RID_INPUT, &input, &input_size,
|
||||
sizeof(RAWINPUTHEADER));
|
||||
if (bytes_read == static_cast<UINT>(-1) ||
|
||||
bytes_read < sizeof(RAWINPUTHEADER) ||
|
||||
input.header.dwType != RIM_TYPEKEYBOARD) {
|
||||
return;
|
||||
}
|
||||
|
||||
const RAWKEYBOARD& keyboard = input.data.keyboard;
|
||||
if (keyboard.VKey == 0xFF ||
|
||||
keyboard.ExtraInformation ==
|
||||
static_cast<ULONG>(kInjectedKeyboardInputMarker)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_down = false;
|
||||
if (keyboard.Message == WM_KEYDOWN || keyboard.Message == WM_SYSKEYDOWN) {
|
||||
is_down = true;
|
||||
} else if (keyboard.Message != WM_KEYUP &&
|
||||
keyboard.Message != WM_SYSKEYUP) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool extended = (keyboard.Flags & (RI_KEY_E0 | RI_KEY_E1)) != 0;
|
||||
UINT mapped_scan_code = keyboard.MakeCode;
|
||||
if ((keyboard.Flags & RI_KEY_E0) != 0) {
|
||||
mapped_scan_code |= 0xE000;
|
||||
} else if ((keyboard.Flags & RI_KEY_E1) != 0) {
|
||||
mapped_scan_code |= 0xE100;
|
||||
}
|
||||
if (mapped_scan_code == 0xE11D || mapped_scan_code == 0xE02A) {
|
||||
return;
|
||||
}
|
||||
|
||||
int key_code = static_cast<int>(keyboard.VKey);
|
||||
if (key_code == VK_SHIFT || key_code == VK_CONTROL || key_code == VK_MENU) {
|
||||
const UINT normalized =
|
||||
MapVirtualKeyW(mapped_scan_code, MAPVK_VSC_TO_VK_EX);
|
||||
if (normalized != 0) {
|
||||
key_code = static_cast<int>(normalized);
|
||||
}
|
||||
}
|
||||
|
||||
if (on_key_action_) {
|
||||
on_key_action_(key_code, is_down, keyboard.MakeCode, extended, user_ptr_);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply remote keyboard commands to the local machine.
|
||||
int PlatformKeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down,
|
||||
uint32_t scan_code, bool extended) {
|
||||
INPUT input = {0};
|
||||
input.type = INPUT_KEYBOARD;
|
||||
input.ki.dwExtraInfo =
|
||||
static_cast<ULONG_PTR>(kInjectedKeyboardInputMarker);
|
||||
|
||||
const bool prefer_vk = PreferSideSpecificVkInjection(key_code);
|
||||
const UINT resolved_scan_code =
|
||||
scan_code != 0
|
||||
? static_cast<UINT>(scan_code & 0xFF) | (extended ? 0xE000u : 0u)
|
||||
: MapVirtualKeyW(static_cast<UINT>(key_code), MAPVK_VK_TO_VSC_EX);
|
||||
|
||||
if (scan_code != 0 && !prefer_vk) {
|
||||
input.ki.wVk = 0;
|
||||
input.ki.wScan = static_cast<WORD>(scan_code & 0xFF);
|
||||
input.ki.dwFlags |= KEYEVENTF_SCANCODE;
|
||||
if (extended) {
|
||||
input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
|
||||
}
|
||||
} else {
|
||||
input.ki.wVk = static_cast<WORD>(key_code);
|
||||
|
||||
if (prefer_vk && resolved_scan_code != 0) {
|
||||
input.ki.wScan = static_cast<WORD>(resolved_scan_code & 0xFF);
|
||||
if ((resolved_scan_code & 0xFF00) != 0) {
|
||||
input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
|
||||
}
|
||||
} else if (resolved_scan_code != 0) {
|
||||
input.ki.wVk = 0;
|
||||
input.ki.wScan = static_cast<WORD>(resolved_scan_code & 0xFF);
|
||||
input.ki.dwFlags |= KEYEVENTF_SCANCODE;
|
||||
if ((resolved_scan_code & 0xFF00) != 0) {
|
||||
input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_down) {
|
||||
input.ki.dwFlags |= KEYEVENTF_KEYUP;
|
||||
}
|
||||
|
||||
const UINT sent = SendInput(1, &input, sizeof(INPUT));
|
||||
if (sent != 1) {
|
||||
LOG_WARN("SendInput failed for key_code={}, is_down={}, err={}", key_code,
|
||||
is_down, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2024-11-22
|
||||
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _KEYBOARD_CAPTURER_H_
|
||||
#define _KEYBOARD_CAPTURER_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class PlatformKeyboardCapturer final : public KeyboardCapturer {
|
||||
public:
|
||||
PlatformKeyboardCapturer();
|
||||
virtual ~PlatformKeyboardCapturer();
|
||||
|
||||
public:
|
||||
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
|
||||
virtual int Unhook();
|
||||
virtual int SendKeyboardCommand(int key_code, bool is_down,
|
||||
uint32_t scan_code = 0,
|
||||
bool extended = false);
|
||||
|
||||
private:
|
||||
static LRESULT CALLBACK RawInputWindowProc(HWND window, UINT message,
|
||||
WPARAM w_param, LPARAM l_param);
|
||||
|
||||
void RawInputThreadMain();
|
||||
bool CreateRawInputWindow();
|
||||
void DestroyRawInputWindow();
|
||||
void HandleRawInput(HRAWINPUT raw_input_handle);
|
||||
|
||||
OnKeyAction on_key_action_ = nullptr;
|
||||
void* user_ptr_ = nullptr;
|
||||
HWND raw_input_window_ = nullptr;
|
||||
bool raw_input_registered_ = false;
|
||||
std::thread capture_thread_;
|
||||
DWORD capture_thread_id_ = 0;
|
||||
bool capture_start_complete_ = false;
|
||||
bool capture_start_succeeded_ = false;
|
||||
std::mutex capture_state_mutex_;
|
||||
std::condition_variable capture_start_condition_;
|
||||
};
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "mouse_controller.h"
|
||||
|
||||
#include <remote_action.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
PlatformMouseController::PlatformMouseController() {}
|
||||
|
||||
PlatformMouseController::~PlatformMouseController() {}
|
||||
|
||||
int PlatformMouseController::Init(std::vector<DisplayInfo> display_info_list) {
|
||||
display_info_list_ = display_info_list;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PlatformMouseController::Destroy() { return 0; }
|
||||
|
||||
int PlatformMouseController::SendMouseCommand(RemoteAction remote_action,
|
||||
int display_index) {
|
||||
if (display_index < 0 ||
|
||||
display_index >= static_cast<int>(display_info_list_.size())) {
|
||||
LOG_WARN("Mouse command skipped, invalid display_index={}, displays={}",
|
||||
display_index, display_info_list_.size());
|
||||
return -1;
|
||||
}
|
||||
|
||||
INPUT ip = {0};
|
||||
|
||||
if (remote_action.type == ControlType::mouse) {
|
||||
ip.type = INPUT_MOUSE;
|
||||
ip.mi.dx =
|
||||
(LONG)(remote_action.m.x * display_info_list_[display_index].width) +
|
||||
display_info_list_[display_index].left;
|
||||
ip.mi.dy =
|
||||
(LONG)(remote_action.m.y * display_info_list_[display_index].height) +
|
||||
display_info_list_[display_index].top;
|
||||
|
||||
switch (remote_action.m.flag) {
|
||||
case MouseFlag::left_down:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE;
|
||||
break;
|
||||
case MouseFlag::left_up:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE;
|
||||
break;
|
||||
case MouseFlag::right_down:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_ABSOLUTE;
|
||||
break;
|
||||
case MouseFlag::right_up:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_ABSOLUTE;
|
||||
break;
|
||||
case MouseFlag::middle_down:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_ABSOLUTE;
|
||||
break;
|
||||
case MouseFlag::middle_up:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_MIDDLEUP | MOUSEEVENTF_ABSOLUTE;
|
||||
break;
|
||||
case MouseFlag::wheel_vertical:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_WHEEL;
|
||||
ip.mi.mouseData = remote_action.m.s * 120;
|
||||
break;
|
||||
case MouseFlag::wheel_horizontal:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_HWHEEL;
|
||||
ip.mi.mouseData = remote_action.m.s * 120;
|
||||
break;
|
||||
default:
|
||||
ip.mi.dwFlags = MOUSEEVENTF_MOVE;
|
||||
break;
|
||||
}
|
||||
|
||||
ip.mi.time = 0;
|
||||
|
||||
if (!SetCursorPos(ip.mi.dx, ip.mi.dy)) {
|
||||
LOG_WARN("SetCursorPos failed for mouse x={}, y={}, flag={}, err={}",
|
||||
ip.mi.dx, ip.mi.dy, static_cast<int>(remote_action.m.flag),
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip.mi.dwFlags != MOUSEEVENTF_MOVE) {
|
||||
UINT sent = SendInput(1, &ip, sizeof(INPUT));
|
||||
if (sent != 1) {
|
||||
LOG_WARN(
|
||||
"SendInput failed for mouse x={}, y={}, wheel={}, flag={}, err={}",
|
||||
ip.mi.dx, ip.mi.dy, remote_action.m.s,
|
||||
static_cast<int>(remote_action.m.flag), GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2023-12-14
|
||||
* Copyright (c) 2023 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MOUSE_CONTROLLER_H_
|
||||
#define _MOUSE_CONTROLLER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <remote_action.h>
|
||||
|
||||
#include "device_controller.h"
|
||||
#include "display_info.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class PlatformMouseController final : public MouseController {
|
||||
public:
|
||||
PlatformMouseController();
|
||||
virtual ~PlatformMouseController();
|
||||
|
||||
public:
|
||||
virtual int Init(std::vector<DisplayInfo> display_info_list);
|
||||
virtual int Destroy();
|
||||
virtual int SendMouseCommand(RemoteAction remote_action, int display_index);
|
||||
|
||||
private:
|
||||
std::vector<DisplayInfo> display_info_list_;
|
||||
};
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef CROSSDESK_COMMON_WINDOWS_INPUT_MARKER_H_
|
||||
#define CROSSDESK_COMMON_WINDOWS_INPUT_MARKER_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// SendInput copies dwExtraInfo into KBDLLHOOKSTRUCT. Tag CrossDesk-generated
|
||||
// keyboard input so the controller hook can ignore only its own injections
|
||||
// while still accepting input from accessibility tools or remote sessions.
|
||||
inline constexpr std::uintptr_t kInjectedKeyboardInputMarker = 0x4353444B;
|
||||
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif // CROSSDESK_COMMON_WINDOWS_INPUT_MARKER_H_
|
||||
@@ -0,0 +1,206 @@
|
||||
// virtual_key_codes.h
|
||||
#ifndef VIRTUAL_KEY_CODES_H
|
||||
#define VIRTUAL_KEY_CODES_H
|
||||
|
||||
#define VK_LBUTTON 0x01 // Left mouse button
|
||||
#define VK_RBUTTON 0x02 // Right mouse button
|
||||
#define VK_CANCEL 0x03 // Control-break processing
|
||||
#define VK_MBUTTON 0x04 // Middle mouse button
|
||||
#define VK_XBUTTON1 0x05 // X1 mouse button
|
||||
#define VK_XBUTTON2 0x06 // X2 mouse button
|
||||
// 0x07 Reserved
|
||||
#define VK_BACK 0x08 // Backspace key
|
||||
#define VK_TAB 0x09 // Tab key
|
||||
// 0x0A-0B Reserved
|
||||
#define VK_CLEAR 0x0C // Clear key
|
||||
#define VK_RETURN 0x0D // Enter key
|
||||
// 0x0E-0F Unassigned
|
||||
#define VK_SHIFT 0x10 // Shift key
|
||||
#define VK_CONTROL 0x11 // Ctrl key
|
||||
#define VK_MENU 0x12 // Alt key
|
||||
#define VK_PAUSE 0x13 // Pause key
|
||||
#define VK_CAPITAL 0x14 // Caps lock key
|
||||
#define VK_KANA 0x15 // IME Kana mode
|
||||
#define VK_HANGUL 0x15 // IME Hangul mode
|
||||
#define VK_IME_ON 0x16 // IME On
|
||||
#define VK_JUNJA 0x17 // IME Junja mode
|
||||
#define VK_FINAL 0x18 // IME final mode
|
||||
#define VK_HANJA 0x19 // IME Hanja mode
|
||||
#define VK_KANJI 0x19 // IME Kanji mode
|
||||
#define VK_IME_OFF 0x1A // IME Off
|
||||
#define VK_ESCAPE 0x1B // Esc key
|
||||
#define VK_CONVERT 0x1C // IME convert
|
||||
#define VK_NONCONVERT 0x1D // IME nonconvert
|
||||
#define VK_ACCEPT 0x1E // IME accept
|
||||
#define VK_MODECHANGE 0x1F // IME mode change request
|
||||
#define VK_SPACE 0x20 // Spacebar key
|
||||
#define VK_PRIOR 0x21 // Page up key
|
||||
#define VK_NEXT 0x22 // Page down key
|
||||
#define VK_END 0x23 // End key
|
||||
#define VK_HOME 0x24 // Home key
|
||||
#define VK_LEFT 0x25 // Left arrow key
|
||||
#define VK_UP 0x26 // Up arrow key
|
||||
#define VK_RIGHT 0x27 // Right arrow key
|
||||
#define VK_DOWN 0x28 // Down arrow key
|
||||
#define VK_SELECT 0x29 // Select key
|
||||
#define VK_PRINT 0x2A // Print key
|
||||
#define VK_EXECUTE 0x2B // Execute key
|
||||
#define VK_SNAPSHOT 0x2C // Print screen key
|
||||
#define VK_INSERT 0x2D // Insert key
|
||||
#define VK_DELETE 0x2E // Delete key
|
||||
#define VK_HELP 0x2F // Help key
|
||||
|
||||
#define VK_0 0x30 // 0 key
|
||||
#define VK_1 0x31 // 1 key
|
||||
#define VK_2 0x32 // 2 key
|
||||
#define VK_3 0x33 // 3 key
|
||||
#define VK_4 0x34 // 4 key
|
||||
#define VK_5 0x35 // 5 key
|
||||
#define VK_6 0x36 // 6 key
|
||||
#define VK_7 0x37 // 7 key
|
||||
#define VK_8 0x38 // 8 key
|
||||
#define VK_9 0x39 // 9 key
|
||||
// 0x3A-40 Undefined
|
||||
|
||||
#define VK_A 0x41 // A key
|
||||
#define VK_B 0x42 // B key
|
||||
#define VK_C 0x43 // C key
|
||||
#define VK_D 0x44 // D key
|
||||
#define VK_E 0x45 // E key
|
||||
#define VK_F 0x46 // F key
|
||||
#define VK_G 0x47 // G key
|
||||
#define VK_H 0x48 // H key
|
||||
#define VK_I 0x49 // I key
|
||||
#define VK_J 0x4A // J key
|
||||
#define VK_K 0x4B // K key
|
||||
#define VK_L 0x4C // L key
|
||||
#define VK_M 0x4D // M key
|
||||
#define VK_N 0x4E // N key
|
||||
#define VK_O 0x4F // O key
|
||||
#define VK_P 0x50 // P key
|
||||
#define VK_Q 0x51 // Q key
|
||||
#define VK_R 0x52 // R key
|
||||
#define VK_S 0x53 // S key
|
||||
#define VK_T 0x54 // T key
|
||||
#define VK_U 0x55 // U key
|
||||
#define VK_V 0x56 // V key
|
||||
#define VK_W 0x57 // W key
|
||||
#define VK_X 0x58 // X key
|
||||
#define VK_Y 0x59 // Y key
|
||||
#define VK_Z 0x5A // Z key
|
||||
|
||||
#define VK_LWIN 0x5B // Left Windows logo key
|
||||
#define VK_RWIN 0x5C // Right Windows logo key
|
||||
#define VK_APPS 0x5D // Application key
|
||||
// 0x5E Reserved
|
||||
#define VK_SLEEP 0x5F // Computer Sleep key
|
||||
|
||||
#define VK_NUMPAD0 0x60 // Numeric keypad 0 key
|
||||
#define VK_NUMPAD1 0x61 // Numeric keypad 1 key
|
||||
#define VK_NUMPAD2 0x62 // Numeric keypad 2 key
|
||||
#define VK_NUMPAD3 0x63 // Numeric keypad 3 key
|
||||
#define VK_NUMPAD4 0x64 // Numeric keypad 4 key
|
||||
#define VK_NUMPAD5 0x65 // Numeric keypad 5 key
|
||||
#define VK_NUMPAD6 0x66 // Numeric keypad 6 key
|
||||
#define VK_NUMPAD7 0x67 // Numeric keypad 7 key
|
||||
#define VK_NUMPAD8 0x68 // Numeric keypad 8 key
|
||||
#define VK_NUMPAD9 0x69 // Numeric keypad 9 key
|
||||
#define VK_MULTIPLY 0x6A // Multiply key
|
||||
#define VK_ADD 0x6B // Add key
|
||||
#define VK_SEPARATOR 0x6C // Separator key
|
||||
#define VK_SUBTRACT 0x6D // Subtract key
|
||||
#define VK_DECIMAL 0x6E // Decimal key
|
||||
#define VK_DIVIDE 0x6F // Divide key
|
||||
|
||||
#define VK_F1 0x70 // F1 key
|
||||
#define VK_F2 0x71 // F2 key
|
||||
#define VK_F3 0x72 // F3 key
|
||||
#define VK_F4 0x73 // F4 key
|
||||
#define VK_F5 0x74 // F5 key
|
||||
#define VK_F6 0x75 // F6 key
|
||||
#define VK_F7 0x76 // F7 key
|
||||
#define VK_F8 0x77 // F8 key
|
||||
#define VK_F9 0x78 // F9 key
|
||||
#define VK_F10 0x79 // F10 key
|
||||
#define VK_F11 0x7A // F11 key
|
||||
#define VK_F12 0x7B // F12 key
|
||||
#define VK_F13 0x7C // F13 key
|
||||
#define VK_F14 0x7D // F14 key
|
||||
#define VK_F15 0x7E // F15 key
|
||||
#define VK_F16 0x7F // F16 key
|
||||
#define VK_F17 0x80 // F17 key
|
||||
#define VK_F18 0x81 // F18 key
|
||||
#define VK_F19 0x82 // F19 key
|
||||
#define VK_F20 0x83 // F20 key
|
||||
#define VK_F21 0x84 // F21 key
|
||||
#define VK_F22 0x85 // F22 key
|
||||
#define VK_F23 0x86 // F23 key
|
||||
#define VK_F24 0x87 // F24 key
|
||||
// 0x88–0x8F Reserved
|
||||
|
||||
#define VK_NUMLOCK 0x90 // Num lock key
|
||||
#define VK_SCROLL 0x91 // Scroll lock key
|
||||
// 0x92–0x96 OEM specific
|
||||
// 0x97–0x9F Unassigned
|
||||
|
||||
#define VK_LSHIFT 0xA0 // Left Shift key
|
||||
#define VK_RSHIFT 0xA1 // Right Shift key
|
||||
#define VK_LCONTROL 0xA2 // Left Ctrl key
|
||||
#define VK_RCONTROL 0xA3 // Right Ctrl key
|
||||
#define VK_LMENU 0xA4 // Left Alt key
|
||||
#define VK_RMENU 0xA5 // Right Alt key
|
||||
|
||||
#define VK_BROWSER_BACK 0xA6 // Browser Back key
|
||||
#define VK_BROWSER_FORWARD 0xA7 // Browser Forward key
|
||||
#define VK_BROWSER_REFRESH 0xA8 // Browser Refresh key
|
||||
#define VK_BROWSER_STOP 0xA9 // Browser Stop key
|
||||
#define VK_BROWSER_SEARCH 0xAA // Browser Search key
|
||||
#define VK_BROWSER_FAVORITES 0xAB // Browser Favorites key
|
||||
#define VK_BROWSER_HOME 0xAC // Browser Start and Home key
|
||||
#define VK_VOLUME_MUTE 0xAD // Volume Mute key
|
||||
#define VK_VOLUME_DOWN 0xAE // Volume Down key
|
||||
#define VK_VOLUME_UP 0xAF // Volume Up key
|
||||
|
||||
#define VK_MEDIA_NEXT_TRACK 0xB0 // Next Track key
|
||||
#define VK_MEDIA_PREV_TRACK 0xB1 // Previous Track key
|
||||
#define VK_MEDIA_STOP 0xB2 // Stop Media key
|
||||
#define VK_MEDIA_PLAY_PAUSE 0xB3 // Play/Pause Media key
|
||||
#define VK_LAUNCH_MAIL 0xB4 // Start Mail key
|
||||
#define VK_LAUNCH_MEDIA_SELECT 0xB5 // Select Media key
|
||||
#define VK_LAUNCH_APP1 0xB6 // Start Application 1 key
|
||||
#define VK_LAUNCH_APP2 0xB7 // Start Application 2 key
|
||||
// 0xB8–0xB9 Reserved
|
||||
|
||||
#define VK_OEM_1 0xBA // For US: Semicolon/Colon key
|
||||
#define VK_OEM_PLUS 0xBB // Equals/Plus key
|
||||
#define VK_OEM_COMMA 0xBC // Comma/Less Than key
|
||||
#define VK_OEM_MINUS 0xBD // Dash/Underscore key
|
||||
#define VK_OEM_PERIOD 0xBE // Period/Greater Than key
|
||||
#define VK_OEM_2 0xBF // Slash/Question Mark key
|
||||
#define VK_OEM_3 0xC0 // Grave Accent/Tilde key
|
||||
// 0xC1–0xDA Reserved
|
||||
|
||||
#define VK_OEM_4 0xDB // Left Brace key
|
||||
#define VK_OEM_5 0xDC // Backslash/Pipe key
|
||||
#define VK_OEM_6 0xDD // Right Brace key
|
||||
#define VK_OEM_7 0xDE // Apostrophe/Quote key
|
||||
#define VK_OEM_8 0xDF // (Canadian CSA: Right Ctrl key)
|
||||
// 0xE0 Reserved
|
||||
#define VK_OEM_102 0xE2 // (European ISO: Backslash/Pipe key)
|
||||
// 0xE3–E4 OEM specific
|
||||
#define VK_PROCESSKEY 0xE5 // IME PROCESS key
|
||||
// 0xE6 OEM specific
|
||||
#define VK_PACKET 0xE7 // Unicode characters as keystrokes
|
||||
// 0xE8 Unassigned
|
||||
// 0xE9–F5 OEM specific
|
||||
#define VK_ATTN 0xF6 // Attn key
|
||||
#define VK_CRSEL 0xF7 // CrSel key
|
||||
#define VK_EXSEL 0xF8 // ExSel key
|
||||
#define VK_EREOF 0xF9 // Erase EOF key
|
||||
#define VK_PLAY 0xFA // Play key
|
||||
#define VK_ZOOM 0xFB // Zoom key
|
||||
#define VK_NONAME 0xFC // Reserved
|
||||
#define VK_PA1 0xFD // PA1 key
|
||||
#define VK_OEM_CLEAR 0xFE // Clear key
|
||||
|
||||
#endif // VIRTUAL_KEY_CODES_H
|
||||
Reference in New Issue
Block a user