沒有 WPF 背景,靠 AI 做出 Windows 滑鼠特效工具
AIY-Cursor 是一個給遊戲影片用的即時滑鼠特效工具。開始做之前,我完全沒有 WPF、Win32 API 或 C# 桌面程式的背景。這篇記錄為什麼做、怎麼做到的。
問題從遊戲影片開始
上傳遊戲遊玩影片的時候,遇到兩個問題同時存在:
一是原創性。純錄影的畫面和其他人的相似度太高,平台容易判定為搬運或低原創度。 二是游標看不見。影片裡的游標幾乎不可見,觀眾看不出你的操作在哪、在幹嘛。
找了一圈現有的工具。免費的功能不完整,特效種類少、通常沒音效。 付費的像 YoloMouse(Steam,$4 USD)解決的是另一個問題——在遊戲裡看清楚游標,替換游標形狀——但不是「讓影片畫面有視覺特效」,而且也沒有音效功能。
每個功能單獨看都不複雜,但沒有一個工具把它們組在一起。
AIY = AI + Y(為什麼不試試)
問題清楚了,但我完全沒有 Windows 桌面程式開發的背景:沒有 WPF、沒有 Win32 API、沒有 C# 桌面開發。
剛好 AI 輔助開發已經成熟到一個程度,我想測試一件事:靠 AI 協作,一個沒有相關背景的人,能不能做出這種工具?
AIY-Cursor 是這個測試的結果。從架構設計到逐行程式碼,全程在 Claude 的協助下完成。 「AIY」取自 AI + Y,Y 是「為什麼不試試」。
覆蓋層,不是游標替換
最核心的技術決策是:不替換游標本身,而是在所有視窗最上面蓋一層全螢幕透明視窗,特效畫在那層上面。
為什麼不替換游標?因為游標圖示是靜態的,加不了動態特效——漣漪消失動畫、粒子四散、吐火效果都需要動態繪製。靜態圖示做不到這件事。
覆蓋層的做法有一個必要的 Win32 呼叫,叫 WS_EX_TRANSPARENT:
SetWindowLong(hwnd, GWL_EXSTYLE,
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW);
這行讓視窗在視覺上存在,但滑鼠事件完全穿透——底下的程式收得到點擊,特效不會擋到操作。
WPF 本身的 AllowsTransparency="True" 只是「視覺透明」,視窗還是在攔截輸入。這個坑幾乎每個第一次做 WPF 覆蓋層的人都會踩。
Hook 的 300ms 限制
用 WH_MOUSE_LL 全域 Hook 截取滑鼠事件,但 Windows 有個規定:Hook 回呼函式必須在 300ms 內返回,否則 Hook 被強制移除。移除不會有任何錯誤,就是靜默消失,特效突然不動了。
解法是讓回呼函式什麼都不做,只是把事件丟進 queue,實際的 UI 更新用 Dispatcher.BeginInvoke(非同步)。MouseMove 額外做 16ms 節流(約 60fps),避免事件洪流讓回呼積壓超時。
音效疊加:NAudio MixingSampleProvider
滑鼠快速連點的時候,前一個音效還沒播完,新的點擊聲應該疊上去,而不是截斷前一個。
Windows 內建的 SoundPlayer 做不到這件事,MediaPlayer 延遲也不穩定。
NAudio 的 MixingSampleProvider 的做法是:每次播放只是向 Mixer 加一個新的 Provider 實例。快速連點會自然疊放,延遲極低,也不會相互干擾。
Scroll Lock 總開關
Scroll Lock 幾乎沒有程式或遊戲用到,也不會被全螢幕遊戲攔截。按一下關閉所有特效和音效,再按一下恢復。
實際使用場景:用 OCam 框選錄影區域時,要暫停特效——兩個 TOPMOST 視窗競爭 Z-order,特效層會擋住 OCam 的框選操作。按一下 Scroll Lock 暫停,框完再按一下恢復,五秒解決。
5 組內建方案
設定介面有 5 組從保守到個性化的內建方案:
- 規格書原版:淡藍漣漪 + 細線尾跡,適合輔助教學影片
- 醒目錄影:高飽和度,操作點明顯
- 夜光粒子:深色系,適合夜間遊戲畫面
- 充電蓄力:充電繞圈 + 閃爍放電,RPG 蓄力感
- 恐龍小爪:吐火點擊 + 地裂尾跡 + 酷斯拉背脊長按
整個專案的結論是:AI 輔助開發讓「領域外的工具」變得可行。不是說 AI 寫了所有程式碼,而是 AI 讓「我不懂這個領域,但我可以描述我要的行為」這件事變成一條可行的路徑。
AIY-Cursor 是工具,也是這條路徑的測試結果。