玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
DesktopShortcuts.cpp
1// windowshotkeymanager.cpp
2
3#include <QLoggingCategory>
4#include <QCoreApplication>
5
6#ifdef Q_OS_WIN
7#include <windows.h>
8#include <winuser.h>
9#endif
10
11#include "DesktopShortcuts.h"
12static Q_LOGGING_CATEGORY(log, "Plugin.Hook.Desktop.Shortcut")
14 : QObject(parent)
15{
16 initializeKeys();
17
18 // 安装原生事件过滤器
19 qApp->installNativeEventFilter(this);
20}
21
22CDesktopShortcutsManager::~CDesktopShortcutsManager()
23{
24 restoreAllHotkeys();
25 removeKeyboardHook();
26}
27
28void CDesktopShortcutsManager::initializeKeys()
29{
30#ifdef Q_OS_WIN
31 m_keyNames[VK_LWIN] = "Left Windows";
32 m_keyNames[VK_RWIN] = "Right Windows";
33 m_keyNames[VK_TAB] = "Tab";
34 m_keyNames[VK_ESCAPE] = "Escape";
35 m_keyNames[VK_CONTROL] = "Control";
36 m_keyNames[VK_MENU] = "Alt"; // Alt 键的虚拟键码是 VK_MENU
37 m_keyNames[VK_SHIFT] = "Shift";
38 m_keyNames[VK_SPACE] = "Space";
39 m_keyNames[VK_RETURN] = "Enter";
40 m_keyNames[VK_BACK] = "Backspace";
41 m_keyNames[VK_DELETE] = "Delete";
42 m_keyNames[VK_UP] = "Up Arrow";
43 m_keyNames[VK_DOWN] = "Down Arrow";
44 m_keyNames[VK_LEFT] = "Left Arrow";
45 m_keyNames[VK_RIGHT] = "Right Arrow";
46 m_keyNames[VK_F1] = "F1";
47 m_keyNames[VK_F2] = "F2";
48 m_keyNames[VK_F3] = "F3";
49 m_keyNames[VK_F4] = "F4";
50 m_keyNames[VK_F5] = "F5";
51 m_keyNames[VK_F6] = "F6";
52 m_keyNames[VK_F7] = "F7";
53 m_keyNames[VK_F8] = "F8";
54 m_keyNames[VK_F9] = "F9";
55 m_keyNames[VK_F10] = "F10";
56 m_keyNames[VK_F11] = "F11";
57 m_keyNames[VK_F12] = "F12";
58#endif
59}
60
61bool CDesktopShortcutsManager::disableAllHotkeys()
62{
63 if (m_hotkeysDisabled) {
64 return true;
65 }
66
67 bool success = true;
68
69 // 禁用 Windows 键
70 if (!disableWindowsKey()) {
71 success = false;
72 qWarning() << "禁用 Windows 键失败";
73 }
74
75 // 禁用 Alt+Tab
76 if (!disableAltTab()) {
77 success = false;
78 qWarning() << "禁用 Alt+Tab 失败";
79 }
80
81 // 设置键盘钩子
82 if (!setKeyboardHook()) {
83 success = false;
84 qWarning() << "设置键盘钩子失败";
85 }
86
87 if (success) {
88 m_hotkeysDisabled = true;
89 emit statusChanged(true);
90 qDebug() << "所有 Windows 快捷键已禁用";
91 }
92
93 return success;
94}
95
96bool CDesktopShortcutsManager::restoreAllHotkeys()
97{
98 if (!m_hotkeysDisabled) {
99 return true;
100 }
101
102 bool success = true;
103
104 // 恢复 Windows 键
105 if (!enableWindowsKey()) {
106 success = false;
107 }
108
109 // 恢复 Alt+Tab
110 if (!enableAltTab()) {
111 success = false;
112 }
113
114 // 恢复任务管理器
115 if (!enableTaskManager()) {
116 success = false;
117 }
118
119 // 移除键盘钩子
120 if (!removeKeyboardHook()) {
121 success = false;
122 }
123
124 if (success) {
125 m_hotkeysDisabled = false;
126 emit statusChanged(false);
127 qDebug() << "所有 Windows 快捷键已恢复";
128 }
129
130 return success;
131}
132
133bool CDesktopShortcutsManager::disableWindowsKey()
134{
135 // 方法1: 使用 RegisterHotKey 来占用 Windows 键
136 bool success = true;
137
138 // 注册热键来拦截 Windows 键
139 if (!RegisterHotKey(nullptr, 1, MOD_WIN, VK_LWIN)) {
140 qWarning() << "注册左 Windows 键拦截失败:" << GetLastError();
141 success = false;
142 }
143
144 if (!RegisterHotKey(nullptr, 2, MOD_WIN, VK_RWIN)) {
145 qWarning() << "注册右 Windows 键拦截失败:" << GetLastError();
146 success = false;
147 }
148
149 // 方法2: 修改注册表禁用 Windows 键
150 HKEY hKey;
151 LONG result = RegCreateKeyExW(HKEY_CURRENT_USER,
152 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
153 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
154
155 if (result == ERROR_SUCCESS) {
156 DWORD value = 1; // 1 表示禁用 Windows 键
157 result = RegSetValueExW(hKey, L"NoWinKeys", 0, REG_DWORD,
158 reinterpret_cast<const BYTE*>(&value), sizeof(value));
159
160 if (result == ERROR_SUCCESS) {
161 qDebug() << "注册表设置成功,Windows 键已禁用";
162 } else {
163 qWarning() << "注册表设置失败:" << result;
164 success = false;
165 }
166 RegCloseKey(hKey);
167 } else {
168 qWarning() << "创建注册表键失败:" << result;
169 success = false;
170 }
171
172 return success;
173}
174
175bool CDesktopShortcutsManager::enableWindowsKey()
176{
177#ifdef Q_OS_WIN
178 bool success = true;
179
180 // 取消注册热键
181 UnregisterHotKey(nullptr, 1);
182 UnregisterHotKey(nullptr, 2);
183
184 // 恢复注册表设置
185 HKEY hKey;
186 LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
187 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
188 0, KEY_ALL_ACCESS, &hKey);
189
190 if (result == ERROR_SUCCESS) {
191 result = RegDeleteValueW(hKey, L"NoWinKeys");
192 if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) {
193 qDebug() << "Windows 键已恢复";
194 } else {
195 qWarning() << "删除注册表值失败:" << result;
196 success = false;
197 }
198 RegCloseKey(hKey);
199 }
200
201 return success;
202#else
203 return false;
204#endif
205}
206
207bool CDesktopShortcutsManager::disableAltTab()
208{
209 /*
210#ifdef Q_OS_WIN
211 // 使用系统参数设置禁用 Alt+Tab
212 BOOL result = SystemParametersInfo(SPI_SETSWITCHTASKS, 0, nullptr, 0);
213 if (result) {
214 qDebug() << "Alt+Tab 已禁用";
215 return true;
216 } else {
217 qWarning() << "禁用 Alt+Tab 失败:" << GetLastError();
218 return false;
219 }
220#else
221 return false;
222#endif //*/
223 return false;
224}
225
226bool CDesktopShortcutsManager::enableAltTab()
227{
228 /*
229#ifdef Q_OS_WIN
230 BOOL result = SystemParametersInfo(SPI_SETSWITCHTASKS, 1, nullptr, 0);
231 if (result) {
232 qDebug() << "Alt+Tab 已恢复";
233 return true;
234 } else {
235 qWarning() << "恢复 Alt+Tab 失败:" << GetLastError();
236 return false;
237 }
238#else
239 return false;
240#endif//*/
241 return false;
242}
243
244bool CDesktopShortcutsManager::disableTaskManager()
245{
246#ifdef Q_OS_WIN
247 HKEY hKey;
248 LONG result = RegCreateKeyExW(HKEY_CURRENT_USER,
249 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
250 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
251
252 if (result == ERROR_SUCCESS) {
253 DWORD value = 1; // 1 表示禁用任务管理器
254 result = RegSetValueExW(hKey, L"DisableTaskMgr", 0, REG_DWORD,
255 reinterpret_cast<const BYTE*>(&value), sizeof(value));
256
257 if (result == ERROR_SUCCESS) {
258 qDebug() << "任务管理器已禁用";
259 return true;
260 } else {
261 qWarning() << "禁用任务管理器失败:" << result;
262 }
263 RegCloseKey(hKey);
264 }
265#endif
266 return false;
267}
268
269bool CDesktopShortcutsManager::enableTaskManager()
270{
271#ifdef Q_OS_WIN
272 HKEY hKey;
273 LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
274 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
275 0, KEY_ALL_ACCESS, &hKey);
276
277 if (result == ERROR_SUCCESS) {
278 result = RegDeleteValueW(hKey, L"DisableTaskMgr");
279 RegCloseKey(hKey);
280
281 if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) {
282 qDebug() << "任务管理器已恢复";
283 return true;
284 }
285 }
286#endif
287 return false;
288}
289
290bool CDesktopShortcutsManager::setKeyboardHook()
291{
292#ifdef Q_OS_WIN
293 if (m_keyboardHooked) {
294 return true;
295 }
296
297 m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProc, GetModuleHandle(nullptr), 0);
298 if (m_keyboardHook) {
299 m_keyboardHooked = true;
300 qDebug() << "键盘钩子设置成功";
301 return true;
302 } else {
303 qWarning() << "设置键盘钩子失败:" << GetLastError();
304 return false;
305 }
306#else
307 return false;
308#endif
309}
310
311bool CDesktopShortcutsManager::removeKeyboardHook()
312{
313#ifdef Q_OS_WIN
314 if (m_keyboardHook) {
315 BOOL result = UnhookWindowsHookEx(m_keyboardHook);
316 if (result) {
317 m_keyboardHook = nullptr;
318 m_keyboardHooked = false;
319 qDebug() << "键盘钩子已移除";
320 return true;
321 } else {
322 qWarning() << "移除键盘钩子失败:" << GetLastError();
323 return false;
324 }
325 }
326#endif
327 return true;
328}
329
330#ifdef Q_OS_WIN
331LRESULT CALLBACK CDesktopShortcutsManager::keyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
332{
333 if (nCode >= 0) {
334 KBDLLHOOKSTRUCT *kbStruct = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
335
336 // 检查按键按下事件
337 if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
338 int keyCode = kbStruct->vkCode;
339
340 // 拦截系统快捷键
341 if (keyCode == VK_LWIN || keyCode == VK_RWIN) {
342 qDebug() << "拦截 Windows 键";
343 return 1; // 阻止按键传递
344 }
345
346 // 拦截 Alt+Tab
347 if (keyCode == VK_TAB && (GetAsyncKeyState(VK_MENU) & 0x8000)) {
348 qDebug() << "拦截 Alt+Tab";
349 return 1;
350 }
351
352 // 拦截 Alt+Esc
353 if (keyCode == VK_ESCAPE && (GetAsyncKeyState(VK_MENU) & 0x8000)) {
354 qDebug() << "拦截 Alt+Esc";
355 return 1;
356 }
357
358 // 拦截 Ctrl+Esc (开始菜单)
359 if (keyCode == VK_ESCAPE && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
360 qDebug() << "拦截 Ctrl+Esc";
361 return 1;
362 }
363 }
364 }
365
366 // 继续传递消息
367 return CallNextHookEx(nullptr, nCode, wParam, lParam);
368}
369#endif
370
371bool CDesktopShortcutsManager::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
372{
373#ifdef Q_OS_WIN
374 if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG") {
375 MSG *msg = static_cast<MSG*>(message);
376
377 // 处理热键消息
378 if (msg->message == WM_HOTKEY) {
379 int hotkeyId = static_cast<int>(msg->wParam);
380 QString keyName = m_keyNames.value(hotkeyId, "Unknown");
381
382 emit hotkeyBlocked(hotkeyId, keyName);
383 qDebug() << "拦截系统热键:" << keyName;
384
385 *result = 0;
386 return true;
387 }
388
389 // 处理其他系统消息
390 if (msg->message == WM_SYSCOMMAND) {
391 // 拦截系统命令
392 switch (msg->wParam) {
393 case SC_SCREENSAVE: // 屏幕保护
394 case SC_MONITORPOWER: // 显示器电源
395 case SC_TASKLIST: // 任务列表 (Ctrl+Esc)
396 qDebug() << "拦截系统命令:" << msg->wParam;
397 *result = 0;
398 return true;
399 }
400 }
401 }
402#endif
403
404 return false;
405}