/*
JoyToMouse.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
版本:
1.0.0
功能:
将游戏手柄操作映射为鼠标操作。
原理:
接收手柄消息,然后产生相应鼠标消息。
使用:
方向键移动(会自动加速);
键 1 <==> 左键;
键 2 <==> 右键;
键 3 <==> 调整灵敏度,增加;
键 4 <==> 调整灵敏度,减小。
*/
#include <Windows.h>
#include <MMSystem.h>
#pragma comment( lib, "winmm.lib" )
/* 每 ELAPSE 毫秒检测手柄输入 */
#define ELAPSE 17
/* 速度 mickeys / ELAPSE */
INT BASE_VX = 4;
INT BASE_VY = 4;
/* 加速度 mickeys / ELAPSE / ELAPSE */
INT ACCEL_VX = 8;
INT ACCEL_VY = 8;
/* 加加速度 mickeys / ELAPSE / ELAPSE / ELAPSE */
#define ACCEL_ACCEL_VX 1
#define ACCEL_ACCEL_VY 1
/* 方向标志 */
#define MASK_LEFT ((DWORD)1)
#define MASK_RIGHT ((DWORD)2)
#define MASK_UP ((DWORD)4)
#define MASK_DOWN ((DWORD)8)
TCHAR gClassName[] = TEXT("JoyToMouse");
TCHAR gWndName[] = TEXT("JoyToMouse -- coreBugZJ");
VOID msgOut( HWND hWnd, TCHAR msg[], UINT msglen ) {
HDC hdc = GetDC( hWnd );
TextOut( hdc, 50, 20, msg, msglen );
ReleaseDC( hWnd, hdc );
/* MessageBox( NULL, msg, msg, MB_OK ); */
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
static JOYINFO ji1;
static DWORD id1 = 0xFFFF;
static JOYCAPS jc1;
static DWORD numDev;
static DWORD jxm1, jxl1, jxr1, jym1, jyt1, jyb1, x1, y1;
static DWORD dirMask = 0;
static INT vx = 0, vy = 0;
INT dx, dy;
DWORD bf;
switch ( uMsg ) {
case WM_CREATE :
SetTimer( hWnd, 1, ELAPSE, NULL );
if ( 0 == (numDev = joyGetNumDevs()) ) {
MessageBox( hWnd, TEXT("0 == joyGetNumDevs()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
SendMessage( hWnd, WM_DESTROY, 0, 0 );
return 0;
}
// 手柄 1
if ( JOYERR_NOERROR != joyGetPos( JOYSTICKID1, &ji1 ) ) {
MessageBox( hWnd, TEXT("JOYERR_NOERROR != joyGetPos()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
SendMessage( hWnd, WM_DESTROY, 0, 0 );
return 0;
}
if ( JOYERR_NOERROR != joyGetDevCaps( JOYSTICKID1, &jc1, sizeof(jc1) ) ) {
MessageBox( hWnd, TEXT("JOYERR_NOERROR != joyGetDevCaps()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
SendMessage( hWnd, WM_DESTROY, 0, 0 );
return 0;
}
id1 = JOYSTICKID1;
jxm1 = ( jc1.wXmin + jc1.wXmax ) / 2;
jxl1 = ( jc1.wXmin + jxm1 ) / 2;
jxr1 = ( jc1.wXmax + jxm1 ) / 2;
jym1 = ( jc1.wYmin + jc1.wYmax ) / 2;
jyt1 = ( jc1.wYmin + jym1 ) / 2;
jyb1 = ( jc1.wYmax + jym1 ) / 2;
x1 = jxm1;
y1 = jym1;
joySetCapture( hWnd, id1, ELAPSE, TRUE );
return 0;
case WM_TIMER :
if ( 0 == dirMask ) {
return 0;
}
dx = dy = 0;
if ( dirMask & MASK_LEFT ) {
vx += ACCEL_VX;
dx = -vx;
}
if ( dirMask & MASK_RIGHT ) {
vx += ACCEL_VX;
dx = vx;
}
if ( dirMask & MASK_UP ) {
vy += ACCEL_VY;
dy = -vy;
}
if ( dirMask & MASK_DOWN ) {
vy += ACCEL_VY;
dy = vy;
}
msgOut( hWnd, TEXT("MOVE "), 12 );
mouse_event( MOUSEEVENTF_MOVE, dx, dy, 0, 0 );
return 0;
case MM_JOY1MOVE :
dirMask = 0;
x1 = LOWORD(lParam);
y1 = HIWORD(lParam);
if ( x1 < jxl1 ) {
dirMask |= MASK_LEFT;
vx = BASE_VX;
msgOut( hWnd, TEXT("LEFT1 DOWN "), 12 );
}
if ( x1 > jxr1 ) {
dirMask |= MASK_RIGHT;
vx = BASE_VX;
msgOut( hWnd, TEXT("RIGHT1 DOWN "), 12 );
}
if ( y1 < jyt1 ) {
dirMask |= MASK_UP;
vy = BASE_VY;
msgOut( hWnd, TEXT("UP1 DOWN "), 12 );
}
if ( y1 > jyb1 ) {
dirMask |= MASK_DOWN;
vy = BASE_VY;
msgOut( hWnd, TEXT("DOWN1 DOWN "), 12 );
}
return 0;
case MM_JOY1BUTTONDOWN :
bf = wParam;
if ( (bf & JOY_BUTTON1CHG) && (bf & JOY_BUTTON1) ) {
mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
msgOut( hWnd, TEXT("BTN11 DOWN "), 12 );
}
if ( (bf & JOY_BUTTON2CHG) && (bf & JOY_BUTTON2) ) {
mouse_event( MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0 );
msgOut( hWnd, TEXT("BTN12 DOWN "), 12 );
}
if ( (bf & JOY_BUTTON3CHG) && (bf & JOY_BUTTON3) ) {
ACCEL_VX += ACCEL_ACCEL_VX;
ACCEL_VY += ACCEL_ACCEL_VY;
BASE_VX += ACCEL_VX;
BASE_VY += ACCEL_VY;
msgOut( hWnd, TEXT("BTN13 DOWN "), 12 );
}
if ( (bf & JOY_BUTTON4CHG) && (bf & JOY_BUTTON4) ) {
BASE_VX -= ACCEL_VX;
BASE_VY -= ACCEL_VY;
if ( BASE_VX < 1 ) {
BASE_VX = 1;
}
if ( BASE_VY < 1 ) {
BASE_VY = 1;
}
ACCEL_VX -= ACCEL_ACCEL_VX;
ACCEL_VY -= ACCEL_ACCEL_VY;
if ( ACCEL_VX < 0 ) {
ACCEL_VX = 0;
}
if ( ACCEL_VY < 0 ) {
ACCEL_VY = 0;
}
msgOut( hWnd, TEXT("BTN14 DWON "), 12 );
}
return 0;
case MM_JOY1BUTTONUP :
bf = wParam;
if ( (bf & JOY_BUTTON1CHG) && (0 == (bf & JOY_BUTTON1)) ) {
mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
msgOut( hWnd, TEXT("BTN11 UP "), 12 );
}
if ( (bf & JOY_BUTTON2CHG) && (0 == (bf & JOY_BUTTON2)) ) {
mouse_event( MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 );
msgOut( hWnd, TEXT("BTN12 UP "), 12 );
}
if ( (bf & JOY_BUTTON3CHG) && (0 == (bf & JOY_BUTTON3)) ) {
msgOut( hWnd, TEXT("BTN13 UP "), 12 );
}
if ( (bf & JOY_BUTTON4CHG) && (0 == (bf & JOY_BUTTON4)) ) {
msgOut( hWnd, TEXT("BTN14 UP "), 12 );
}
return 0;
case WM_DESTROY :
KillTimer( hWnd, 1 );
if ( JOYSTICKID1 == id1 ) {
joyReleaseCapture( id1 );
}
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmd, INT nShow ) {
WNDCLASSEX wc;
HWND hWnd;
MSG msg;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(wc);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
wc.hInstance = hInst;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = gClassName;
wc.lpszMenuName = NULL;
wc.style = 0;
if ( 0 == RegisterClassEx( &wc ) ) {
MessageBox( NULL, TEXT("RegisterClassEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
return 0;
}
hWnd = CreateWindowEx( 0,
gClassName, gWndName,
WS_OVERLAPPEDWINDOW,
200, 200, 400, 100,
NULL, NULL,
hInst, NULL );
if ( NULL == hWnd ) {
MessageBox( NULL, TEXT("CreateWindowEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
return 0;
}
ShowWindow( hWnd, nShow );
UpdateWindow( hWnd );
while ( GetMessage( &msg, NULL, 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return msg.wParam;
}