文章目录
在 WINDOWS 下编程控制游戏手柄比较主流的技术是用 DirectInput。如果不需要复杂的控制功能,也可以直接使用 WIN API (multimedia joystick API)。来完成简单控制。在 windows 系统中,最多可以同时监控两个游戏手柄,每个游戏手柄最多可以有四个控制键。在程序中既可以直接读取游戏手柄的位置信息和按键状态,也可以通过监控相应的系统消息的方式来获得游戏手柄的信息。多数时候我们在程序中都采用接收游戏手柄消息的方式,因为这种方式不需要定时轮询游戏手柄的状态。游戏手柄相关的函数都封装在 Winmm.dll 中。相应的头文件是 mmsystem.h, 链接时需要链接 WINMM.lib。源代码如下所示:
- 1.关键函数
- 1.1 joySetCapture
- 1.2 joyReleaseCapture
- 2.游戏窗口消息
- 3.简单案例
- 4.作者答疑
#include
#pragma comment(lib, "WINMM.lib")
1.关键函数
1.1 joySetCapture
joySetCapture函数通过将消息发送到指定窗口来捕获游戏杆。函数结构如下:
MMRESULT joySetCapture(
HWND hwnd,//处理窗口以接收操纵杆消息。
UINT uJoyID,//要捕获的操纵杆的标识符。uJoyID的有效值范围从零 (JOYSTICKID1) 到 15。
UINT uPeriod,//轮询频率,以毫秒为单位。
BOOL fChanged//更改位置标志。将此参数指定为TRUE以仅在位置更改的值大于操纵杆移动阈值时发送消息。否则,将以uPeriod中指定的轮询频率发送消息。
);
返回值:如果成功或以下错误值之一,则返回 JOYERR_NOERROR。
返回码描述MMSYSERR_NODRIVER操纵杆驱动程序不存在。MMSYSERR_INVALPARAM无效的操纵杆 ID 或 hwnd 为NULL。JOYERR_NOCANDO无法捕获操纵杆输入,因为所需的服务(例如 Windows 计时器)不可用。JOYERR_UNPLUGGED指定的操纵杆未连接到系统。JOYERR_PARMS无效的操纵杆 ID 或 hwnd 为NULL。部分范例代码,如下所示:
UINT result =::joySetCapture(CDialog::m_hWnd, JOYSTICKID1, 0, FALSE);
if(result == JOYERR_NOCANDO)
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox("不能捕获游戏杆", NULL, MB_OK | MB_ICONEXCLAMATION);
return -1;
}
if(result == JOYERR_UNPLUGGED)
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox("游戏杆未与系统连接", NULL, MB_OK | MB_ICONEXCLAMATION);
return -1;
}
1.2 joyReleaseCapture
joyReleaseCapture函数释放指定捕获的操纵杆。函数结构如下:
MMRESULT joyReleaseCapture(
UINT uJoyID//要释放的操纵杆的标识符。uJoyID的有效值范围从零 (JOYSTICKID1) 到 15。
);
返回值:如果成功或以下错误值之一,则返回 JOYERR_NOERROR。
返回码描述MMSYSERR_NODRIVER操纵杆驱动程序不存在。MMSYSERR_INVALIDPARAM指定的操纵杆设备标识符uJoyID无效。JOYERR_PARMS指定的操纵杆设备标识符uJoyID无效。部分范例代码,如下所示:
joyReleaseCapture(JOYSTICKID1);
2.游戏窗口消息
在Win32中,支持窗口消息有三个MM_JOY1BUTTONDOWN、MM_JOY1MOVE、MM_JOY1BUTTONUP、MM_JOY2BUTTONDOWN、MM_JOY2MOVE和MM_JOY2BUTTONUP。通过这六个消息来接受两个手柄。
3.简单案例下面在MFC的消息函数中,展示如何接受游戏消息:
LRESULT CMyjoystickDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case MM_JOY1BUTTONDOWN :
if (wParam & JOY_BUTTON1)
{
MessageBeep(MB_ICONQUESTION);
SetDlgItemText(IDC_BUTTON1, "按下");
}
if (wParam & JOY_BUTTON2)
{
MessageBeep(MB_ICONEXCLAMATION);
SetDlgItemText(IDC_BUTTON2, "按下");
m_btn2.SetCheck(BST_CHECKED);
}
if (wParam & JOY_BUTTON3)
{
SetDlgItemText(IDC_BUTTON3, "按下");
}
if (wParam & JOY_BUTTON4)
{
SetDlgItemText(IDC_BUTTON4, "按下");
}
case MM_JOY1MOVE :
WORD x, y;
POINT pt;
//UpdateData(TRUE);
//获取当前屏幕光标位置
GetCursorPos(&pt);
//游戏杆在当前系统中的位置坐标范围从0 65535。位置表示范围从0-31
if (!m_Absolute)
{
x = LOWORD(lParam) / 2048;
y = HIWORD(lParam) / 2048;
//如果游戏杆在中心位置的左边,移动光标到左边。反之亦然
if(x = 20)
pt.x = pt.x + x - 15;
//如果游戏杆在中心位置的下边,移动光标到下边。反之亦然
if(y = 20)
pt.y = pt.y + y - 15;
}
else
{
CDC *pDC = GetDC();
x = LOWORD(lParam);
y = HIWORD(lParam);
pt.x = (pDC->GetDeviceCaps(HORZRES) * x) / 65536;
pt.y = (pDC->GetDeviceCaps(VERTRES) * y) / 65536;
ReleaseDC(pDC);
}
/* Set the new cursor position.*/
SetCursorPos(pt.x, pt.y);
break;
case MM_JOY1BUTTONUP :
SetDlgItemText(IDC_BUTTON1, "1");
SetDlgItemText(IDC_BUTTON2, "2");
SetDlgItemText(IDC_BUTTON3, "3");
SetDlgItemText(IDC_BUTTON4, "4");
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
4.作者答疑
代码长度过长,如需全部项目或有疑问,请留言。
提示: 作者知了-联系方式1 提示: 作者知了-联系方式2