JoyToKey 游戲手柄輸入映射為鍵盤輸入
本想用游戲手柄玩模擬器游戲的,可惜
游戲手柄在本機上可以使用,然而在虛擬機中無法使用(本機為Win7,手柄為北通戰戟,虛擬機為VirtualBox4.0.12),
而我的模擬器游戲都裝在虛擬的WinXP中,因為我不放心這些模擬器呀。
于是:
1
/*
2
JoyToKey.cpp
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
功能:
7
將游戲手柄操作映射為鍵盤按鍵操作。
8
9
原理:
10
接收手柄消息,然后產生相應鍵盤消息。
11
12
上 W
13
下 S
14
左 A
15
右 D
16
17
1 U
18
2 I
19
3 J
20
4 K
21
22
*/
23
24
25
#include <Windows.h>
26
#include <MMSystem.h>
27
28
29
#pragma comment( lib, "winmm.lib" )
30
31
32
TCHAR gClassName[] = TEXT("JoyToKey");
33
TCHAR gWndName[] = TEXT("JoyToKey -- coreBugZJ");
34
35
36
#define ID_TIMER 1
37
#define ELAPSE 50
38
39
40
VOID 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
52
LRESULT 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
152
INT 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
/*2
JoyToKey.cpp3

4
Copyright (C) 2011, coreBugZJ, all rights reserved.5

6
功能:7
將游戲手柄操作映射為鍵盤按鍵操作。8

9
原理:10
接收手柄消息,然后產生相應鍵盤消息。11

12
上 W13
下 S14
左 A15
右 D16

17
1 U18
2 I19
3 J20
4 K21

22
*/23

24

25
#include <Windows.h>26
#include <MMSystem.h>27

28

29
#pragma comment( lib, "winmm.lib" )30

31

32
TCHAR gClassName[] = TEXT("JoyToKey");33
TCHAR gWndName[] = TEXT("JoyToKey -- coreBugZJ");34

35

36
#define ID_TIMER 137
#define ELAPSE 5038

39

40
VOID 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

52
LRESULT 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
// 1120
MAKEKEY('U');121
errorOut( hWnd, TEXT("1 "), 12 );122
}123
if ( ji.wButtons & JOY_BUTTON2 ) {124
// 2125
MAKEKEY('I');126
errorOut( hWnd, TEXT("2 "), 12 );127
}128
if ( ji.wButtons & JOY_BUTTON3 ) {129
// 3130
MAKEKEY('J');131
errorOut( hWnd, TEXT("3 "), 12 );132
}133
if ( ji.wButtons & JOY_BUTTON4 ) {134
// 4135
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

152
INT 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

在我的宿主機上運行此軟件,然后在虛擬機上運行游戲且設置鍵盤操作的對應鍵位,因為對手柄操作將產生相應的鍵盤操作,所以就可以用手柄玩游戲了。
小問題:由于手柄操作映射到鍵盤操作的方式,導致操作有一點點的變異。。。
posted on 2011-10-03 23:32 coreBugZJ 閱讀(4414) 評論(4) 編輯 收藏 引用 所屬分類: Windows 、娛樂



