这是之前的 JoyToKey 的改进版,真正实用,我和 CY 两人用手柄对拳皇97,比键盘更容易放出招来(游戏是在不支持手柄的虚拟机中运行的)。
1
/**//*
2
JoyToKey.cpp
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
版本:
7
2.0.0
8
9
功能:
10
将游戏手柄操作映射为键盘按键操作。
11
12
原理:
13
接收手柄消息,然后产生相应键盘消息。
14
15
改进:
16
1.改进了手柄与键盘按键按下与释放的对应:手柄按键释放后才产生键盘按键释放消息,手柄按键按下后只产生键盘按键按下消息。
17
2.增加双手柄支持,可以同时使用两个手柄。
18
19
使用时不必考虑手柄按键和键盘按键的对应关系,就如直接使用手柄一般使用。
20
21
*/
22
23
24
#include <Windows.h>
25
#include <MMSystem.h>
26
27
28
#pragma comment( lib, "winmm.lib" )
29
30
31
// 每 ELAPSE 毫秒检测手柄输入
32
#define ELAPSE 50
33
// 手柄按键对应键盘按键
34
#define UP1 ('W')
35
#define DOWN1 ('S')
36
#define LEFT1 ('A')
37
#define RIGHT1 ('D')
38
#define BTN11 ('U')
39
#define BTN12 ('I')
40
#define BTN13 ('J')
41
#define BTN14 ('K')
42
43
#define UP2 ('Z')
44
#define DOWN2 ('X')
45
#define LEFT2 ('C')
46
#define RIGHT2 ('V')
47
#define BTN21 ('B')
48
#define BTN22 ('N')
49
#define BTN23 ('M')
50
#define BTN24 ('F')
51
52
53
TCHAR gClassName[] = TEXT("JoyToKey");
54
TCHAR gWndName[] = TEXT("JoyToKey -- coreBugZJ");
55
56
57
VOID msgOut( HWND hWnd, TCHAR msg[], UINT msglen )
{
58
HDC hdc = ::GetDC( hWnd );
59
::TextOut( hdc, 50, 20, msg, msglen );
60
::ReleaseDC( hWnd, hdc );
61
}
62
63
#define KEYDOWN(k) ::keybd_event( k, ::MapVirtualKey(k,0), 0, 0 )
64
#define KEYUP(k) ::keybd_event( k, ::MapVirtualKey(k,0), KEYEVENTF_KEYUP, 0 )
65
66
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
67
static JOYINFO ji1, ji2;
68
static DWORD id1 = 0xFFFF, id2 = 0xFFFF;
69
static JOYCAPS jc1, jc2;
70
static DWORD numDev;
71
static DWORD jxm1, jxl1, jxr1, jym1, jyt1, jyb1, x1, y1;
72
static DWORD jxm2, jxl2, jxr2, jym2, jyt2, jyb2, x2, y2;
73
74
DWORD x, y;
75
DWORD bf;
76
77
switch ( uMsg )
{
78
case WM_CREATE :
79
if ( 0 == (numDev = ::joyGetNumDevs()) )
{
80
::MessageBox( hWnd, TEXT("0 == ::joyGetNumDevs()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
81
::SendMessage( hWnd, WM_DESTROY, 0, 0 );
82
return 0;
83
}
84
85
// 手柄 1
86
if ( JOYERR_NOERROR != ::joyGetPos( JOYSTICKID1, &ji1 ) )
{
87
::MessageBox( hWnd, TEXT("JOYERR_NOERROR != ::joyGetPos()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
88
::SendMessage( hWnd, WM_DESTROY, 0, 0 );
89
return 0;
90
}
91
if ( JOYERR_NOERROR != ::joyGetDevCaps( JOYSTICKID1, &jc1, sizeof(jc1) ) )
{
92
::MessageBox( hWnd, TEXT("JOYERR_NOERROR != ::joyGetDevCaps()\n\n请检查手柄是否插好"), TEXT("Error"), MB_OK | MB_ICONERROR );
93
::SendMessage( hWnd, WM_DESTROY, 0, 0 );
94
return 0;
95
}
96
id1 = JOYSTICKID1;
97
jxm1 = ( jc1.wXmin + jc1.wXmax ) / 2;
98
jxl1 = ( jc1.wXmin + jxm1 ) / 2;
99
jxr1 = ( jc1.wXmax + jxm1 ) / 2;
100
jym1 = ( jc1.wYmin + jc1.wYmax ) / 2;
101
jyt1 = ( jc1.wYmin + jym1 ) / 2;
102
jyb1 = ( jc1.wYmax + jym1 ) / 2;
103
x1 = jxm1;
104
y1 = jym1;
105
::joySetCapture( hWnd, id1, ELAPSE, TRUE );
106
107
// 手柄 2
108
if ( 2 > numDev )
{
109
return 0;
110
}
111
if ( JOYERR_NOERROR != ::joyGetPos( JOYSTICKID2, &ji2 ) )
{
112
return 0;
113
}
114
if ( JOYERR_NOERROR != ::joyGetDevCaps( JOYSTICKID2, &jc2, sizeof(jc2) ) )
{
115
return 0;
116
}
117
id2 = JOYSTICKID2;
118
jxm2 = ( jc2.wXmin + jc2.wXmax ) / 2;
119
jxl2 = ( jc2.wXmin + jxm2 ) / 2;
120
jxr2 = ( jc2.wXmax + jxm2 ) / 2;
121
jym2 = ( jc2.wYmin + jc2.wYmax ) / 2;
122
jyt2 = ( jc2.wYmin + jym2 ) / 2;
123
jyb2 = ( jc2.wYmax + jym2 ) / 2;
124
x2 = jxm2;
125
y2 = jym2;
126
::joySetCapture( hWnd, id2, ELAPSE, TRUE );
127
128
return 0;
129
130
case MM_JOY1MOVE :
131
bf = wParam;
132
x = LOWORD(lParam);
133
y = HIWORD(lParam);
134
135
if ( x1 < jxl1 )
{
136
KEYUP(LEFT1);
137
::msgOut( hWnd, TEXT("LEFT1 UP "), 12 );
138
}
139
if ( x1 > jxr1 )
{
140
KEYUP(RIGHT1);
141
::msgOut( hWnd, TEXT("RIGHT1 UP "), 12 );
142
}
143
if ( y1 < jyt1 )
{
144
KEYUP(UP1);
145
::msgOut( hWnd, TEXT("UP1 UP "), 12 );
146
}
147
if ( y1 > jyb1 )
{
148
KEYUP(DOWN1);
149
::msgOut( hWnd, TEXT("DOWN1 UP "), 12 );
150
}
151
152
x1 = x;
153
y1 = y;
154
if ( x1 < jxl1 )
{
155
KEYDOWN(LEFT1);
156
::msgOut( hWnd, TEXT("LEFT1 DOWN "), 12 );
157
}
158
if ( x1 > jxr1 )
{
159
KEYDOWN(RIGHT1);
160
::msgOut( hWnd, TEXT("RIGHT1 DOWN "), 12 );
161
}
162
if ( y1 < jyt1 )
{
163
KEYDOWN(UP1);
164
::msgOut( hWnd, TEXT("UP1 DOWN "), 12 );
165
}
166
if ( y1 > jyb1 )
{
167
KEYDOWN(DOWN1);
168
::msgOut( hWnd, TEXT("DOWN1 DOWN "), 12 );
169
}
170
return 0;
171
172
case MM_JOY1BUTTONDOWN :
173
bf = wParam;
174
if ( (bf & JOY_BUTTON1CHG) && (bf & JOY_BUTTON1) )
{
175
KEYDOWN(BTN11);
176
::msgOut( hWnd, TEXT("BTN11 DOWN "), 12 );
177
}
178
if ( (bf & JOY_BUTTON2CHG) && (bf & JOY_BUTTON2) )
{
179
KEYDOWN(BTN12);
180
::msgOut( hWnd, TEXT("BTN12 DOWN "), 12 );
181
}
182
if ( (bf & JOY_BUTTON3CHG) && (bf & JOY_BUTTON3) )
{
183
KEYDOWN(BTN13);
184
::msgOut( hWnd, TEXT("BTN13 DOWN "), 12 );
185
}
186
if ( (bf & JOY_BUTTON4CHG) && (bf & JOY_BUTTON4) )
{
187
KEYDOWN(BTN14);
188
::msgOut( hWnd, TEXT("BTN14 DWON "), 12 );
189
}
190
return 0;
191
192
case MM_JOY1BUTTONUP :
193
bf = wParam;
194
if ( (bf & JOY_BUTTON1CHG) && (0 == (bf & JOY_BUTTON1)) )
{
195
KEYUP(BTN11);
196
::msgOut( hWnd, TEXT("BTN11 UP "), 12 );
197
}
198
if ( (bf & JOY_BUTTON2CHG) && (0 == (bf & JOY_BUTTON2)) )
{
199
KEYUP(BTN12);
200
::msgOut( hWnd, TEXT("BTN12 UP "), 12 );
201
}
202
if ( (bf & JOY_BUTTON3CHG) && (0 == (bf & JOY_BUTTON3)) )
{
203
KEYUP(BTN13);
204
::msgOut( hWnd, TEXT("BTN13 UP "), 12 );
205
}
206
if ( (bf & JOY_BUTTON4CHG) && (0 == (bf & JOY_BUTTON4)) )
{
207
KEYUP(BTN14);
208
::msgOut( hWnd, TEXT("BTN14 UP "), 12 );
209
}
210
return 0;
211
212
case MM_JOY2MOVE :
213
bf = wParam;
214
x = LOWORD(lParam);
215
y = HIWORD(lParam);
216
217
if ( x2 < jxl2 )
{
218
KEYUP(LEFT2);
219
::msgOut( hWnd, TEXT("LEFT2 UP "), 12 );
220
}
221
if ( x2 > jxr2 )
{
222
KEYUP(RIGHT2);
223
::msgOut( hWnd, TEXT("RIGHT2 UP "), 12 );
224
}
225
if ( y2 < jyt2 )
{
226
KEYUP(UP2);
227
::msgOut( hWnd, TEXT("UP2 UP "), 12 );
228
}
229
if ( y2 > jyb2 )
{
230
KEYUP(DOWN2);
231
::msgOut( hWnd, TEXT("DOWN2 UP "), 12 );
232
}
233
234
x2 = x;
235
y2 = y;
236
if ( x2 < jxl2 )
{
237
KEYDOWN(LEFT2);
238
::msgOut( hWnd, TEXT("LEFT2 DOWN "), 12 );
239
}
240
if ( x2 > jxr2 )
{
241
KEYDOWN(RIGHT2);
242
::msgOut( hWnd, TEXT("RIGHT2 DOWN "), 12 );
243
}
244
if ( y2 < jyt2 )
{
245
KEYDOWN(UP2);
246
::msgOut( hWnd, TEXT("UP2 DOWN "), 12 );
247
}
248
if ( y2 > jyb2 )
{
249
KEYDOWN(DOWN2);
250
::msgOut( hWnd, TEXT("DOWN2 DOWN "), 12 );
251
}
252
return 0;
253
254
case MM_JOY2BUTTONDOWN :
255
bf = wParam;
256
if ( (bf & JOY_BUTTON1CHG) && (bf & JOY_BUTTON1) )
{
257
KEYDOWN(BTN21);
258
::msgOut( hWnd, TEXT("BTN21 DOWN "), 12 );
259
}
260
if ( (bf & JOY_BUTTON2CHG) && (bf & JOY_BUTTON2) )
{
261
KEYDOWN(BTN22);
262
::msgOut( hWnd, TEXT("BTN22 DOWN "), 12 );
263
}
264
if ( (bf & JOY_BUTTON3CHG) && (bf & JOY_BUTTON3) )
{
265
KEYDOWN(BTN23);
266
::msgOut( hWnd, TEXT("BTN23 DOWN "), 12 );
267
}
268
if ( (bf & JOY_BUTTON4CHG) && (bf & JOY_BUTTON4) )
{
269
KEYDOWN(BTN24);
270
::msgOut( hWnd, TEXT("BTN24 DWON "), 12 );
271
}
272
return 0;
273
274
case MM_JOY2BUTTONUP :
275
bf = wParam;
276
if ( (bf & JOY_BUTTON1CHG) && (0 == (bf & JOY_BUTTON1)) )
{
277
KEYUP(BTN21);
278
::msgOut( hWnd, TEXT("BTN21 UP "), 12 );
279
}
280
if ( (bf & JOY_BUTTON2CHG) && (0 == (bf & JOY_BUTTON2)) )
{
281
KEYUP(BTN22);
282
::msgOut( hWnd, TEXT("BTN22 UP "), 12 );
283
}
284
if ( (bf & JOY_BUTTON3CHG) && (0 == (bf & JOY_BUTTON3)) )
{
285
KEYUP(BTN23);
286
::msgOut( hWnd, TEXT("BTN23 UP "), 12 );
287
}
288
if ( (bf & JOY_BUTTON4CHG) && (0 == (bf & JOY_BUTTON4)) )
{
289
KEYUP(BTN24);
290
::msgOut( hWnd, TEXT("BTN24 UP "), 12 );
291
}
292
return 0;
293
294
case WM_DESTROY :
295
if ( JOYSTICKID1 == id1 )
{
296
::joyReleaseCapture( id1 );
297
}
298
if ( JOYSTICKID2 == id2 )
{
299
::joyReleaseCapture( id2 );
300
}
301
::PostQuitMessage( 0 );
302
return 0;
303
}
304
305
return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
306
}
307
308
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmd, INT nShow )
{
309
WNDCLASSEX wc;
310
HWND hWnd;
311
MSG msg;
312
313
wc.cbClsExtra = 0;
314
wc.cbSize = sizeof(wc);
315
wc.cbWndExtra = 0;
316
wc.hbrBackground = (HBRUSH)::GetStockObject( WHITE_BRUSH );
317
wc.hCursor = ::LoadCursor( NULL, IDC_ARROW );
318
wc.hIcon = ::LoadIcon( NULL, IDI_APPLICATION );
319
wc.hIconSm = ::LoadIcon( NULL, IDI_APPLICATION );
320
wc.hInstance = hInst;
321
wc.lpfnWndProc = WndProc;
322
wc.lpszClassName = gClassName;
323
wc.lpszMenuName = NULL;
324
wc.style = 0;
325
326
if ( 0 == ::RegisterClassEx( &wc ) )
{
327
::MessageBox( NULL, TEXT("RegisterClassEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
328
return 0;
329
}
330
331
hWnd = ::CreateWindowEx( 0,
332
gClassName, gWndName,
333
WS_OVERLAPPEDWINDOW,
334
200, 200, 400, 100,
335
NULL, NULL,
336
hInst, NULL );
337
if ( NULL == hWnd )
{
338
::MessageBox( NULL, TEXT("CreateWindowEx Failed!"), TEXT("Error"), MB_OK | MB_ICONERROR );
339
return 0;
340
}
341
::ShowWindow( hWnd, nShow );
342
::UpdateWindow( hWnd );
343
344
while ( ::GetMessage( &msg, NULL, 0, 0 ) )
{
345
::TranslateMessage( &msg );
346
::DispatchMessage( &msg );
347
}
348
return msg.wParam;
349
}
350