簡單實現.NET Hook與事件模擬

波多爾斯基發表於2023-10-27

最近玩《星露穀物語》上癮,本來是看著個休閒遊戲,現在玩成修仙遊戲了,上百個小時渾身是肝,中午午休習慣都強行給改了。

雖然挺有意思,但是太肝了,入坑前請謹慎。補充一下,這個遊戲應該是基於 XNA/MonoGame 寫的。

這個遊戲在喪失焦點的時候會自動暫停,無法自動推進,我覺得效率太低了,為了齊先生的場子,我得搞一個自動點選的東西。

不想下載軟體就自己寫一個吧,因為要保證遊戲始終在前面,那肯定開關需要啟用全域性快捷鍵。找了一下,. NET 有一個 SharpHook (tolik.io) 就挺簡單的,花幾分鐘寫了一個,實現了功能。

SharpHook 是一個跨平臺的 Hook 元件,核心基於 libuiohook

監聽事件

官網的文件非常簡潔易懂,我設定快捷鍵監聽,監聽按鍵按下。

var hook = new TaskPoolGlobalHook();
hook.HookEnabled += OnHookEnabled;     // EventHandler<HookEventArgs>
hook.HookDisabled += OnHookDisabled;   // EventHandler<HookEventArgs>

hook.KeyTyped += OnKeyTyped;           // EventHandler<KeyboardHookEventArgs>

hook.Run();

然後在事件中設定定時器啟動以及停止,我目標是每隔兩秒鐘按滑鼠左鍵一次。

private static void OnKeyTyped(object? sender, KeyboardHookEventArgs e)
{
    if (e.SuppressEvent) return;
    if (e.Data.KeyCode.HasFlag(KeyCode.VcSemicolon)) // ;鍵
    {
        Console.WriteLine("start timer");
        _timer.Start();
    }
    else if (e.Data.KeyCode.HasFlag(KeyCode.VcL)) //L鍵
    {
        Console.WriteLine("stop timer");
        _timer.Stop();
    }
    e.SuppressEvent = true;
}

模擬事件

這個庫同樣可以模擬滑鼠和鍵盤的操作,我這裡操作滑鼠,鍵盤也是同理。

static EventSimulator _simulator = new EventSimulator();
private static void _timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
	_simulator.SimulateMousePress(MouseButton.Button1);
	Thread.Sleep(100);
	_simulator.SimulateMouseRelease(MouseButton.Button1);
}

注意,很多遊戲是單獨監聽滑鼠的按下與鬆開的,這樣算一次完整的點選,如果中間沒有設定延時,有可能識別不滑鼠的動作。這個遊戲就是這樣,沒有延時就不行。

好了,執行之後放在後臺,在遊戲獲取焦點的時候,按";"啟動,然後滑鼠懸停在物品上面就能自動拿起/放下了,按“L”退出。

image

鍵位與其他

參考 Key Code Mappings | SharpHook (tolik.io) 看鍵名稱與 Key Code。除錯的時候,如果在 OnKeyTyped 事件中設定斷點會有一下子非常卡,耐心一點就正常了。

另外,我 Hook 上方 F 功能鍵的時候一直不成功,但是 ESC 是可以正常被響應的,沒有深入去研究為什麼,以後真完全有必要了再看看。

相關文章