coreBugZJ

此 blog 已弃。

JoyToKey 2.0 用游戏手柄模拟键盘玩游戏

这是之前的 JoyToKey 的改进版,真正实用,我和 CY 两人用手柄对拳皇97,比键盘更容易放出招来(游戏是在不支持手柄的虚拟机中运行的)。
  1/*
  2JoyToKey.cpp
  3
  4Copyright (C) 2011, coreBugZJ, all rights reserved.
  5
  6版本:
  72.0.0
  8
  9功能:
 10将游戏手柄操作映射为键盘按键操作。
 11
 12原理:
 13接收手柄消息,然后产生相应键盘消息。
 14
 15改进:
 161.改进了手柄与键盘按键按下与释放的对应:手柄按键释放后才产生键盘按键释放消息,手柄按键按下后只产生键盘按键按下消息。
 172.增加双手柄支持,可以同时使用两个手柄。
 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
 53TCHAR gClassName[] = TEXT("JoyToKey");
 54TCHAR gWndName[]   = TEXT("JoyToKey -- coreBugZJ");
 55
 56
 57VOID msgOut( HWND hWnd, TCHAR msg[], UINT msglen ) {
 58        HDC hdc = ::GetDC( hWnd );
 59        ::TextOut( hdc, 5020, 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
 66LRESULT 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, 00 );
 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, 00 );
 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, 00 );
 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
308INT 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                200200400100
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, 00 ) ) {
345                ::TranslateMessage( &msg );
346                ::DispatchMessage( &msg );
347        }

348        return msg.wParam;
349}

350


posted on 2011-10-04 23:31 coreBugZJ 阅读(2614) 评论(1)  编辑 收藏 引用 所属分类: Windows娱乐

Feedback

# re: JoyToKey 2.0 用游戏手柄模拟键盘玩游戏 2012-03-03 01:24 General_Clarke

没有写包含wingdi.h。
其它正常
有价值的代码,
谢谢  回复  更多评论   



只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理