本想用游戏手柄玩模拟器游戏的,可惜
游戏手柄在本机上可以使用,然而在虚拟机中无法使用(本机为Win7,手柄为北通战戟,虚拟机为VirtualBox4.0.12),
而我的模拟器游戏都装在虚拟的WinXP中,因为我不放心这些模拟器呀。
于是:
  1
 /**//*
/**//*
  2 JoyToKey.cpp
JoyToKey.cpp
  3
  4 Copyright (C) 2011, coreBugZJ, all rights reserved.
Copyright (C) 2011, coreBugZJ, all rights reserved.
  5
  6 功能:
功能:
  7 将游戏手柄操作映射为键盘按键操作。
将游戏手柄操作映射为键盘按键操作。
  8
  9 原理:
原理:
 10 接收手柄消息,然后产生相应键盘消息。
接收手柄消息,然后产生相应键盘消息。
 11
 12 上 W
上 W
 13 下 S
下 S
 14 左 A
左 A
 15 右 D
右 D
 16
 17 1  U
1  U
 18 2  I
2  I
 19 3  J
3  J
 20 4  K
4  K
 21
 22 */
*/
 23
 24
 25 #include <Windows.h>
#include <Windows.h>
 26 #include <MMSystem.h>
#include <MMSystem.h>
 27
 28
 29 #pragma comment( lib, "winmm.lib" )
#pragma comment( lib, "winmm.lib" )
 30
 31
 32 TCHAR gClassName[] = TEXT("JoyToKey");
TCHAR gClassName[] = TEXT("JoyToKey");
 33 TCHAR gWndName[]   = TEXT("JoyToKey -- coreBugZJ");
TCHAR gWndName[]   = TEXT("JoyToKey -- coreBugZJ");
 34
 35
 36 #define  ID_TIMER  1
#define  ID_TIMER  1
 37 #define  ELAPSE    50
#define  ELAPSE    50
 38
 39
 40
 VOID errorOut( HWND hWnd, TCHAR msg[], UINT msglen )
VOID errorOut( HWND hWnd, TCHAR msg[], UINT msglen )  {
{
 41 HDC hdc = ::GetDC( hWnd );
        HDC hdc = ::GetDC( hWnd );
 42 ::TextOut( hdc, 50, 50, msg, msglen );
        ::TextOut( hdc, 50, 50, msg, msglen );
 43 ::ReleaseDC( hWnd, hdc );
        ::ReleaseDC( hWnd, hdc );
 44 }
}
 45
 46 #define  MAKEKEY(k)  do { \
#define  MAKEKEY(k)  do { \
 47 ::keybd_event( k, MapVirtualKey(k,0), 0, 0 ); \
                ::keybd_event( k, MapVirtualKey(k,0), 0, 0 ); \
 48 ::Sleep( 50 ); \
                ::Sleep( 50 ); \
 49 ::keybd_event( k, MapVirtualKey(k,0), KEYEVENTF_KEYUP, 0 ); \
                ::keybd_event( k, MapVirtualKey(k,0), KEYEVENTF_KEYUP, 0 ); \
 50 } while ( 0 )
        } while ( 0 )
 51
 52
 LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )  {
{
 53 static JOYINFO ji;
        static JOYINFO ji;
 54 static UINT    id = 0xFFFF;
        static UINT    id = 0xFFFF;
 55 static JOYCAPS jc;
        static JOYCAPS jc;
 56 static INT jxl, jxr, jyt, jyb, jxm, jym;
        static INT jxl, jxr, jyt, jyb, jxm, jym;
 57
 58
 switch ( uMsg )
        switch ( uMsg )  {
{
 59 case WM_CREATE :
        case WM_CREATE : 
 60
 if ( 0 == ::joyGetNumDevs() )
                if ( 0 == ::joyGetNumDevs() )  {
{
 61 ::MessageBox( hWnd, TEXT("0 == ::joyGetNumDevs()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
                        ::MessageBox( hWnd, TEXT("0 == ::joyGetNumDevs()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
 62 ::SendMessage( hWnd, WM_DESTROY, 0, 0 );
                        ::SendMessage( hWnd, WM_DESTROY, 0, 0 );
 63 return 0;
                        return 0;
 64 }
                }
 65
 66
 if ( JOYERR_UNPLUGGED == ::joyGetPos( JOYSTICKID1, &ji ) )
                if ( JOYERR_UNPLUGGED == ::joyGetPos( JOYSTICKID1, &ji ) )  {
{
 67 ::MessageBox( hWnd, TEXT("JOYERR_UNPLUGGED == ::joyGetPos()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
                        ::MessageBox( hWnd, TEXT("JOYERR_UNPLUGGED == ::joyGetPos()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
 68 ::SendMessage( hWnd, WM_DESTROY, 0, 0 );
                        ::SendMessage( hWnd, WM_DESTROY, 0, 0 );
 69 return 0;
                        return 0;
 70 }
                }
 71
 72
 if ( JOYERR_NOERROR != ::joyGetDevCaps( JOYSTICKID1, &jc, sizeof(jc) ) )
                if ( JOYERR_NOERROR != ::joyGetDevCaps( JOYSTICKID1, &jc, sizeof(jc) ) )  {
{
 73 ::MessageBox( hWnd, TEXT("JOYERR_NOERROR != ::joyGetDevCaps()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
                        ::MessageBox( hWnd, TEXT("JOYERR_NOERROR != ::joyGetDevCaps()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
 74 ::SendMessage( hWnd, WM_DESTROY, 0, 0 );
                        ::SendMessage( hWnd, WM_DESTROY, 0, 0 );
 75 return 0;
                        return 0;
 76 }
                }
 77
 78 id = JOYSTICKID1;
                id = JOYSTICKID1;
 79
 80 jxm = ( jc.wXmin + jc.wXmax ) / 2;
                jxm = ( jc.wXmin + jc.wXmax ) / 2;
 81 jxl = ( jc.wXmin + jxm ) / 2;
                jxl = ( jc.wXmin + jxm ) / 2;
 82 jxr = ( jc.wXmax + jxm ) / 2;
                jxr = ( jc.wXmax + jxm ) / 2;
 83
 84 jym = ( jc.wYmin + jc.wYmax ) / 2;
                jym = ( jc.wYmin + jc.wYmax ) / 2;
 85 jyt = ( jc.wYmin + jym ) / 2;
                jyt = ( jc.wYmin + jym ) / 2;
 86 jyb = ( jc.wYmax + jym ) / 2;
                jyb = ( jc.wYmax + jym ) / 2;
 87
 88 ::joySetCapture( hWnd, id, 0, FALSE );
                ::joySetCapture( hWnd, id, 0, FALSE );
 89
 90 ::SetTimer( hWnd, ID_TIMER, ELAPSE, NULL );
                ::SetTimer( hWnd, ID_TIMER, ELAPSE, NULL );
 91
 92 return 0;
                return 0;
 93
 94 case WM_TIMER :
        case WM_TIMER : 
 95
 if ( JOYERR_NOERROR != ::joyGetPos( id, &ji ) )
                if ( JOYERR_NOERROR != ::joyGetPos( id, &ji ) )  {
{
 96 return 0;
                        return 0;
 97 }
                }
 98
 if ( ji.wXpos < jxl )
                if ( ji.wXpos < jxl )  {
{
 99 // 左
                        // 左
100 MAKEKEY('A');
                        MAKEKEY('A');
101 errorOut( hWnd, TEXT("left         "), 12 );
                        errorOut( hWnd, TEXT("left         "), 12 );
102 }
                }
103
 if ( ji.wXpos > jxr )
                if ( ji.wXpos > jxr )  {
{
104 // 右
                        // 右
105 MAKEKEY('D');
                        MAKEKEY('D');
106 errorOut( hWnd, TEXT("right        "), 12 );
                        errorOut( hWnd, TEXT("right        "), 12 );
107 }
                }
108
 if ( ji.wYpos < jyt )
                if ( ji.wYpos < jyt )  {
{
109 // 上
                        // 上
110 MAKEKEY('W');
                        MAKEKEY('W');
111 errorOut( hWnd, TEXT("top          "), 12 );
                        errorOut( hWnd, TEXT("top          "), 12 );
112 }
                }
113
 if ( ji.wYpos > jyb )
                if ( ji.wYpos > jyb )  {
{
114 // 下
                        // 下
115 MAKEKEY('S');
                        MAKEKEY('S');
116 errorOut( hWnd, TEXT("down         "), 12 );
                        errorOut( hWnd, TEXT("down         "), 12 );
117 }
                }
118
 if ( ji.wButtons & JOY_BUTTON1 )
                if ( ji.wButtons & JOY_BUTTON1 )  {
{
119 // 1
                        // 1
120 MAKEKEY('U');
                        MAKEKEY('U');
121 errorOut( hWnd, TEXT("1            "), 12 );
                        errorOut( hWnd, TEXT("1            "), 12 );
122 }
                }
123
 if ( ji.wButtons & JOY_BUTTON2 )
                if ( ji.wButtons & JOY_BUTTON2 )  {
{
124 // 2
                        // 2
125 MAKEKEY('I');
                        MAKEKEY('I');
126 errorOut( hWnd, TEXT("2            "), 12 );
                        errorOut( hWnd, TEXT("2            "), 12 );
127 }
                }
128
 if ( ji.wButtons & JOY_BUTTON3 )
                if ( ji.wButtons & JOY_BUTTON3 )  {
{
129 // 3
                        // 3
130 MAKEKEY('J');
                        MAKEKEY('J');
131 errorOut( hWnd, TEXT("3            "), 12 );
                        errorOut( hWnd, TEXT("3            "), 12 );
132 }
                }
133
 if ( ji.wButtons & JOY_BUTTON4 )
                if ( ji.wButtons & JOY_BUTTON4 )  {
{
134 // 4
                        // 4
135 MAKEKEY('K');
                        MAKEKEY('K');
136 errorOut( hWnd, TEXT("4            "), 12 );
                        errorOut( hWnd, TEXT("4            "), 12 );
137 }
                }
138 return 0;
                return 0;
139
140 case WM_DESTROY :
        case WM_DESTROY : 
141
 if ( JOYSTICKID1 == id )
                if ( JOYSTICKID1 == id )  {
{
142 ::KillTimer( hWnd, ID_TIMER );
                        ::KillTimer( hWnd, ID_TIMER );
143 ::joyReleaseCapture( id );
                        ::joyReleaseCapture( id );
144 }
                }
145 ::PostQuitMessage( 0 );
                ::PostQuitMessage( 0 );
146 return 0;
                return 0;
147 }
        }
148
149 return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
        return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
150 }
}
151
152
 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmd, INT nShow )
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmd, INT nShow )  {
{
153 WNDCLASSEX  wc;
        WNDCLASSEX  wc;
154 HWND        hWnd;
        HWND        hWnd;
155 MSG         msg;
        MSG         msg;
156
157 wc.cbClsExtra    = 0;
        wc.cbClsExtra    = 0;
158 wc.cbSize        = sizeof(wc);
        wc.cbSize        = sizeof(wc);
159 wc.cbWndExtra    = 0;
        wc.cbWndExtra    = 0;
160 wc.hbrBackground = (HBRUSH)::GetStockObject( WHITE_BRUSH );
        wc.hbrBackground = (HBRUSH)::GetStockObject( WHITE_BRUSH );
161 wc.hCursor       = ::LoadCursor( NULL, IDC_ARROW );
        wc.hCursor       = ::LoadCursor( NULL, IDC_ARROW );
162 wc.hIcon         = ::LoadIcon( NULL, IDI_APPLICATION );
        wc.hIcon         = ::LoadIcon( NULL, IDI_APPLICATION );
163 wc.hIconSm       = ::LoadIcon( NULL, IDI_APPLICATION );
        wc.hIconSm       = ::LoadIcon( NULL, IDI_APPLICATION );
164 wc.hInstance     = hInst;
        wc.hInstance     = hInst;
165 wc.lpfnWndProc   = WndProc;
        wc.lpfnWndProc   = WndProc;
166 wc.lpszClassName = gClassName;
        wc.lpszClassName = gClassName;
167 wc.lpszMenuName  = NULL;
        wc.lpszMenuName  = NULL;
168 wc.style         = 0;
        wc.style         = 0;
169
170
 if ( 0 == ::RegisterClassEx( &wc ) )
        if ( 0 == ::RegisterClassEx( &wc ) )  {
{
171 ::MessageBox( NULL, TEXT("RegisterClassEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
                ::MessageBox( NULL, TEXT("RegisterClassEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
172 return 0;
                return 0;
173 }
        }
174
175 hWnd = ::CreateWindowEx( 0,
        hWnd = ::CreateWindowEx( 0, 
176 gClassName, gWndName,
                gClassName, gWndName, 
177 WS_OVERLAPPEDWINDOW,
                WS_OVERLAPPEDWINDOW, 
178 200, 200, 400, 100,
                200, 200, 400, 100, 
179 NULL, NULL,
                NULL, NULL, 
180 hInst, NULL );
                hInst, NULL );
181
 if ( NULL == hWnd )
        if ( NULL == hWnd )  {
{
182 ::MessageBox( NULL, TEXT("CreateWindowEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
                ::MessageBox( NULL, TEXT("CreateWindowEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
183 return 0;
                return 0;
184 }
        }
185 ::ShowWindow( hWnd, nShow );
        ::ShowWindow( hWnd, nShow );
186 ::UpdateWindow( hWnd );
        ::UpdateWindow( hWnd );
187
188
 while ( ::GetMessage( &msg, NULL, 0, 0 ) )
        while ( ::GetMessage( &msg, NULL, 0, 0 ) )  {
{
189 ::TranslateMessage( &msg );
                ::TranslateMessage( &msg );
190 ::DispatchMessage( &msg );
                ::DispatchMessage( &msg );
191 }
        }
192 return msg.wParam;
        return msg.wParam;
193 }
}
194
 在我的宿主机上运行此软件,然后在虚拟机上运行游戏且设置键盘操作的对应键位,因为对手柄操作将产生相应的键盘操作,所以就可以用手柄玩游戏了。
小问题:由于手柄操作映射到键盘操作的方式,导致操作有一点点的变异。。。