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