Skip to content

Commit 0eac3d9

Browse files
author
nahida-mono
committed
pull
2 parents 03c1cf5 + 80a8285 commit 0eac3d9

File tree

3 files changed

+97
-116
lines changed

3 files changed

+97
-116
lines changed

src/Snap.Hutao.Remastered.Native/HutaoNative.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,12 @@ HRESULT STDMETHODCALLTYPE HutaoNative::MakeHotKeyAction(HutaoNativeHotKeyActionK
152152
{
153153
AssertNonNullAndReturn(ppv);
154154

155-
HutaoNativeHotKeyActionCallback cb = {};
156-
cb.value = reinterpret_cast<HutaoNativeHotKeyActionCallbackFunc>(callback);
157-
GCHandle userDataHandle = static_cast<GCHandle>(userData);
155+
// Convert nint to appropriate types
156+
HutaoNativeHotKeyActionCallback actionCallback;
157+
actionCallback.value = reinterpret_cast<void (__stdcall *)(BOOL, LONG_PTR)>(callback);
158+
LONG_PTR userDataPtr = static_cast<LONG_PTR>(userData);
158159

159-
hutao::com_ptr<IHutaoNativeHotKeyAction> hotKeyAction = hutao::make_com_ptr<HutaoNativeHotKeyAction>(kind, cb, userDataHandle);
160+
hutao::com_ptr<IHutaoNativeHotKeyAction> hotKeyAction = hutao::make_com_ptr<HutaoNativeHotKeyAction>(kind, actionCallback, userDataPtr);
160161
*ppv = hotKeyAction.detach();
161162

162163
return S_OK;

src/Snap.Hutao.Remastered.Native/HutaoNativeHotKeyAction.cpp

Lines changed: 76 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,34 @@
11
#include "HutaoNativeHotKeyAction.h"
2+
#include "HutaoNativeHotKeyActionCallback.h"
23
#include "Error.h"
34
#include <Windows.h>
45
#include <chrono>
6+
#include <thread>
57

68
const wchar_t* WINDOW_CLASS_NAME = L"HutaoNativeHotKeyActionWindowClass";
79
const UINT WM_HOTKEY_MESSAGE = WM_APP + 2;
810

911
UINT HutaoNativeHotKeyAction::s_nextHotKeyId = 0x4000; // 从0x4000开始,避免与系统热键冲突
1012

11-
HutaoNativeHotKeyAction::HutaoNativeHotKeyAction(HutaoNativeHotKeyActionKind kind, HutaoNativeHotKeyActionCallback callback, GCHandle userData)
12-
: m_callback(callback)
13+
HutaoNativeHotKeyAction::HutaoNativeHotKeyAction(HutaoNativeHotKeyActionKind kind, HutaoNativeHotKeyActionCallback callback, nint userData)
14+
: m_kind(kind)
15+
, m_callback(callback)
1316
, m_userData(userData)
14-
, m_kind(kind)
1517
, m_modifiers(0)
1618
, m_vk(0)
1719
, m_enabled(false)
1820
, m_hotKeyId(0)
1921
, m_hWnd(nullptr)
20-
, m_clicking(false)
21-
, m_clickIntervalMs(50) // default 50ms interval
22-
, m_keyPressing(false)
23-
, m_keyIntervalMs(100) // default 100ms interval for key press
24-
, m_active(false)
22+
, m_isRunning(false)
2523
{
2624
m_hotKeyId = static_cast<int>(++s_nextHotKeyId);
2725
}
2826

2927
HutaoNativeHotKeyAction::~HutaoNativeHotKeyAction()
3028
{
3129
SetIsEnabled(FALSE);
32-
33-
StopAutoClick();
34-
StopAutoKeyPress();
35-
30+
StopAction();
31+
3632
if (m_hWnd != nullptr)
3733
{
3834
DestroyWindow(m_hWnd);
@@ -90,27 +86,24 @@ LRESULT CALLBACK HutaoNativeHotKeyAction::WndProc(HWND hWnd, UINT message, WPARA
9086
{
9187
if (message == WM_HOTKEY)
9288
{
93-
// Toggle active state on hotkey press
94-
bool newState = !pThis->m_active.load();
95-
pThis->m_active.store(newState);
96-
97-
// Notify managed side about toggled state
98-
if (pThis->m_callback.value != nullptr)
89+
// 热键被触发,切换动作状态
90+
bool wasRunning = pThis->m_isRunning.load();
91+
92+
if (wasRunning)
9993
{
100-
BOOL isOn = newState ? TRUE : FALSE;
101-
pThis->m_callback.value(isOn, pThis->m_userData);
94+
pThis->StopAction();
10295
}
103-
104-
// Start/stop auto actions based on kind
105-
if (pThis->m_kind == HutaoNativeHotKeyActionKind::MouseClickRepeatForever)
96+
else
10697
{
107-
if (pThis->m_active.load()) pThis->StartAutoClick(); else pThis->StopAutoClick();
98+
pThis->ExecuteAction();
10899
}
109-
else if (pThis->m_kind == HutaoNativeHotKeyActionKind::KeyPressRepeatForever)
100+
101+
// 调用回调函数通知状态变化
102+
if (pThis->m_callback.value != nullptr)
110103
{
111-
if (pThis->m_active.load()) pThis->StartAutoKeyPress(); else pThis->StopAutoKeyPress();
104+
pThis->m_callback.value(!wasRunning ? TRUE : FALSE, pThis->m_userData);
112105
}
113-
106+
114107
return 0;
115108
}
116109
}
@@ -136,85 +129,76 @@ void HutaoNativeHotKeyAction::RegisterHotKey()
136129
::RegisterHotKey(m_hWnd, m_hotKeyId, m_modifiers, m_vk);
137130
}
138131

139-
// Auto-click implementation
140-
void HutaoNativeHotKeyAction::StartAutoClick()
132+
void HutaoNativeHotKeyAction::ExecuteAction()
141133
{
142-
bool expected = false;
143-
if (!m_clicking.compare_exchange_strong(expected, true))
144-
return; // already clicking
145-
146-
// Launch thread
147-
m_clickThread = std::thread([this]() {
148-
// Continue clicking until stopped
149-
while (m_clicking.load())
134+
if (m_isRunning.load())
135+
{
136+
return; // 已经在运行
137+
}
138+
139+
m_isRunning.store(true);
140+
141+
// 启动新线程执行动作
142+
m_actionThread = std::thread([this]() {
143+
while (m_isRunning.load())
150144
{
151-
// Simulate left mouse down and up
152-
INPUT inputs[2];
153-
ZeroMemory(inputs, sizeof(inputs));
154-
155-
inputs[0].type = INPUT_MOUSE;
156-
inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
157-
158-
inputs[1].type = INPUT_MOUSE;
159-
inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
160-
161-
SendInput(2, inputs, sizeof(INPUT));
162-
163-
std::this_thread::sleep_for(std::chrono::milliseconds(m_clickIntervalMs));
145+
if (m_kind == MouseClickRepeatForever)
146+
{
147+
SimulateMouseClick();
148+
}
149+
else if (m_kind == KeyPressRepeatForever)
150+
{
151+
SimulateKeyPress();
152+
}
153+
154+
// 延迟一段时间(例如50ms,即每秒20次)
155+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
164156
}
165157
});
166158
}
167159

168-
void HutaoNativeHotKeyAction::StopAutoClick()
160+
void HutaoNativeHotKeyAction::StopAction()
169161
{
170-
bool expected = true;
171-
if (!m_clicking.compare_exchange_strong(expected, false))
172-
return; // not clicking
173-
174-
if (m_clickThread.joinable())
162+
m_isRunning.store(false);
163+
164+
if (m_actionThread.joinable())
175165
{
176-
m_clickThread.join();
166+
m_actionThread.join();
177167
}
178168
}
179169

180-
// Auto-keypress implementation
181-
void HutaoNativeHotKeyAction::StartAutoKeyPress()
170+
void HutaoNativeHotKeyAction::SimulateMouseClick()
182171
{
183-
bool expected = false;
184-
if (!m_keyPressing.compare_exchange_strong(expected, true))
185-
return; // already pressing
186-
187-
m_keyThread = std::thread([this]() {
188-
// Repeatedly send configured vk or 'F'
189-
WORD vkToSend = (WORD)m_vk ? (WORD)m_vk : 0x46;
190-
INPUT inputs[2];
191-
ZeroMemory(inputs, sizeof(inputs));
192-
inputs[0].type = INPUT_KEYBOARD;
193-
inputs[0].ki.wVk = vkToSend;
194-
inputs[0].ki.dwFlags = 0; // key down
195-
196-
inputs[1].type = INPUT_KEYBOARD;
197-
inputs[1].ki.wVk = vkToSend;
198-
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP; // key up
199-
200-
while (m_keyPressing.load())
201-
{
202-
SendInput(2, inputs, sizeof(INPUT));
203-
std::this_thread::sleep_for(std::chrono::milliseconds(m_keyIntervalMs));
204-
}
205-
});
172+
// 模拟鼠标左键点击
173+
INPUT inputs[2] = {0};
174+
175+
// 按下左键
176+
inputs[0].type = INPUT_MOUSE;
177+
inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
178+
179+
// 释放左键
180+
inputs[1].type = INPUT_MOUSE;
181+
inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
182+
183+
SendInput(2, inputs, sizeof(INPUT));
206184
}
207185

208-
void HutaoNativeHotKeyAction::StopAutoKeyPress()
186+
void HutaoNativeHotKeyAction::SimulateKeyPress()
209187
{
210-
bool expected = true;
211-
if (!m_keyPressing.compare_exchange_strong(expected, false))
212-
return; // not pressing
213-
214-
if (m_keyThread.joinable())
215-
{
216-
m_keyThread.join();
217-
}
188+
// 模拟F键按下(VK_F为0x46)
189+
INPUT inputs[2] = {0};
190+
191+
// 按下F键
192+
inputs[0].type = INPUT_KEYBOARD;
193+
inputs[0].ki.wVk = 0x46; // VK_F
194+
inputs[0].ki.dwFlags = 0;
195+
196+
// 释放F键
197+
inputs[1].type = INPUT_KEYBOARD;
198+
inputs[1].ki.wVk = 0x46; // VK_F
199+
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
200+
201+
SendInput(2, inputs, sizeof(INPUT));
218202
}
219203

220204
HRESULT STDMETHODCALLTYPE HutaoNativeHotKeyAction::Update(int modifiers, uint vk)
@@ -277,6 +261,7 @@ HRESULT STDMETHODCALLTYPE HutaoNativeHotKeyAction::SetIsEnabled(BOOL isEnabled)
277261
{
278262
// 禁用热键
279263
UnregisterHotKey();
264+
StopAction();
280265
}
281266

282267
m_enabled = newEnabled;

src/Snap.Hutao.Remastered.Native/HutaoNativeHotKeyAction.h

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class HutaoNativeHotKeyAction : public hutao::CustomImplements<
1313
IHutaoNativeHotKeyAction>
1414
{
1515
public:
16-
HutaoNativeHotKeyAction(HutaoNativeHotKeyActionKind kind, HutaoNativeHotKeyActionCallback callback, GCHandle userData);
16+
HutaoNativeHotKeyAction(HutaoNativeHotKeyActionKind kind, HutaoNativeHotKeyActionCallback callback, nint userData);
1717
~HutaoNativeHotKeyAction();
1818

1919
// IHutaoNativeHotKeyAction methods
@@ -22,14 +22,16 @@ class HutaoNativeHotKeyAction : public hutao::CustomImplements<
2222
virtual HRESULT STDMETHODCALLTYPE SetIsEnabled(BOOL isEnabled) override;
2323

2424
private:
25-
HutaoNativeHotKeyActionCallback m_callback;
26-
GCHandle m_userData;
27-
HutaoNativeHotKeyActionKind m_kind;
25+
HutaoNativeHotKeyActionKind m_kind;
26+
HutaoNativeHotKeyActionCallback m_callback;
27+
nint m_userData;
2828
int m_modifiers;
2929
uint m_vk;
3030
bool m_enabled;
3131
int m_hotKeyId;
3232
HWND m_hWnd;
33+
std::atomic<bool> m_isRunning;
34+
std::thread m_actionThread;
3335
static UINT s_nextHotKeyId;
3436

3537
// running state toggled by WM_HOTKEY
@@ -41,21 +43,14 @@ class HutaoNativeHotKeyAction : public hutao::CustomImplements<
4143
// Window helpers
4244
static ATOM RegisterWindowClass();
4345
HWND CreateMessageWindow();
44-
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
45-
46-
// Auto-click support
47-
std::thread m_clickThread;
48-
std::atomic<bool> m_clicking;
49-
int m_clickIntervalMs;
50-
51-
void StartAutoClick();
52-
void StopAutoClick();
53-
54-
// Auto-keypress support (for KeyPressRepeatForever)
55-
std::thread m_keyThread;
56-
std::atomic<bool> m_keyPressing;
57-
int m_keyIntervalMs;
58-
59-
void StartAutoKeyPress();
60-
void StopAutoKeyPress();
46+
void UnregisterHotKey();
47+
void RegisterHotKey();
48+
49+
// 动作执行函数
50+
void ExecuteAction();
51+
void StopAction();
52+
53+
// 输入模拟函数
54+
void SimulateMouseClick();
55+
void SimulateKeyPress();
6156
};

0 commit comments

Comments
 (0)