購買北通 USB 手柄玩懷舊模擬器後,靈機一動:能否寫外掛讓手柄玩 Flash 遊戲?Flash 不支援手柄 API,但可透過外掛將手柄事件轉鍵盤/滑鼠事件。網路多為 C++ 範例,本系列以 C# 實作完整流程。
joySetCapture 向系統註冊,系統定時推送訊息到視窗。joyGetPos/joyGetPosEx 主動查詢。本篇專注被動模式。
| 函數 | 說明 |
|---|---|
| joyGetNumDevs | 取得系統支援手裝置數量 |
| joyGetDevCaps | 查詢裝置效能規格 |
| joySetCapture | 申請捕捉裝置,系統定時推送狀態訊息 |
| joyReleaseCapture | 釋放捕捉 |
| joyGetPos | 取得座標與按鈕狀態 (4 鍵) |
| joyGetPosEx | 取得座標與按鈕狀態 (32 鍵) |
| joyGetThreshold | 查詢移動閾值 |
| joySetThreshold | 設定移動閾值 |
[DllImport("winmm.dll")]
public static extern int joySetCapture(
IntPtr hWnd, // 視窗控制代碼
int uJoyID, // 裝置 ID (0-15),JOYSTICKID1 或 JOYSTICKID2
int uPeriod, // 輪詢間隔 (毫秒)
bool fChanged // 是否僅在移動超過閾值才通知
);
JOYERR_NOERROR (0),失敗回傳非零錯誤碼。joyReleaseCapture 釋放。重寫 WndProc 處理訊息。針對 JOYSTICKID1:
| 訊息編號 | 說明 |
|---|---|
| MM_JOY1MOVE | 位置變動或按鈕按下 (持續推送,即使未操作) |
| MM_JOY1BUTTONDOWN | A/B/C/D 四鍵任一按下 |
| MM_JOY1BUTTONUP | A/B/C/D 四鍵任一釋放 |
JOYSTICKID2 對應 MM_JOY2MOVE、MM_JOY2BUTTONDOWN、MM_JOY2BUTTONUP。
重要:MM_JOYXMOVE 會持續推送,無論是否操作!
JOY_BUTTON1 | JOY_BUTTON2)。BUTTONDOWN/UP 的按鈕值定義與 MOVE 不同!private void GetXYButtonsStateFromLParam(int lParam, ref JoystickButtons buttons)
{
int x = lParam & 0x0000FFFF; // 低 16 位 X
int y = (int)((lParam & 0xFFFF0000) >> 16); // 高 16 位 Y
int m = 0x7EFF; // 中心點數值
if (x > m) buttons |= JoystickButtons.Right;
else if (x < m) buttons |= JoystickButtons.Left;
if (y > m) buttons |= JoystickButtons.Down;
else if (y < m) buttons |= JoystickButtons.Up;
}
joySetCapture 註冊視窗接收訊息。WndProc 解析 MM_JOYXMOVE、BUTTONDOWN、BUTTONUP。LParam 解析方向鍵,WParam 解析功能鍵。