首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder 遊戲搖桿模擬滑鼠:自定義訊息映射實作完整教學

     編輯:關於C++

核心 API 速覽

函數用途
joySetCapture(hwnd, uJoyID, uPeriod, fChanged)捕獲搖桿,指定接收視窗、輪詢週期
joyReleaseCapture(uJoyID)釋放捕獲

搖桿 ID:JOYSTICKID1 / JOYSTICKID2。輪詢週期單位毫秒,0 表使用預設。

C++Builder 自定義訊息映射三步驟

  1. 類別宣告中建立映射表(BEGIN_MESSAGE_MAP)
  2. 私有區宣告處理函數
  3. CPP 實作處理函數

完整代碼實作

Unit1.h — 宣告區

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)
};

Unit1.cpp — 實作區

#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);
}

關鍵細節提醒

  1. 訊息常數未預定義:MM_JOY1MOVE (0x3A0)、MM_JOY1BUTTONDOWN (0x3A5) 需自行包含 mmsystem.h。
  2. Dispatch 必加:若攔截訊息不傳遞,視窗無法處理 WM_PAINT、WM_TIMER 等系統訊息,導致介面凍結。
  3. 座標閾值:原碼用 if (x) … else … 判斷方向,實際應以中立值(通常 32768)為基準,避免微小抖動觸發移動。
  4. 多搖桿支援:若需同時支援兩支,建立兩組捕獲/處理邏輯,uJoyID 分別為 0/1。

擴充靈感

  • 加入 死區 與 加速度曲線,提升操作手感。
  • 對應 MM_JOY1BUTTONUP 處理長按/雙擊邏輯。
  • 整合 XInput (Xbox 手柄) 以支援現代手柄。
  • 將搖桿映射為鍵盤巨集,玩不支援手柄的遊戲。

結語

透過 joySetCapture + 自定義訊息映射 + mouse_event,僅百行代碼即可完成搖桿模擬滑鼠。這不僅是經典多媒體編程練習,更展示了 Windows 訊息機制的靈活性。有舊搖桿吃灰的朋友,快拿出來試試吧!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved