| 函數 | 用途 |
|---|---|
joySetCapture(hwnd, uJoyID, uPeriod, fChanged) | 捕獲搖桿,指定接收視窗、輪詢週期 |
joyReleaseCapture(uJoyID) | 釋放捕獲 |
搖桿 ID:JOYSTICKID1 / JOYSTICKID2。輪詢週期單位毫秒,0 表使用預設。
BEGIN_MESSAGE_MAP)class TForm1 : public TForm {
__published:
// IDE 元件...
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
private:
void __fastcall OnJoyDown(TMessage &Message); // MM_JOY1BUTTONDOWN
void __fastcall OnJoyMove(TMessage &Message); // MM_JOY1MOVE
public:
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(MM_JOY1BUTTONDOWN, TMessage, OnJoyDown)
MESSAGE_HANDLER(MM_JOY1MOVE, TMessage, OnJoyMove)
END_MESSAGE_MAP(TForm)
};
#include
#pragma hdrstop
#include "Unit1.h"
#include // joy API、MM_* 訊息常數
#pragma comment(lib, "winmm.lib")
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {}
void __fastcall TForm1::FormCreate(TObject *Sender) {
int res = joySetCapture(Handle, JOYSTICKID1, 0, FALSE);
switch (res) {
case JOYERR_NOCANDO: ShowMessage("無法捕獲搖桿!"); break;
case JOYERR_UNPLUGGED: ShowMessage("搖桿未連接!"); break;
case MMSYSERR_NODRIVER: ShowMessage("系統未安裝搖桿驅動!"); break;
default: ShowMessage("捕獲搖桿成功!");
}
}
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) {
joyReleaseCapture(JOYSTICKID1);
}
// 搖桿按鈕 → 滑鼠點擊
void __fastcall TForm1::OnJoyDown(TMessage &Message) {
if (Message.WParam & JOY_BUTTON1) {
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Caption = "左鍵按下";
}
if (Message.WParam & JOY_BUTTON2) {
mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
Caption = "右鍵按下";
}
if (Message.WParam & JOY_BUTTON3) {
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Caption = "左鍵抬起";
}
if (Message.WParam & JOY_BUTTON4) {
mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
Caption = "右鍵抬起";
}
TForm::Dispatch(&Message); // 繼續傳遞,防止訊息死結
}
// 搖桿移動 → 滑鼠游標位移
void __fastcall TForm1::OnJoyMove(TMessage &Message) {
POINT pt; GetCursorPos(&pt);
int x = LOWORD(Message.LParam);
int y = HIWORD(Message.LParam);
// 32768 為中立位置(視驅動而定),非中立才移動
if (x != 32768) {
pt.x += (x > 32768) ? 10 : -10; // 簡化:直接判斷正負
}
if (y != 32768) {
pt.y += (y > 32768) ? 10 : -10;
}
SetCursorPos(pt.x, pt.y);
TForm::Dispatch(&Message);
}
MM_JOY1MOVE (0x3A0)、MM_JOY1BUTTONDOWN (0x3A5) 需自行包含 mmsystem.h。if (x) … else … 判斷方向,實際應以中立值(通常 32768)為基準,避免微小抖動觸發移動。uJoyID 分別為 0/1。MM_JOY1BUTTONUP 處理長按/雙擊邏輯。XInput (Xbox 手柄) 以支援現代手柄。透過 joySetCapture + 自定義訊息映射 + mouse_event,僅百行代碼即可完成搖桿模擬滑鼠。這不僅是經典多媒體編程練習,更展示了 Windows 訊息機制的靈活性。有舊搖桿吃灰的朋友,快拿出來試試吧!