Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1547 lines
50 KiB

  1. //===========================================================================
  2. // TEST.CPP
  3. //
  4. // Functions:
  5. // Test_DlgProc()
  6. // DoJoyMove()
  7. // DoTestButtons()
  8. // DoTestPOV()
  9. // DrawCross()
  10. // DisplayAvailableButtons()
  11. // JoyError()
  12. // DisplayAvailablePOVs()
  13. // SetOEMWindowText()
  14. //
  15. //===========================================================================
  16. // This is necessary for UnregisterDeviceNotification!
  17. #if (WINVER < 0x0500)
  18. #undef WINVER
  19. #define WINVER 0x0500
  20. #endif
  21. #include "cplsvr1.h"
  22. #include <initguid.h>
  23. #include <winuser.h> // For RegisterDeviceNotification stuff!
  24. #include <dbt.h> // for DBT_ defines!!!
  25. #include <hidclass.h>
  26. #include "dicputil.h"
  27. #include "resource.h"
  28. #include "pov.h"
  29. #include "assert.h"
  30. #include <regstr.h> // for REGSTR_VAL_'s below
  31. #include <commctrl.h> // for CProgressCtrl!
  32. #include <shlwapi.h> // for Str... functions!
  33. #include "Gradient.h" // for Gradient Fill Slider!
  34. #ifndef LONG2POINT
  35. #define LONG2POINT(l, pt) ((pt).x = (SHORT)LOWORD(l), (pt).y = (SHORT)HIWORD(l))
  36. #endif // LONG2POINT
  37. // local functions for services exclusive to this module!
  38. static void DisplayAvailablePOVs ( const HWND hWndToolTip, const HWND hDlg, BYTE nPOVs );
  39. static void DisplayAvailableButtons( const HWND hWndToolTip, const HWND hDlg, const int nNumButtons );
  40. static void DisplayAvailableAxisTest(const HWND hWndToolTip, const HWND hDlg, BYTE nAxisFlags, LPDIRECTINPUTDEVICE2 pdiDevice2);
  41. static void DoTestButtons ( const HWND hDlg, PBYTE pbButtons, int nButtons );
  42. static short JoyError ( const HWND hDlg );
  43. static BOOL SetDeviceRanges ( const HWND hDlg, LPDIRECTINPUTDEVICE2 pdiDevice2, BYTE nAxis );
  44. static DWORD DecodeAxisPOV( DWORD dwVal );
  45. // Local defines
  46. #define DELTA 5
  47. #define ID_JOY_TIMER 2002
  48. #define TIMER_INTERVAL 45 // time between polls in milliseconds
  49. #define MAX_SLIDER_POS 100
  50. #define MIN_SLIDER_POS 0
  51. #define FORCE_POV_REFRESH 254
  52. #define ACTIVE_COLOR RGB(255,0,0)
  53. #define INACTIVE_COLOR RGB(128,0,0)
  54. extern BOOL bDlgCentered;
  55. extern BYTE nStatic;
  56. extern CDIGameCntrlPropSheet_X *pdiCpl;
  57. extern HINSTANCE ghInst;
  58. BOOL bGradient;
  59. static HWND ProgWnd[NUM_WNDS];
  60. static CGradientProgressCtrl *pProgs[NUM_WNDS];
  61. static HPEN hTextPen;
  62. static HPEN hWinPen;
  63. LPDIJOYSTATE lpDIJoyState;
  64. extern HICON hIconArray[2];
  65. //===========================================================================
  66. // Test_DlgProc
  67. //
  68. // Parameters:
  69. // HWND hWnd - handle to dialog window
  70. // UINT uMsg - dialog message
  71. // WPARAM wParam - message specific data
  72. // LPARAM lParam - message specific data
  73. //
  74. // Returns: BOOL
  75. //
  76. //===========================================================================
  77. INT_PTR CALLBACK Test_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  78. {
  79. static LPDIRECTINPUTDEVICE2 pdiDevice2;
  80. static PVOID hNotifyDevNode;
  81. static HWND hWndToolTip;
  82. static BYTE nAxis;
  83. switch( uMsg ) {
  84. /*
  85. #ifdef _UNICODE
  86. case WM_DEVICECHANGE:
  87. if ((UINT)wParam == DBT_DEVICEREMOVECOMPLETE)
  88. {
  89. if (nStatic & CALIBRATING)
  90. break;
  91. pdiDevice2->Unacquire();
  92. if (FAILED(pdiDevice2->Acquire()))
  93. {
  94. KillTimer(hWnd, ID_JOY_TIMER);
  95. Error(hWnd, (short)IDS_JOYREADERROR, (short)IDS_JOYUNPLUGGED);
  96. // if you call this function you will hang up the system for 30 seconds or more!!!
  97. if (hNotifyDevNode)
  98. UnregisterDeviceNotification(hNotifyDevNode);
  99. ::PostMessage(GetParent(hWnd), WM_COMMAND, IDOK, 0);
  100. }
  101. }
  102. break;
  103. #endif
  104. */
  105. case WM_ACTIVATEAPP:
  106. if( wParam ) {
  107. pdiDevice2->Acquire();
  108. // Hack for bug #228798
  109. if( lpDIJoyState ) {
  110. // This is to refresh the cross hair...
  111. lpDIJoyState->lX+=1;
  112. DoJoyMove( hWnd, nAxis );
  113. // This is to refresh the POV
  114. if( pdiCpl->GetStateFlags()->nPOVs )
  115. DoTestPOV(FORCE_POV_REFRESH, lpDIJoyState->rgdwPOV, hWnd);
  116. }
  117. SetTimer( hWnd, ID_JOY_TIMER, TIMER_INTERVAL, NULL);
  118. } else {
  119. KillTimer(hWnd, ID_JOY_TIMER);
  120. pdiDevice2->Unacquire();
  121. }
  122. break;
  123. case WM_LBUTTONDOWN:
  124. // Click Drag service for PropSheets!
  125. PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam);
  126. break;
  127. // OnHelp
  128. case WM_HELP:
  129. KillTimer(hWnd, ID_JOY_TIMER);
  130. OnHelp(lParam);
  131. SetTimer( hWnd, ID_JOY_TIMER, TIMER_INTERVAL, NULL);
  132. return(TRUE);
  133. // OnContextMenu
  134. case WM_CONTEXTMENU:
  135. KillTimer(hWnd, ID_JOY_TIMER);
  136. OnContextMenu(wParam);
  137. SetTimer( hWnd, ID_JOY_TIMER, TIMER_INTERVAL, NULL);
  138. return(TRUE);
  139. // OnInit
  140. case WM_INITDIALOG:
  141. // get ptr to our object
  142. if( !pdiCpl )
  143. pdiCpl = (CDIGameCntrlPropSheet_X*)((LPPROPSHEETPAGE)lParam)->lParam;
  144. hTextPen = hWinPen = NULL;
  145. // Establish if you have enough colours to display the gradient fill scroll bar!
  146. {
  147. HDC hDC = ::GetWindowDC(hWnd);
  148. if( hDC ) { // Prefix Whistler Bug#45099
  149. bGradient = (BOOL)(GetDeviceCaps(hDC, NUMCOLORS) < 0);
  150. ::ReleaseDC(hWnd, hDC);
  151. }
  152. }
  153. // load the up and down states!
  154. hIconArray[0] = (HICON)LoadImage(ghInst, (PTSTR)IDI_BUTTONON, IMAGE_ICON, 0, 0, NULL);
  155. assert (hIconArray[0]);
  156. hIconArray[1] = (HICON)LoadImage(ghInst, (PTSTR)IDI_BUTTONOFF, IMAGE_ICON, 0, 0, NULL);
  157. assert (hIconArray[1]);
  158. // initialize DirectInput
  159. if( FAILED(InitDInput(GetParent(hWnd), pdiCpl)) ) {
  160. Error(hWnd, (short)IDS_INTERNAL_ERROR, (short)IDS_NO_DIJOYCONFIG);
  161. // Fix #108983 NT, Remove Flash on Error condition.
  162. SetWindowPos(::GetParent(hWnd), HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW);
  163. PostMessage(GetParent(hWnd), WM_SYSCOMMAND, SC_CLOSE, 0);
  164. return(FALSE);
  165. }
  166. // Get the device2 interface pointer
  167. pdiCpl->GetDevice(&pdiDevice2);
  168. nAxis = pdiCpl->GetStateFlags()->nAxis;
  169. // Set The scale for the Device Range!!!
  170. SetDeviceRanges(hWnd, pdiDevice2, nAxis);
  171. LPDIRECTINPUTJOYCONFIG pdiJoyConfig;
  172. pdiCpl->GetJoyConfig(&pdiJoyConfig);
  173. // Create the Pens for X/Y axis!
  174. CreatePens();
  175. // Create ToolTip window!
  176. hWndToolTip = CreateWindowEx( 0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP,
  177. CW_USEDEFAULT, CW_USEDEFAULT, 10, 10, hWnd, NULL, ghInst, NULL);
  178. // Show the available Axis!
  179. DisplayAvailableAxisTest(hWndToolTip, hWnd, nAxis, pdiDevice2);
  180. DisplayAvailableButtons(hWndToolTip, hWnd, pdiCpl->GetStateFlags()->nButtons);
  181. DisplayAvailablePOVs(hWndToolTip, hWnd, pdiCpl->GetStateFlags()->nPOVs);
  182. lpDIJoyState = new (DIJOYSTATE);
  183. assert(lpDIJoyState);
  184. ZeroMemory(lpDIJoyState, sizeof(DIJOYSTATE));
  185. // Clear the Static vars in DoJoyMove!
  186. DoJoyMove(hWnd, nAxis);
  187. // Center the Dialog!
  188. // If it's not been centered!
  189. if( !bDlgCentered ) {
  190. SetTitle(hWnd);
  191. CenterDialog(hWnd);
  192. bDlgCentered = TRUE;
  193. }
  194. {
  195. // Get the Type name
  196. DIJOYCONFIG_DX5 DIJoyConfig;
  197. ZeroMemory(&DIJoyConfig, sizeof(DIJOYCONFIG_DX5));
  198. DIJoyConfig.dwSize = sizeof(DIJOYCONFIG_DX5);
  199. if( SUCCEEDED(pdiJoyConfig->GetConfig(pdiCpl->GetID(), (LPDIJOYCONFIG)&DIJoyConfig, DIJC_REGHWCONFIGTYPE)) ) {
  200. if( DIJoyConfig.hwc.dwUsageSettings & JOY_US_ISOEM ) {
  201. LPCTSTR pszLabels[] = {
  202. REGSTR_VAL_JOYOEMTESTMOVEDESC,
  203. REGSTR_VAL_JOYOEMTESTMOVECAP,
  204. REGSTR_VAL_JOYOEMTESTBUTTONCAP,
  205. REGSTR_VAL_JOYOEMPOVLABEL,
  206. REGSTR_VAL_JOYOEMTESTWINCAP};
  207. const short nControlIDs[] = {
  208. IDC_TEXT_AXESHELP,
  209. IDC_AXISGRP,
  210. IDC_GROUP_BUTTONS,
  211. IDC_GROUP_POV,
  212. 0};
  213. SetOEMWindowText(hWnd, nControlIDs, pszLabels, DIJoyConfig.wszType, pdiJoyConfig, (BYTE)(sizeof(nControlIDs)/sizeof(short))-1);
  214. }
  215. bPolledPOV = (DIJoyConfig.hwc.hws.dwFlags & JOY_HWS_HASPOV) && (DIJoyConfig.hwc.hws.dwFlags & JOY_HWS_POVISPOLL);
  216. CalibratePolledPOV( &DIJoyConfig.hwc );
  217. }
  218. #ifdef _UNICODE
  219. // Set up the Device Notification
  220. // Removed per Om...
  221. //RegisterForDevChange(hWnd, &hNotifyDevNode);
  222. #endif
  223. }
  224. break; // end of WM_INITDIALOG
  225. // OnTimer
  226. case WM_TIMER:
  227. if( SUCCEEDED(DIUtilPollJoystick(pdiDevice2, lpDIJoyState)) ) {
  228. if( nAxis )
  229. DoJoyMove( hWnd, nAxis );
  230. if( pdiCpl->GetStateFlags()->nButtons )
  231. DoTestButtons( hWnd, lpDIJoyState->rgbButtons, pdiCpl->GetStateFlags()->nButtons );
  232. if( pdiCpl->GetStateFlags()->nPOVs )
  233. DoTestPOV( pdiCpl->GetStateFlags()->nPOVs, lpDIJoyState->rgdwPOV, hWnd );
  234. } else {
  235. KillTimer(hWnd, ID_JOY_TIMER);
  236. pdiDevice2->Unacquire();
  237. if( JoyError( hWnd ) == IDRETRY ) {
  238. pdiDevice2->Acquire();
  239. SetTimer( hWnd, ID_JOY_TIMER, TIMER_INTERVAL, NULL);
  240. } else {
  241. // Send a message back to the CPL to update list, as it may have changed!
  242. ::PostMessage(GetParent(hWnd), WM_COMMAND, IDOK, 0);
  243. }
  244. }
  245. break; // end of WM_TIMER
  246. // All this has to be done because WM_MOUSEMOVE doesn't get sent to static text!
  247. case WM_MOUSEMOVE:
  248. if( hWndToolTip ) {
  249. POINT pt;
  250. LONG2POINT(lParam, pt);
  251. HWND hChildWnd = ::ChildWindowFromPoint(hWnd, pt);
  252. static HWND hPrev;
  253. if( hChildWnd != hPrev && hChildWnd !=NULL ) {
  254. switch( GetDlgCtrlID(hChildWnd) ) {
  255. case IDC_JOYLIST1_LABEL:
  256. case IDC_JOYLIST2_LABEL:
  257. case IDC_JOYLIST3_LABEL:
  258. case IDC_JOYLIST4_LABEL:
  259. case IDC_JOYLIST5_LABEL:
  260. case IDC_JOYLIST6_LABEL:
  261. case IDC_JOYLIST7_LABEL:
  262. if( IsWindowVisible(hChildWnd) ) {
  263. MSG msg;
  264. //we need to fill out a message structure and pass it to the tooltip
  265. //with the TTM_RELAYEVENT message
  266. msg.hwnd = hWnd;
  267. msg.message = uMsg;
  268. msg.wParam = wParam;
  269. msg.lParam = lParam;
  270. msg.time = GetMessageTime();
  271. GetCursorPos(&msg.pt);
  272. ::SendMessage(hWndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
  273. }
  274. break;
  275. // We don't need to trap for anything else, as the rest are TTF_SUBCLASS'd
  276. default:
  277. break;
  278. }
  279. // store the last one so we don't have to do this again...
  280. hPrev = hChildWnd;
  281. }
  282. }
  283. break;
  284. // OnDestroy
  285. case WM_DESTROY:
  286. bDlgCentered = FALSE;
  287. KillTimer(hWnd, ID_JOY_TIMER);
  288. // Delete the button icons...
  289. DestroyIcon(hIconArray[0]);
  290. DestroyIcon(hIconArray[1]);
  291. // Kill pProgs
  292. if( bGradient ) {
  293. BYTE nAxisCounter = MAX_AXIS - 3;
  294. BYTE nTmpFlags = nAxis;
  295. // Clear the X and Y flags... they don't have progress controls
  296. // associated with them!
  297. nTmpFlags &= ~(HAS_X | HAS_Y);
  298. while( nTmpFlags ) {
  299. if( nTmpFlags & (HAS_Z<<nAxisCounter) ) {
  300. delete (pProgs[nAxisCounter]);
  301. pProgs[nAxisCounter] = 0;
  302. nTmpFlags &= ~(HAS_Z<<nAxisCounter);
  303. }
  304. nAxisCounter--;
  305. }
  306. }
  307. // Destroy the pens!
  308. if (hTextPen)
  309. DeleteObject(hTextPen);
  310. if( hWinPen )
  311. DeleteObject(hWinPen);
  312. if( lpDIJoyState ) {
  313. delete (lpDIJoyState);
  314. lpDIJoyState = NULL;
  315. }
  316. // Make sure you set this to NULL!
  317. pdiDevice2 = NULL;
  318. break; // end of WM_DESTROY
  319. // OnNotify
  320. case WM_NOTIFY:
  321. switch( ((NMHDR*)lParam)->code ) {
  322. case PSN_SETACTIVE:
  323. if( pdiDevice2 ) {
  324. pdiDevice2->Acquire();
  325. // if you have this, you are safe to start the timer!
  326. if( lpDIJoyState )
  327. SetTimer( hWnd, ID_JOY_TIMER, TIMER_INTERVAL, NULL);
  328. lpDIJoyState->lX+=1;
  329. DoJoyMove(hWnd, HAS_X | HAS_Y);
  330. }
  331. break;
  332. case PSN_KILLACTIVE:
  333. KillTimer(hWnd, ID_JOY_TIMER);
  334. pdiDevice2->Unacquire();
  335. break;
  336. }
  337. break; // end of WM_NOTIFY
  338. case WM_SYSCOLORCHANGE:
  339. {
  340. //Destroy old pens.
  341. if (hTextPen)
  342. {
  343. DeleteObject(hTextPen);
  344. hTextPen=NULL;
  345. }
  346. if(hWinPen)
  347. {
  348. DeleteObject(hWinPen);
  349. hWinPen=NULL;
  350. }
  351. //Recreate pens with new colors.
  352. CreatePens();
  353. //Change colors of slider bars.
  354. for(int i=0;i<NUM_WNDS;i++)
  355. {
  356. if(pProgs[i]) {
  357. pProgs[i]->SetBkColor(GetSysColor(COLOR_WINDOW));
  358. }
  359. }
  360. }
  361. break;
  362. }
  363. return(FALSE);
  364. } //*** end Test_DlgProc()
  365. //===========================================================================
  366. // DoJoyMove( HWND hDlg, LPDIJOYSTATE pDIJoyState, int nDrawFlags )
  367. //
  368. // Reports to hDlg state information from pDIJoyState, dwDrawFlags, and pJoyRange;
  369. //
  370. // Parameters:
  371. // HWND hDlg - Handle to Dialog
  372. // LPDIJOYSTATE pDIJoyState - State information about the device
  373. // LPJOYRANGE pJoyRange
  374. //
  375. // Returns: nichts
  376. //
  377. //===========================================================================
  378. void DoJoyMove( const HWND hDlg, BYTE nDrawFlags )
  379. {
  380. if( !::IsWindow(hDlg) ) {
  381. #ifdef _DEBUG
  382. OutputDebugString(TEXT("DoJoyMove: hDlg: Not a valid window!\n"));
  383. #endif
  384. return;
  385. }
  386. if( nDrawFlags == 0 ) {
  387. #ifdef _DEBUG
  388. OutputDebugString(TEXT("DoJoyMove: nDrawFlags is Zero!\n"));
  389. #endif
  390. return;
  391. }
  392. // draw the cross in the XY box if needed
  393. if( (nDrawFlags & HAS_X) || (nDrawFlags & HAS_Y) ) {
  394. static POINTS ptOld = {DELTA,DELTA};
  395. HWND hCtrl = GetDlgItem( hDlg, IDC_JOYLIST1 );
  396. assert(hCtrl);
  397. //RedrawWindow(hCtrl, NULL, NULL, RDW_INVALIDATE | RDW_ERASENOW);
  398. RECT rc;
  399. GetClientRect(hCtrl, &rc);
  400. // The Real Max is rc.bottom-DELTA!
  401. rc.bottom -= DELTA;
  402. // Check for ranges - Y Axis
  403. if( lpDIJoyState->lY > rc.bottom ) {
  404. #ifdef _DEBUG
  405. OutputDebugString(TEXT("GCDEF: DoJoyMove: retrieved Y pos > Max Y pos!\n"));
  406. #endif
  407. lpDIJoyState->lY = rc.bottom;
  408. } else if( lpDIJoyState->lY < DELTA ) {
  409. #ifdef _DEBUG
  410. OutputDebugString(TEXT("GCDEF: DoJoyMove: retrieved Y pos < Min Y pos!\n"));
  411. #endif
  412. lpDIJoyState->lY = DELTA;
  413. }
  414. // Check for ranges - X Axis
  415. if( lpDIJoyState->lX > rc.right ) {
  416. #ifdef _DEBUG
  417. OutputDebugString(TEXT("GCDEF: DoJoyMove: retrieved X pos > Max X pos!\n"));
  418. #endif
  419. lpDIJoyState->lX = rc.right;
  420. } else if( lpDIJoyState->lX < DELTA ) {
  421. #ifdef _DEBUG
  422. OutputDebugString(TEXT("GCDEF: DoJoyMove: retrieved X pos < Min X pos!\n"));
  423. #endif
  424. lpDIJoyState->lX = DELTA;
  425. }
  426. // out with the old...
  427. if( (ptOld.x != (short)lpDIJoyState->lX) || (ptOld.y != (short)lpDIJoyState->lY) ) {
  428. // Sorry... no drawing outside of your RECT!
  429. if( (ptOld.x > (rc.right-DELTA)) || (ptOld.y > rc.bottom) ) {
  430. ptOld.x = ptOld.y = DELTA;
  431. return;
  432. }
  433. DrawCross(hCtrl, &ptOld, COLOR_WINDOW );
  434. ptOld.x = (short)lpDIJoyState->lX;
  435. ptOld.y = (short)lpDIJoyState->lY;
  436. // in with the new...
  437. DrawCross( hCtrl, &ptOld, COLOR_WINDOWTEXT );
  438. }
  439. nDrawFlags &= ~(HAS_X | HAS_Y);
  440. }
  441. // draw Z bar if needed
  442. if( nDrawFlags ) {
  443. if( nDrawFlags & HAS_Z ) {
  444. static BYTE nOldZ; // = MAX_SLIDER_POS+1;
  445. if( lpDIJoyState->lZ != nOldZ ) {
  446. if( bGradient )
  447. pProgs[Z_INDEX]->SetPos(lpDIJoyState->lZ);
  448. ::PostMessage(ProgWnd[Z_INDEX], PBM_SETPOS, (WPARAM)abs(lpDIJoyState->lZ - MAX_SLIDER_POS), 0L);
  449. nOldZ = (BYTE)lpDIJoyState->lZ;
  450. }
  451. nDrawFlags &= ~HAS_Z;
  452. }
  453. } else return;
  454. // draw Slider0 bar if needed
  455. if( nDrawFlags ) {
  456. if( nDrawFlags & HAS_SLIDER0 ) {
  457. // Any value > 100, as that's the largest one we'll ever recieve!
  458. static BYTE nOldS0; // = MAX_SLIDER_POS+1;
  459. if( lpDIJoyState->rglSlider[0] != nOldS0 ) {
  460. nOldS0 = (BYTE)lpDIJoyState->rglSlider[0];
  461. if( bGradient )
  462. pProgs[S0_INDEX]->SetPos(lpDIJoyState->rglSlider[0]);
  463. ::PostMessage(ProgWnd[S0_INDEX], PBM_SETPOS, (WPARAM)abs(lpDIJoyState->rglSlider[0]-MAX_SLIDER_POS), 0L);
  464. }
  465. nDrawFlags &= ~HAS_SLIDER0;
  466. }
  467. } else return;
  468. // draw Rx bar if needed
  469. if( nDrawFlags ) {
  470. if( nDrawFlags & HAS_RX ) {
  471. static BYTE nOldRx; // = MAX_SLIDER_POS+1;
  472. if( lpDIJoyState->lRx != nOldRx ) {
  473. nOldRx = (BYTE)lpDIJoyState->lRx;
  474. if( bGradient )
  475. pProgs[RX_INDEX]->SetPos(lpDIJoyState->lRx);
  476. ::PostMessage(ProgWnd[RX_INDEX], PBM_SETPOS, (WPARAM)abs(lpDIJoyState->lRx - MAX_SLIDER_POS), 0L);
  477. }
  478. nDrawFlags &= ~HAS_RX;
  479. }
  480. } else return;
  481. // draw Ry bar if needed
  482. if( nDrawFlags ) {
  483. if( nDrawFlags & HAS_RY ) {
  484. static BYTE nOldRy; // = MAX_SLIDER_POS+1;
  485. if( lpDIJoyState->lRy != nOldRy ) {
  486. nOldRy = (BYTE)lpDIJoyState->lRy;
  487. if( bGradient )
  488. pProgs[RY_INDEX]->SetPos(lpDIJoyState->lRy);
  489. ::PostMessage(ProgWnd[RY_INDEX], PBM_SETPOS, (WPARAM)abs(lpDIJoyState->lRy - MAX_SLIDER_POS), 0L);
  490. }
  491. nDrawFlags &= ~HAS_RY;
  492. }
  493. } else return;
  494. // draw Rz bar if needed
  495. if( nDrawFlags ) {
  496. if( nDrawFlags & HAS_RZ ) {
  497. static BYTE nOldRz; // = MAX_SLIDER_POS+1;
  498. if( lpDIJoyState->lRz != nOldRz ) {
  499. nOldRz = (BYTE)lpDIJoyState->lRz;
  500. if( bGradient )
  501. pProgs[RZ_INDEX]->SetPos(lpDIJoyState->lRz);
  502. ::PostMessage(ProgWnd[RZ_INDEX], PBM_SETPOS, (WPARAM)abs(lpDIJoyState->lRz - MAX_SLIDER_POS), 0L);
  503. }
  504. nDrawFlags &= ~HAS_RZ;
  505. }
  506. } else return;
  507. // draw Slider1 bar if needed
  508. if( nDrawFlags ) {
  509. if( nDrawFlags & HAS_SLIDER1 ) {
  510. static BYTE nOldS1; // = MAX_SLIDER_POS+1;
  511. if( lpDIJoyState->rglSlider[1] != nOldS1 ) {
  512. nOldS1 = (BYTE)lpDIJoyState->rglSlider[1];
  513. if( bGradient )
  514. pProgs[S1_INDEX]->SetPos(lpDIJoyState->rglSlider[1]);
  515. ::PostMessage(ProgWnd[S1_INDEX], PBM_SETPOS, (WPARAM)abs(lpDIJoyState->rglSlider[1] - MAX_SLIDER_POS), 0L);
  516. }
  517. }
  518. }
  519. } // *** end of DoJoyMove
  520. //===========================================================================
  521. // DoTestButtons( HWND hDlg, PBYTE pbButtons, short nButtons )
  522. //
  523. // Lites whatever button(s) that may be pressed.
  524. //
  525. // Parameters:
  526. // HWND hDlg - Handle to Dialog
  527. // PBYTE pbButtons - Pointer to byte array of buttons and their states
  528. // int dwButtons - Number of buttons on device (per STATEFLAGS struct)
  529. //
  530. // Returns: nichts
  531. //
  532. //===========================================================================
  533. static void DoTestButtons( const HWND hDlg, PBYTE pbButtons, int nButtons )
  534. {
  535. // validate pointer(s)
  536. if( (IsBadReadPtr((void*)pbButtons, sizeof(BYTE))) ) {
  537. #ifdef _DEBUG
  538. OutputDebugString(TEXT("DoTestButtons: Bad Read Pointer argument!\n"));
  539. #endif
  540. return;
  541. }
  542. if( (IsBadWritePtr((void*)pbButtons, sizeof(BYTE))) ) {
  543. #ifdef _DEBUG
  544. OutputDebugString(TEXT("DoTestButtons: Bad Write Pointer argument!\n"));
  545. #endif
  546. return;
  547. }
  548. // Don't worry about the Zero Button condition!
  549. // It's being done in the timer!
  550. static BYTE bLookup[MAX_BUTTONS] = {NULL};
  551. BYTE i = 0;
  552. // Loop threw the buttons looking only at the ones we know we have!
  553. while( nButtons && (nButtons & (HAS_BUTTON1<<i)) ) {
  554. // check for a button press
  555. if( pbButtons[i] != bLookup[i] ) {
  556. // update the button with the proper bitmap
  557. HWND hCtrl = GetDlgItem(hDlg, IDC_TESTJOYBTNICON1+i);
  558. // Set the Extra Info
  559. SetWindowLongPtr(hCtrl, GWLP_USERDATA, (LONG_PTR)(pbButtons[i] & 0x80) ? 1 : 0);
  560. RedrawWindow(hCtrl, NULL, NULL, RDW_INVALIDATE | RDW_ERASENOW);
  561. // update the lookup table
  562. bLookup[i] = pbButtons[i];
  563. }
  564. // strip the button!
  565. nButtons &= ~(HAS_BUTTON1<<i++);
  566. }
  567. } // end of DoTestButtons
  568. //===========================================================================
  569. // DoTestPOV( PDWORD pdwPOV )
  570. //
  571. // Routes a call to SetDegrees to set the degrees to pdwPOV
  572. //
  573. // Parameters:
  574. // PDWORD pdwPOV - degrees at which to display the POV arrow
  575. //
  576. // Returns: nichts
  577. //
  578. //===========================================================================
  579. void DoTestPOV( BYTE nPov, PDWORD pdwPOV, HWND hDlg )
  580. {
  581. // Assume all POV's to be centred at start
  582. // JOY_POVCENTERED is defined as 0xffffffff
  583. static short dwOldPOV[MAX_POVS] = {-1,-1,-1,-1};
  584. BYTE nPovCounter = MAX_POVS-1;
  585. BYTE nPovs = 0;
  586. BOOL bChanged = FALSE;
  587. if( nPov == FORCE_POV_REFRESH ) {
  588. nPovs = 1;
  589. bChanged = TRUE;
  590. } else {
  591. // You Never have to worry about nPov being Zero,
  592. // it is checked before entering this function!
  593. do {
  594. // Be aware that nPov is not just a number... it's a bit mask!
  595. if( nPov & (HAS_POV1<<nPovCounter) ) {
  596. DWORD dwPov = (nPov & HAS_CALIBRATED) ? pdwPOV[nPovCounter] : pdwPOV[nPovCounter];
  597. if( dwOldPOV[nPovCounter] != (int)dwPov ) {
  598. dwOldPOV[nPovCounter] = (dwPov > 36001) ? -1 : (int)dwPov;
  599. bChanged = TRUE;
  600. }
  601. nPovs++;
  602. nPov &= ~(HAS_POV1<<nPovCounter);
  603. }
  604. } while( nPovCounter-- && nPov );
  605. }
  606. if( bChanged ) {
  607. SetDegrees(nPovs, dwOldPOV, GetDlgItem(hDlg, IDC_JOYPOV));
  608. }
  609. } // *** end of DoTestPOV
  610. //===========================================================================
  611. // DrawCross( HWND hwnd, LPPOINTS pPoint, short nFlag)
  612. //
  613. // Draws a cross on hwnd at pPoint of type nFlag
  614. //
  615. // Parameters:
  616. // HWND hwnd
  617. // LPPOINTS pPoint
  618. // int nFlag
  619. //
  620. // Returns: nichts
  621. //
  622. //===========================================================================
  623. static void DrawCross(const HWND hwnd, LPPOINTS pPoint, short nFlag)
  624. {
  625. assert(hwnd);
  626. HDC hdc = GetDC( hwnd );
  627. HPEN holdpen = (struct HPEN__ *) SelectObject( hdc, (nFlag == COLOR_WINDOW) ? hWinPen : hTextPen );
  628. MoveToEx( hdc, pPoint->x-(DELTA-1), pPoint->y, NULL);
  629. LineTo( hdc, pPoint->x+DELTA, pPoint->y );
  630. MoveToEx( hdc, pPoint->x, pPoint->y-(DELTA-1), NULL );
  631. LineTo( hdc, pPoint->x, pPoint->y+DELTA );
  632. SelectObject( hdc, holdpen );
  633. ReleaseDC( hwnd, hdc );
  634. } // *** end of DrawCross
  635. void CreatePens( void )
  636. {
  637. // We always create both at the same time so checking one is sufficient!
  638. if( hTextPen == NULL ) {
  639. LOGPEN LogPen;
  640. LogPen.lopnStyle = PS_SOLID;
  641. LogPen.lopnWidth.x = LogPen.lopnWidth.y = 0;
  642. LogPen.lopnColor = GetSysColor( COLOR_WINDOW );
  643. hWinPen = CreatePenIndirect(&LogPen);
  644. LogPen.lopnColor = GetSysColor( COLOR_WINDOWTEXT );
  645. hTextPen = CreatePenIndirect(&LogPen);
  646. }
  647. }
  648. //===========================================================================
  649. // DisplayAvailableButtons(HWND hWnd, int nNumButtons)
  650. //
  651. // Removes buttons not found on the device!
  652. //
  653. //
  654. // Parameters:
  655. // HWND hDlg - Dialog handle
  656. // int nNumButtons - Number of buttons to display
  657. //
  658. // Returns:
  659. //
  660. //===========================================================================
  661. void DisplayAvailableButtons(const HWND hWndToolTip, const HWND hDlg, const int nButtonFlags)
  662. {
  663. LPTOOLINFO pToolInfo;
  664. LPTSTR lpStr;
  665. if( nButtonFlags ) {
  666. if( hWndToolTip ) {
  667. pToolInfo = new (TOOLINFO);
  668. ASSERT (pToolInfo);
  669. lpStr = new (TCHAR[STR_LEN_32]);
  670. ASSERT(lpStr);
  671. ZeroMemory(pToolInfo, sizeof(TOOLINFO));
  672. pToolInfo->cbSize = sizeof(TOOLINFO);
  673. pToolInfo->uFlags = 0;
  674. pToolInfo->hwnd = hDlg;
  675. ::SendDlgItemMessage(hDlg, IDC_GROUP_BUTTONS, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)lpStr);
  676. pToolInfo->lpszText = lpStr;
  677. }
  678. }
  679. HWND hCtrl;
  680. // Show the ones we have...
  681. // Destroy the ones we don't!
  682. BYTE i = MAX_BUTTONS;
  683. do {
  684. hCtrl = GetDlgItem(hDlg, IDC_TESTJOYBTNICON1+(--i));
  685. if( (nButtonFlags & HAS_BUTTON1<<i) && pToolInfo ) {
  686. // Add the Control to the tool!
  687. pToolInfo->uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  688. pToolInfo->uId = (ULONG_PTR) hCtrl;
  689. // Add the control!
  690. ::SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)pToolInfo);
  691. continue;
  692. }
  693. DestroyWindow(hCtrl);
  694. } while( i );
  695. if( nButtonFlags ) {
  696. if( lpStr )
  697. delete[] (lpStr);
  698. if( pToolInfo )
  699. delete (pToolInfo);
  700. } else {
  701. // don't forget to remove the groupe!
  702. hCtrl = GetDlgItem(hDlg, IDC_GROUP_BUTTONS);
  703. DestroyWindow(hCtrl);
  704. }
  705. } //*** end DisplayAvailableButtons()
  706. //===========================================================================
  707. // JoyError(HWND hwnd)
  708. //
  709. // Displays the "Device Not Connected"
  710. //
  711. // Parameters:
  712. // HWND hwnd - window handle
  713. //
  714. // Returns: rc - User selection from MessageBox
  715. //
  716. //===========================================================================
  717. short JoyError( const HWND hwnd )
  718. {
  719. assert(hwnd);
  720. TCHAR lptszTitle[STR_LEN_32];
  721. short rc;
  722. if( LoadString(ghInst, IDS_JOYREADERROR, lptszTitle, STR_LEN_32) ) {
  723. TCHAR lptszMsg[STR_LEN_128];
  724. if( LoadString(ghInst, IDS_JOYUNPLUGGED, lptszMsg, STR_LEN_128) ) {
  725. rc = (short)MessageBox( hwnd, lptszMsg, lptszTitle, MB_RETRYCANCEL | MB_ICONERROR );
  726. if( rc == IDCANCEL ) {
  727. // terminate the dialog if we give up
  728. PostMessage( GetParent(hwnd), WM_COMMAND, IDCANCEL, 0 );
  729. }
  730. }
  731. }
  732. return(rc);
  733. } // *** end of JoyError
  734. //===========================================================================
  735. // DisplayAvailablePOVs( const HWND hWndToolTip, const HWND hDlg, BYTE nPOVs )
  736. //
  737. // Displays POV window if there are any associated with the device.
  738. //
  739. // Parameters:
  740. // HWND hDlg - window handle
  741. // short nPOVs - number of POVs
  742. //
  743. // Returns: nichts
  744. //
  745. //===========================================================================
  746. static void DisplayAvailablePOVs ( const HWND hWndToolTip, const HWND hDlg, BYTE nPOVs )
  747. {
  748. HWND hwndPOV = GetDlgItem(hDlg, IDC_JOYPOV);
  749. SetWindowPos( hwndPOV, NULL, NULL, NULL, NULL, NULL,
  750. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((nPOVs) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  751. SetWindowPos( GetDlgItem( hDlg, IDC_GROUP_POV ), NULL, NULL, NULL, NULL, NULL,
  752. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((nPOVs) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  753. if( nPOVs ) {
  754. // Disable RTL flag
  755. SetWindowLongPtr(hwndPOV, GWL_EXSTYLE, GetWindowLongPtr(hwndPOV,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL );
  756. if( hWndToolTip ) {
  757. TOOLINFO ToolInfo;
  758. TCHAR lpStr[STR_LEN_32];
  759. ZeroMemory(&ToolInfo, sizeof(TOOLINFO));
  760. ToolInfo.cbSize = sizeof(TOOLINFO);
  761. ToolInfo.uFlags = 0;
  762. ToolInfo.hwnd = hDlg;
  763. ::SendDlgItemMessage(hDlg, IDC_GROUP_POV, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)lpStr);
  764. ToolInfo.lpszText = lpStr;
  765. ToolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  766. ToolInfo.uId = (ULONG_PTR)hwndPOV;
  767. // Add the control!
  768. ::SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ToolInfo);
  769. }
  770. }
  771. } // *** end of DisplayAvailablePOVs
  772. //===========================================================================
  773. // SetOEMWindowText( HWND hDlg, short *nControlIDs, LPTSTR *pszLabels, BYTE nCount )
  774. //
  775. // Retrieves text from registry keys and Displays it in a Dialog Control or title!
  776. //
  777. // Parameters:
  778. // HWND hDlg - Handle to dialog where strings are to be sent
  779. // nControlIDs - Pointer to array of Dialog Item ID's
  780. // Zero may be used if you want the Title!
  781. // pszLabels - Pointer to array of Registry Keys to read
  782. // nCount - Number of ellements in the array
  783. //
  784. // Returns: nichts
  785. //
  786. //===========================================================================
  787. void SetOEMWindowText ( const HWND hDlg, const short *nControlIDs, LPCTSTR *pszLabels, LPCWSTR wszType, LPDIRECTINPUTJOYCONFIG pdiJoyConfig, BYTE nCount )
  788. {
  789. if( nCount == 0 ) {
  790. #ifdef _DEBUG
  791. OutputDebugString(TEXT("JOY.CPL: Test.cpp: SetOEMWindowText: nCount is Zero!\n"));
  792. #endif
  793. return;
  794. }
  795. // validate nControlIDs pointer
  796. if( IsBadReadPtr((void*)nControlIDs, sizeof(short)) ) {
  797. #ifdef _DEBUG
  798. OutputDebugString(TEXT("JOY.CPL: Test.cpp: SetOEMWindowText: nControlIDs is not a valid Read Pointer!\n"));
  799. #endif
  800. return;
  801. }
  802. // validate pointers
  803. if( IsBadReadPtr((void*)pszLabels, sizeof(TCHAR)) ) {
  804. #ifdef _DEBUG
  805. OutputDebugString(TEXT("JOY.CPL: Test.cpp: SetOEMWindowText: pszLabels is not a valid Read Pointer!\n"));
  806. #endif
  807. return;
  808. }
  809. HKEY hKey;
  810. pdiJoyConfig->Acquire();
  811. // Open the TypeKey
  812. if( FAILED(pdiJoyConfig->OpenTypeKey( wszType, KEY_ALL_ACCESS, &hKey)) ) {
  813. #ifdef _DEBUG
  814. OutputDebugString(TEXT("Test.cpp: SetOEMWindowText: OpenTypeKey FAILED!\n"));
  815. #endif
  816. return;
  817. }
  818. TCHAR pszBuff[MAX_STR_LEN];
  819. DWORD dwCount = sizeof(pszBuff);
  820. DWORD dwType = REG_SZ;
  821. do {
  822. if( RegQueryValueEx( hKey, pszLabels[nCount], NULL, &dwType, (CONST LPBYTE)pszBuff, &dwCount ) == ERROR_SUCCESS ) {
  823. // This is because RegQueryValueEx returns dwCount size as the size
  824. // of the terminating char if the label is found w/o a string!
  825. if( dwCount > sizeof(TCHAR) ) {
  826. if( nControlIDs[nCount] )
  827. ::SendMessage(GetDlgItem(hDlg, nControlIDs[nCount]), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pszBuff);
  828. else
  829. ::SendMessage(GetParent(hDlg), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pszBuff);
  830. }
  831. #ifdef _DEBUG
  832. else OutputDebugString(TEXT("Test.cpp: SetOEMWindowText: ReqQueryValueEx failed to find Registry string!\n"));
  833. #endif
  834. }
  835. dwCount = MAX_STR_LEN;
  836. } while( nCount-- );
  837. RegCloseKey(hKey);
  838. } // *** end of SetOEMWindowText
  839. //===========================================================================
  840. // DisplayAvailableAxisTest(HWND hDlg, BYTE nAxisFlags, LPDIRECTINPUTDEVICE2 pdiDevice2)
  841. //
  842. // Displays the number and names of the device Axis in the provided dialog.
  843. // This EXPECTS that the controls are not visible by default!
  844. //
  845. // Parameters:
  846. // HWND hDlg - Dialog handle
  847. // BYTE nAxisFlags - Flags for number of Axis to display
  848. //
  849. // Returns:
  850. //
  851. //===========================================================================
  852. void DisplayAvailableAxisTest(const HWND hWndToolTip, const HWND hDlg, BYTE nAxisFlags, LPDIRECTINPUTDEVICE2 pdiDevice2)
  853. {
  854. if( nAxisFlags == 0 ) {
  855. DestroyWindow(GetDlgItem(hDlg, IDC_AXISGRP));
  856. #ifdef _DEBUG
  857. OutputDebugString(TEXT("GCDEF.DLL: DisplayAvailableAxis: Number of Axis is 0!\n"));
  858. #endif
  859. return;
  860. }
  861. LPDIDEVICEOBJECTINSTANCE_DX3 pDevObjInst = new (DIDEVICEOBJECTINSTANCE_DX3);
  862. assert (pDevObjInst);
  863. pDevObjInst->dwSize = sizeof(DIDEVICEOBJECTINSTANCE_DX3);
  864. LPTOOLINFO pToolInfo;
  865. if( hWndToolTip ) {
  866. pToolInfo = new (TOOLINFO);
  867. ASSERT (pToolInfo);
  868. ZeroMemory(pToolInfo, sizeof(TOOLINFO));
  869. pToolInfo->cbSize = sizeof(TOOLINFO);
  870. pToolInfo->uFlags = 0;
  871. pToolInfo->hwnd = hDlg;
  872. }
  873. HWND hCtrl;
  874. // X and Y use the same control so they are isolated!
  875. if( (nAxisFlags & HAS_X) || (nAxisFlags & HAS_Y) ) {
  876. HWND hwndXY = GetDlgItem(hDlg, IDC_JOYLIST1);
  877. // Show the Window
  878. SetWindowPos( hwndXY, NULL, NULL, NULL, NULL, NULL,
  879. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
  880. // Disable RTL flag
  881. SetWindowLongPtr(hwndXY, GWL_EXSTYLE, GetWindowLongPtr(hwndXY,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL );
  882. hCtrl = GetDlgItem(hDlg, IDC_JOYLIST1_LABEL);
  883. // Show it's text
  884. SetWindowPos( hCtrl, NULL, NULL, NULL, NULL, NULL,
  885. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
  886. TCHAR ptszBuff[STR_LEN_64];
  887. ZeroMemory(ptszBuff, sizeof(TCHAR[STR_LEN_64]));
  888. // Set it's text
  889. if( nAxisFlags & HAS_X ) {
  890. if( SUCCEEDED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, DIJOFS_X, DIPH_BYOFFSET)) )
  891. {
  892. int nLen=lstrlen(pDevObjInst->tszName)+1;
  893. if(nLen>STR_LEN_64)
  894. nLen=STR_LEN_64;
  895. StrCpyN(ptszBuff, pDevObjInst->tszName, nLen);
  896. }
  897. // Remove the HAS_X flag
  898. nAxisFlags &= ~HAS_X;
  899. }
  900. if( nAxisFlags & HAS_Y ) {
  901. if( FAILED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, DIJOFS_Y, DIPH_BYOFFSET)) ) {
  902. #ifdef _DEBUG
  903. OutputDebugString(TEXT("GCDEF.DLL: DisplayAvailableAxis: GetObjectInfo Failed to find DIJOFS_Y!\n"));
  904. #endif
  905. }
  906. if( ptszBuff && lstrlen(ptszBuff) ) {
  907. int nLen=STR_LEN_64-lstrlen(ptszBuff);
  908. StrNCat(ptszBuff, TEXT(" / "), nLen);
  909. }
  910. int nLen=STR_LEN_64-lstrlen(ptszBuff);
  911. StrNCat(ptszBuff, pDevObjInst->tszName, nLen);
  912. // Remove the HAS_Y flag
  913. nAxisFlags &= ~HAS_Y;
  914. }
  915. ::SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)ptszBuff);
  916. // CreateWindow could have failed... if so, no tooltips!
  917. if( hWndToolTip ) {
  918. GetWindowRect(hCtrl, &pToolInfo->rect);
  919. ScreenToClient(GetParent(hDlg), (LPPOINT)&pToolInfo->rect);
  920. ScreenToClient(GetParent(hDlg), ((LPPOINT)&pToolInfo->rect)+1);
  921. pToolInfo->lpszText = ptszBuff;
  922. // Add the Label...
  923. ::SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)pToolInfo);
  924. // Add the Control!
  925. pToolInfo->uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  926. pToolInfo->uId = (ULONG_PTR)hwndXY;
  927. // Add the control!
  928. ::SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)pToolInfo);
  929. }
  930. }
  931. // if you have additional axis, keep going!
  932. if( nAxisFlags ) {
  933. // Array of supported axis!
  934. DWORD dwOffsetArray[] = {DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1)};
  935. BYTE nAxisCounter = MAX_AXIS - 3;
  936. // Go 'till you run out of axis!
  937. do {
  938. if( nAxisFlags & (HAS_Z<<nAxisCounter) ) {
  939. // Create and Assign to the global list!
  940. ProgWnd[nAxisCounter] = GetDlgItem(hDlg, nAxisCounter+IDC_JOYLIST2);
  941. ASSERT (ProgWnd[nAxisCounter]);
  942. // Create Gradient Class
  943. if( bGradient ) {
  944. pProgs[nAxisCounter] = new (CGradientProgressCtrl);
  945. assert (pProgs[nAxisCounter]);
  946. // Subclass the Progress Control Window
  947. pProgs[nAxisCounter]->SubclassWindow(ProgWnd[nAxisCounter]);
  948. } else {
  949. // Set the colour
  950. // PBM_SETBARCOLOR is WM_USER+9
  951. ::PostMessage(ProgWnd[nAxisCounter], WM_USER+9, 0, (LPARAM)ACTIVE_COLOR);
  952. }
  953. // Show the control... ProgWnd[nAxisCounter]
  954. SetWindowPos( ProgWnd[nAxisCounter], NULL, NULL, NULL, NULL, NULL,
  955. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
  956. hCtrl = GetDlgItem(hDlg, nAxisCounter+IDC_JOYLIST2_LABEL);
  957. // Now, Show it's text
  958. SetWindowPos( hCtrl, NULL, NULL, NULL, NULL, NULL,
  959. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
  960. // Get it's text
  961. if( SUCCEEDED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, dwOffsetArray[nAxisCounter], DIPH_BYOFFSET)) ) {
  962. TCHAR tszAxisName[20];
  963. int nLen=lstrlen(pDevObjInst->tszName)+1;
  964. if(nLen>20)
  965. nLen=20;
  966. StrCpyN(tszAxisName, pDevObjInst->tszName, nLen);
  967. if( lstrlen( tszAxisName ) > 4 ) {
  968. tszAxisName[4] = L'.';
  969. tszAxisName[5] = L'.';
  970. tszAxisName[6] = 0;
  971. }
  972. ::SendMessage(hCtrl, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tszAxisName);
  973. // Just in case CreateWindow failed!!!
  974. if( hWndToolTip ) {
  975. GetWindowRect(hCtrl, &pToolInfo->rect);
  976. ScreenToClient(GetParent(hDlg), (LPPOINT)&pToolInfo->rect);
  977. ScreenToClient(GetParent(hDlg), ((LPPOINT)&pToolInfo->rect)+1);
  978. pToolInfo->uFlags = 0;
  979. pToolInfo->lpszText = pDevObjInst->tszName;
  980. // Add the Label...
  981. ::SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)pToolInfo);
  982. // Add the Control!
  983. pToolInfo->uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  984. pToolInfo->uId = (ULONG_PTR) ProgWnd[nAxisCounter];
  985. // Now, Add the control!
  986. ::SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)pToolInfo);
  987. }
  988. }
  989. // Remove the flag you just hit!
  990. nAxisFlags &= ~(HAS_Z<<nAxisCounter);
  991. }
  992. } while( nAxisCounter-- && nAxisFlags );
  993. }
  994. if( hWndToolTip ) {
  995. if( pToolInfo )
  996. delete (pToolInfo);
  997. }
  998. if( pDevObjInst )
  999. delete (pDevObjInst);
  1000. } //*** end of DisplayAvailableAxisTest
  1001. //===========================================================================
  1002. // BOOL SetDeviceRanges( HWND hDlg, LPDIRECTINPUTDEVICE2 pdiDevice2, BYTE nAxis)
  1003. //
  1004. // Parameters:
  1005. // HWND hDlg - Handle of Dialog containing controls to scale to
  1006. // LPDIRECTINPUTDEVICE2 pdiDevice2 - Device2 Interface pointer
  1007. // BYTE nAxis - Bit mask of axis ranges to set
  1008. //
  1009. // Returns: FALSE if failed
  1010. //
  1011. //===========================================================================
  1012. BOOL SetDeviceRanges( const HWND hDlg, LPDIRECTINPUTDEVICE2 pdiDevice2, BYTE nAxis)
  1013. {
  1014. if( !::IsWindow(hDlg) ) {
  1015. #ifdef _DEBUG
  1016. OutputDebugString(TEXT("GCDEF: SetDeviceRanges: hDlg: Not a valid window!\n"));
  1017. #endif
  1018. return(FALSE);
  1019. }
  1020. // validate pDIDevice2 pointer
  1021. if( IsBadReadPtr((void*)pdiDevice2, sizeof(IDirectInputDevice2)) ) {
  1022. #ifdef _DEBUG
  1023. OutputDebugString(TEXT("GCDEF: SetDeviceRanges: pdiDevice2: Bad Read Pointer argument!\n"));
  1024. #endif
  1025. return(FALSE);
  1026. }
  1027. if( !nAxis ) {
  1028. #ifdef _DEBUG
  1029. OutputDebugString(TEXT("GCDEF: SetDeviceRanges: nAxis is Zero!\n"));
  1030. #endif
  1031. return(FALSE);
  1032. }
  1033. DIPROPRANGE DIPropRange;
  1034. DIPropRange.diph.dwSize = sizeof(DIPROPRANGE);
  1035. DIPropRange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  1036. DIPropRange.diph.dwHow = DIPH_BYOFFSET;
  1037. BOOL bRet = TRUE;
  1038. HWND hCtrl;
  1039. RECT rc;
  1040. // since X and Y share the same window..
  1041. if( (nAxis & HAS_X) || (nAxis & HAS_Y) ) {
  1042. hCtrl = GetDlgItem(hDlg, IDC_JOYLIST1);
  1043. assert (hCtrl);
  1044. GetClientRect( hCtrl, &rc );
  1045. // Check if it's X
  1046. if( nAxis & HAS_X ) {
  1047. DIPropRange.diph.dwObj = DIJOFS_X;
  1048. DIPropRange.lMin = DELTA;
  1049. DIPropRange.lMax = rc.right-DELTA;
  1050. if( FAILED(pdiDevice2->SetProperty(DIPROP_RANGE, &DIPropRange.diph)) ) {
  1051. #ifdef _DEBUG
  1052. OutputDebugString(TEXT("GCDEF: SetDeviceRanges: SetProperty Failed to return X axis Ranges!\n"));
  1053. #endif
  1054. bRet = FALSE;
  1055. }
  1056. // strip off the bits you just used
  1057. nAxis &= ~HAS_X;
  1058. }
  1059. // Check if it's Y
  1060. if( nAxis & HAS_Y ) {
  1061. DIPropRange.diph.dwObj = DIJOFS_Y;
  1062. DIPropRange.lMin = DELTA;
  1063. DIPropRange.lMax = rc.bottom-DELTA;
  1064. if( FAILED(pdiDevice2->SetProperty(DIPROP_RANGE, &DIPropRange.diph)) ) {
  1065. #ifdef _DEBUG
  1066. OutputDebugString(TEXT("GCDEF: SetDeviceRanges: SetProperty Failed to return Y axis Ranges!\n"));
  1067. #endif
  1068. bRet = FALSE;
  1069. }
  1070. // strip off the bits you just used
  1071. nAxis &= ~HAS_Y;
  1072. }
  1073. }
  1074. // you've got axes > X & Y...
  1075. if( nAxis ) {
  1076. const DWORD dwOfset[] = {DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1)};
  1077. BYTE nAxisCounter = MAX_AXIS - 3;
  1078. // These aren't random!
  1079. // These are the default ranges for the CProgressCtrl!!!
  1080. DIPropRange.lMin = MIN_SLIDER_POS;
  1081. DIPropRange.lMax = MAX_SLIDER_POS;
  1082. do {
  1083. if( nAxis & (HAS_Z<<nAxisCounter) ) {
  1084. DIPropRange.diph.dwObj = dwOfset[nAxisCounter];
  1085. VERIFY(SUCCEEDED(pdiDevice2->SetProperty(DIPROP_RANGE, &DIPropRange.diph)));
  1086. // Remove the flag you just hit!
  1087. nAxis &= ~(HAS_Z<<nAxisCounter);
  1088. }
  1089. nAxisCounter--;
  1090. } while( nAxis );
  1091. }
  1092. return(bRet);
  1093. }
  1094. #ifdef _UNICODE
  1095. ///////////////////////////////////////////////////////////////////////////////
  1096. // FUNCTION: RegisterForDevChange ( HWND hDlg, PVOID *pNoditfyDevNode )
  1097. //
  1098. // PARAMETERS:
  1099. //
  1100. //
  1101. // PURPOSE:
  1102. //
  1103. // RETURN:
  1104. ///////////////////////////////////////////////////////////////////////////////
  1105. void RegisterForDevChange(HWND hDlg, PVOID *pNotifyDevNode)
  1106. {
  1107. DEV_BROADCAST_DEVICEINTERFACE FilterData;
  1108. ZeroMemory(&FilterData, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
  1109. FilterData.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  1110. FilterData.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  1111. FilterData.dbcc_classguid = GUID_CLASS_INPUT;
  1112. *pNotifyDevNode = RegisterDeviceNotification(hDlg, &FilterData, DEVICE_NOTIFY_WINDOW_HANDLE);
  1113. }
  1114. ///////////////////////////////////////////////////////////////////////////////
  1115. // FUNCTION: DecodeAxisPOV ( DWORD dwVal )
  1116. //
  1117. // PARAMETERS:
  1118. //
  1119. //
  1120. // PURPOSE:
  1121. //
  1122. // RETURN:
  1123. ///////////////////////////////////////////////////////////////////////////////
  1124. static DWORD DecodeAxisPOV( DWORD dwVal )
  1125. {
  1126. DWORD dwResult;
  1127. if( bPolledPOV ) {
  1128. /*
  1129. * figure out which direction this value indicates...
  1130. */
  1131. if( (dwVal > myPOV[POV_MIN][JOY_POVVAL_FORWARD])
  1132. &&(dwVal < myPOV[POV_MAX][JOY_POVVAL_FORWARD]) )
  1133. {
  1134. dwResult = JOY_POVFORWARD;
  1135. }
  1136. else if( (dwVal > myPOV[POV_MIN][JOY_POVVAL_BACKWARD])
  1137. &&(dwVal < myPOV[POV_MAX][JOY_POVVAL_BACKWARD]) )
  1138. {
  1139. dwResult = JOY_POVBACKWARD;
  1140. }
  1141. else if( (dwVal > myPOV[POV_MIN][JOY_POVVAL_LEFT])
  1142. &&(dwVal < myPOV[POV_MAX][JOY_POVVAL_LEFT]) )
  1143. {
  1144. dwResult = JOY_POVLEFT;
  1145. }
  1146. else if( (dwVal > myPOV[POV_MIN][JOY_POVVAL_RIGHT])
  1147. &&(dwVal < myPOV[POV_MAX][JOY_POVVAL_RIGHT]) )
  1148. {
  1149. dwResult = JOY_POVRIGHT;
  1150. }
  1151. else
  1152. {
  1153. dwResult = JOY_POVCENTERED;
  1154. }
  1155. } else {
  1156. dwResult = dwVal;
  1157. }
  1158. #if 0
  1159. {
  1160. TCHAR buf[100];
  1161. if( bPolledPOV ) {
  1162. wsprintf(buf, TEXT("calibrated pov: %d\r\n"), dwResult);
  1163. } else {
  1164. wsprintf(buf, TEXT("uncalibrated pov: %d\r\n"), dwResult);
  1165. }
  1166. OutputDebugString(buf);
  1167. }
  1168. #endif
  1169. return dwResult;
  1170. }
  1171. /*
  1172. * doPOVCal - compute calibration for POV for a direction
  1173. */
  1174. static void __inline doPOVCal( LPJOYREGHWCONFIG pHWCfg, DWORD dwDir, LPDWORD dwOrder )
  1175. {
  1176. DWORD dwVal;
  1177. int nDir;
  1178. for( nDir=0; nDir<JOY_POV_NUMDIRS; nDir++ )
  1179. {
  1180. if( dwOrder[nDir] == dwDir )
  1181. {
  1182. break;
  1183. }
  1184. }
  1185. if( nDir == 0 )
  1186. {
  1187. dwVal = 1;
  1188. }
  1189. else
  1190. {
  1191. dwVal = (pHWCfg->hwv.dwPOVValues[dwDir] + pHWCfg->hwv.dwPOVValues[dwOrder[nDir-1]])/2;
  1192. }
  1193. myPOV[POV_MIN][dwDir] = dwVal;
  1194. if( nDir == JOY_POV_NUMDIRS-1 ) {
  1195. dwVal = pHWCfg->hwv.dwPOVValues[dwDir]/10l;
  1196. dwVal += pHWCfg->hwv.dwPOVValues[dwDir];
  1197. } else {
  1198. dwVal = (pHWCfg->hwv.dwPOVValues[dwOrder[nDir+1]] + pHWCfg->hwv.dwPOVValues[dwDir])/2;
  1199. }
  1200. myPOV[POV_MAX][dwDir] = dwVal;
  1201. } /* doPOVCal */
  1202. ///////////////////////////////////////////////////////////////////////////////
  1203. // FUNCTION: CalibratePolledPOV( LPJOYREGHWCONFIG pHWCfg )
  1204. //
  1205. // PARAMETERS:
  1206. //
  1207. //
  1208. // PURPOSE:
  1209. //
  1210. // RETURN:
  1211. ///////////////////////////////////////////////////////////////////////////////
  1212. void CalibratePolledPOV( LPJOYREGHWCONFIG pHWCfg )
  1213. {
  1214. DWORD dwOrder[JOY_POV_NUMDIRS];
  1215. DWORD dwTmp[JOY_POV_NUMDIRS];
  1216. DWORD dwVal;
  1217. int nDir,nDir2;
  1218. /*
  1219. * calibrate POV for polling based ones
  1220. */
  1221. for( nDir=0; nDir<JOY_POV_NUMDIRS; nDir++ )
  1222. {
  1223. dwTmp[nDir] = pHWCfg->hwv.dwPOVValues[nDir];
  1224. dwOrder[nDir] = nDir;
  1225. }
  1226. /*
  1227. * sort (did you ever think you'd see a bubble sort again?)
  1228. */
  1229. for( nDir=0;nDir<JOY_POV_NUMDIRS;nDir++ )
  1230. {
  1231. for( nDir2=nDir; nDir2<JOY_POV_NUMDIRS; nDir2++ )
  1232. {
  1233. if( dwTmp[nDir] > dwTmp[nDir2] )
  1234. {
  1235. dwVal = dwTmp[nDir];
  1236. dwTmp[nDir] = dwTmp[nDir2];
  1237. dwTmp[nDir2] = dwVal;
  1238. dwVal = dwOrder[nDir];
  1239. dwOrder[nDir] = dwOrder[nDir2];
  1240. dwOrder[nDir2] = dwVal;
  1241. }
  1242. }
  1243. }
  1244. for( nDir=0; nDir<JOY_POV_NUMDIRS; nDir++ )
  1245. {
  1246. doPOVCal( pHWCfg, nDir, dwOrder );
  1247. }
  1248. myPOV[POV_MIN][JOY_POV_NUMDIRS] = 0;
  1249. myPOV[POV_MAX][JOY_POV_NUMDIRS] = 0;
  1250. } /* CalibratePolledPOV */
  1251. #endif