Source code of Windows XP (NT5)
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.

2024 lines
67 KiB

  1. //===========================================================================
  2. // CAL.CPP... Would be CALIBRATE.CPP, but that's not 8.3 compliant :(
  3. //
  4. // Functions:
  5. //
  6. // CalInitProc
  7. // CalXYProc
  8. // CalSliderProc
  9. // CalPovProc
  10. // CalStateChange
  11. // CollectCalInfo
  12. // EnableXYWindows
  13. // GetOEMCtrlString
  14. //
  15. //===========================================================================
  16. // This is necessary or PSH_WIZARD_LITE will not be defined!
  17. #if (_WIN32_IE < 0x0500)
  18. #undef _WIN32_IE
  19. #define _WIN32_IE 0x0500
  20. #endif
  21. // This is necessary for UnregisterDeviceNotification!
  22. #if (WINVER < 0x0500)
  23. #undef WINVER
  24. #define WINVER 0x0500
  25. #endif
  26. // Uncomment if we decide to calibrate the POV!
  27. #define WE_SUPPORT_CALIBRATING_POVS 1
  28. #include "cplsvr1.h"
  29. //#include <windowsx.h>
  30. #include <mmsystem.h>
  31. #include <malloc.h>
  32. #include "cplsvr1.h"
  33. #ifdef _UNICODE
  34. #include <winuser.h> // For RegisterDeviceNotification stuff!
  35. #include <dbt.h> // for DBT_ defines!!!
  36. #endif // _UNICODE
  37. // remove to remove support for calibration of deadzones!
  38. //#define DEADZONE 1
  39. #include "resource.h"
  40. #include "cal.h" // Data to be shared with other modules
  41. #include "calocal.h" // Local Data to this module
  42. #include "dicputil.h" // for OnContextMenu and OnHelp
  43. #include "pov.h" // for SetDegrees()
  44. #include <prsht.h> // includes the property sheet functionality
  45. #include <shlwapi.h> // for the Str... functions!
  46. #include <regstr.h> // for pre-defined Registry string names
  47. #include "Gradient.h" // for Gradient Fill Slider!
  48. // Local function prototypes!
  49. static void UpdateXYLabel (const HWND hDlg);
  50. static BOOL UpdateProgressLabel (const HWND hDlg);
  51. // myitoa prototype is in cplsvr1.h
  52. static void reverse (LPTSTR string);
  53. static void RawDataSelected (const HWND hWnd, BOOL bEnable);
  54. static void WizFinish (const HWND hWnd);
  55. // Calibration procedures!
  56. LRESULT CALLBACK CalInitProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  57. LRESULT CALLBACK CalXYProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  58. LRESULT CALLBACK CalSliderProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  59. #ifdef WE_SUPPORT_CALIBRATING_POVS
  60. LRESULT CALLBACK CalPovProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  61. #endif //WE_SUPPORT_CALIBRATING_POVS
  62. VOID CALLBACK TimerProc (const HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  63. //static void EnableSliderWindows (const HWND hWnd, BOOL bEnable);
  64. HWND ProgWndCal; // Handle to Progress Control Window
  65. //DWORD dwUsage; // Usage flags for the device being calibrated!
  66. char nCalState; // Flag state variable!
  67. char nPrevCalState;
  68. LPMYJOYRANGE pRanges; // Ranges recieved by the Calibration!
  69. BOOL bShowRawData;
  70. LPWSTR lpwszTypeName; // Set in WM_INIT, Used in GetOEMCtrlString
  71. LPDIJOYCONFIG_DX5 pJoyConfig; // DIJC_REGHWCONFIGTYPE information about the device!
  72. //
  73. extern LPMYJOYRANGE lpCurrentRanges;
  74. extern LPDIJOYSTATE lpDIJoyState; // Defined in TEST.CPP
  75. extern CDIGameCntrlPropSheet_X *pdiCpl;
  76. extern HINSTANCE ghInst;
  77. HFONT hTitleFont;
  78. static LPDIRECTINPUTDEVICE2 pdiDevice2;
  79. static CGradientProgressCtrl *pGradient;
  80. static BOOL bGradient;
  81. //****************************************************************************
  82. //
  83. // FUNCTION: CreateWizard(HWND hwndOwner, LPARAM lParam)
  84. //
  85. // PURPOSE: Create the Wizard control.
  86. //
  87. // COMMENTS:
  88. //
  89. // This function creates the wizard property sheet.
  90. //****************************************************************************
  91. short CreateWizard(const HWND hwndOwner, LPARAM lParam)
  92. {
  93. #ifdef WE_SUPPORT_CALIBRATING_POVS
  94. const BYTE nTempArray[] = {IDD_INITIAL, IDD_XY, IDD_SLIDER, IDD_POV };
  95. const DLGPROC pDlgProc[] = {(DLGPROC)CalInitProc, (DLGPROC)CalXYProc, (DLGPROC)CalSliderProc, (DLGPROC)CalPovProc };
  96. #else
  97. const BYTE nTempArray[] = {IDD_INITIAL, IDD_XY, IDD_SLIDER };
  98. const DLGPROC pDlgProc[] = {(DLGPROC)CalInitProc, (DLGPROC)CalXYProc, (DLGPROC)CalSliderProc };
  99. #endif
  100. HPROPSHEETPAGE *pPages = new (HPROPSHEETPAGE[sizeof(nTempArray)/sizeof(BYTE)]);
  101. if( !pPages ) {
  102. return 0;
  103. }
  104. // Allocate and Zero the Page header memory
  105. PROPSHEETHEADER *ppsh = new (PROPSHEETHEADER);
  106. if( !ppsh ) {
  107. delete[] (pPages);
  108. return 0;
  109. }
  110. ZeroMemory(ppsh, sizeof(PROPSHEETHEADER));
  111. ppsh->dwSize = sizeof(PROPSHEETHEADER);
  112. ppsh->dwFlags = PSH_WIZARD_LITE | PSH_NOAPPLYNOW | PSH_USEICONID;
  113. ppsh->hwndParent = hwndOwner;
  114. ppsh->pszIcon = MAKEINTRESOURCE(IDI_GCICON);
  115. ppsh->hInstance = ghInst;
  116. ppsh->phpage = pPages;
  117. ppsh->pszbmWatermark = MAKEINTRESOURCE(IDB_CALHD);
  118. PROPSHEETPAGE *ppsp = new (PROPSHEETPAGE);
  119. if( !ppsp ) {
  120. delete[] (pPages);
  121. delete (ppsh);
  122. return 0;
  123. }
  124. ZeroMemory(ppsp, sizeof(PROPSHEETPAGE));
  125. ppsp->dwSize = sizeof(PROPSHEETPAGE);
  126. // ppsp->pszTitle = MAKEINTRESOURCE(nTabID);
  127. ppsp->hInstance = ghInst;
  128. ppsp->lParam = lParam;
  129. while( ppsh->nPages < (sizeof(nTempArray)/sizeof(BYTE)) ) {
  130. ppsp->pfnDlgProc = pDlgProc[ppsh->nPages];
  131. ppsp->pszTemplate = MAKEINTRESOURCE(nTempArray[ppsh->nPages]);
  132. ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(ppsp);
  133. ppsh->nPages++;
  134. }
  135. if( ppsp )
  136. delete (ppsp);
  137. short nRet = (short)PropertySheet(ppsh);
  138. if( pPages )
  139. delete[] (pPages);
  140. // Clean up!
  141. if( ppsh )
  142. delete (ppsh);
  143. return(nRet);
  144. }
  145. //*******************************************************************************
  146. //
  147. // FUNCTION: CalInitProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  148. //
  149. // PURPOSE: Procedure for Start-up screen
  150. //
  151. // COMMENTS: This function is responsible for display of text and bitmap.
  152. // Since it is also the only page that is Guarenteed to be hit,
  153. // it is also responsible for creating, deleteing, and storing
  154. // everything for the calibration wizard.
  155. //
  156. //*******************************************************************************
  157. LRESULT CALLBACK CalInitProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  158. {
  159. static HFONT hBoldFont;
  160. static PVOID hNotifyDevNode;
  161. switch( uMsg ) {
  162. case WM_LBUTTONDOWN:
  163. // Click Drag service for PropSheets!
  164. PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam);
  165. break;
  166. #ifdef _UNICODE
  167. case WM_DEVICECHANGE:
  168. if( (UINT)wParam == DBT_DEVICEREMOVECOMPLETE )
  169. ::PostMessage(GetParent(hWnd), WM_COMMAND, IDCANCEL, 0);
  170. break;
  171. #endif
  172. // OnInit
  173. case WM_INITDIALOG:
  174. // Init to FALSE to turn off Gradient fill!
  175. bGradient = FALSE;
  176. // According to knowlege base artical Q138505, this is the prescribed method of removing
  177. // the context sensitive help '?' from the title bar.
  178. {
  179. LONG style = ::GetWindowLong(GetParent(hWnd), GWL_EXSTYLE);
  180. style &= ~WS_EX_CONTEXTHELP;
  181. HWND hParent = GetParent(hWnd);
  182. ::SetWindowLong(hParent, GWL_EXSTYLE, style);
  183. // Set up the Device Notification
  184. #ifdef _UNICODE
  185. RegisterForDevChange(hWnd, &hNotifyDevNode);
  186. #endif
  187. HDC myDC = GetDC(hWnd);
  188. if( myDC ) { // Prefix Whistler 45095
  189. hTitleFont = CreateFont(-MulDiv(8, GetDeviceCaps(myDC, LOGPIXELSY), 72), 0, 0,
  190. 0, FW_SEMIBOLD, FALSE,
  191. FALSE, FALSE, DEFAULT_CHARSET,
  192. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
  193. DEFAULT_PITCH | FF_DONTCARE, TEXT("MS Shell Dlg"));
  194. // Do the Create font thing...
  195. hBoldFont = CreateFont(-MulDiv(15, GetDeviceCaps(myDC, LOGPIXELSY), 72), 0, 0,
  196. 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
  197. PROOF_QUALITY, DEFAULT_PITCH | FF_ROMAN, TEXT("MS Shell Dlg"));
  198. ReleaseDC(hWnd, myDC);
  199. }
  200. if( hBoldFont )
  201. ::SendDlgItemMessage(hWnd, IDC_INIT_TITLE, WM_SETFONT, (WPARAM)hBoldFont, TRUE);
  202. CenterDialog(hWnd);
  203. ::PostMessage(hParent, PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT);
  204. bShowRawData = FALSE;
  205. // Allocate the memory for the ranges!
  206. pRanges = new MYJOYRANGE;
  207. assert(pRanges);
  208. // Set Everything to
  209. ZeroMemory(pRanges, sizeof(MYJOYRANGE));
  210. // Get the "best guess" ranges...
  211. CopyMemory(pRanges, lpCurrentRanges, sizeof(MYJOYRANGE));
  212. pdiCpl->GetDevice(&pdiDevice2);
  213. // Attempt to Set them... die if you can't!
  214. SetMyRanges(pdiDevice2, pRanges, pdiCpl->GetStateFlags()->nAxis);
  215. if( FAILED(GetLastError()) ) {
  216. Error(hWnd, (short)IDS_USER_MODE_TITLE, (short)IDS_USER_MODE);
  217. PostMessage(GetParent(hWnd), WM_SYSCOMMAND, SC_CLOSE, 0L);
  218. }
  219. pJoyConfig = new(DIJOYCONFIG_DX5);
  220. assert (pJoyConfig);
  221. pJoyConfig->dwSize = sizeof (DIJOYCONFIG_DX5);
  222. LPDIRECTINPUTJOYCONFIG pdiJoyConfig;
  223. pdiCpl->GetJoyConfig(&pdiJoyConfig);
  224. HRESULT hres;
  225. // Retrieve and store Hardware Configuration about the device!
  226. hres = pdiJoyConfig->GetConfig(pdiCpl->GetID(), (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE | DIJC_GUIDINSTANCE);
  227. if( SUCCEEDED(hres) ) {
  228. bPolledPOV = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_HASPOV) && (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL);
  229. CalibratePolledPOV( &pJoyConfig->hwc );
  230. }
  231. }
  232. break;
  233. // Change the background of all Static text fields to WHITE
  234. case WM_CTLCOLORSTATIC:
  235. return(LRESULT)GetStockObject(WHITE_BRUSH);
  236. case WM_DESTROY:
  237. if( pJoyConfig )
  238. delete (pJoyConfig);
  239. if( lpwszTypeName )
  240. LocalFree(lpwszTypeName);
  241. pdiDevice2->Unacquire();
  242. SetCalibrationMode( FALSE );
  243. if( hTitleFont )
  244. DeleteObject((HGDIOBJ)hTitleFont);
  245. if( hBoldFont )
  246. DeleteObject((HGDIOBJ)hBoldFont);
  247. // if you call this function you will hang up the system for 30 seconds or more!!!
  248. #ifdef _UNICODE
  249. if( hNotifyDevNode )
  250. UnregisterDeviceNotification(hNotifyDevNode);
  251. #endif // _UNICODE
  252. break;
  253. }
  254. return(DefWindowProc(hWnd, uMsg, wParam, lParam));
  255. }
  256. //*******************************************************************************
  257. //
  258. // FUNCTION: CalXYProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  259. //
  260. // PURPOSE: Procedure for first three stages of calibration
  261. //
  262. // COMMENTS: This function is responsible for capture of X/Y and Center values!
  263. //
  264. //*******************************************************************************
  265. LRESULT CALLBACK CalXYProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  266. {
  267. switch( uMsg ) {
  268. case WM_LBUTTONDOWN:
  269. // Click Drag service for PropSheets!
  270. PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam);
  271. break;
  272. // OnInit
  273. case WM_INITDIALOG:
  274. {
  275. // set up the local globals
  276. nCalState = JCS_XY_CENTER1;
  277. nPrevCalState = JCS_INIT;
  278. // Get the JoyConfig Interface Pointer!
  279. LPDIRECTINPUTJOYCONFIG pdiJoyConfig;
  280. pdiCpl->GetJoyConfig(&pdiJoyConfig);
  281. if( SUCCEEDED(pdiJoyConfig->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND)) ) {
  282. // Set the font for the
  283. ::SendDlgItemMessage(hWnd, IDC_WIZARD_MSG_HDR, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
  284. lpwszTypeName = StrDupW(pJoyConfig->wszType);
  285. // This sets up the Windows and the global ProgWndCal!
  286. UpdateXYLabel(hWnd);
  287. // Set up for first round
  288. CalStateChange( hWnd, (BYTE)pJoyConfig->hwc.hws.dwFlags );
  289. VERIFY(SUCCEEDED(SetCalibrationMode(TRUE)));
  290. VERIFY(FAILED(pdiDevice2->Acquire()));
  291. }
  292. }
  293. break;
  294. // Change the background of all Static text fields to WHITE
  295. case WM_CTLCOLORSTATIC:
  296. // We only want to paint the background for the items in the top white rectangle!
  297. switch( GetDlgCtrlID((HWND)lParam) ) {
  298. case IDC_WIZARD_MSG:
  299. case IDC_HEADERFRAME:
  300. case IDC_WIZARD_MSG_HDR:
  301. return(LRESULT)GetStockObject(WHITE_BRUSH);
  302. }
  303. return(FALSE);
  304. // OnNotify
  305. case WM_NOTIFY:
  306. switch( ((NMHDR FAR *) lParam)->code ) {
  307. case PSN_KILLACTIVE:
  308. KillTimer(hWnd, ID_CAL_TIMER);
  309. break;
  310. case PSN_RESET:
  311. // reset to the original values
  312. KillTimer(hWnd, ID_CAL_TIMER);
  313. break;
  314. case PSN_SETACTIVE:
  315. SetTimer( hWnd, ID_CAL_TIMER, CALIBRATION_INTERVAL, (TIMERPROC)TimerProc);
  316. // Sorry, you can't go back to the first page...
  317. if( nCalState > JCS_XY_CENTER1 )
  318. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT | PSWIZB_BACK);
  319. else
  320. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT);
  321. break;
  322. case PSN_WIZBACK:
  323. // Determine what the next calibration stage is!
  324. // Look out... we're backing up!
  325. if( nCalState == nPrevCalState )
  326. nPrevCalState--;
  327. nCalState = nPrevCalState;
  328. CalStateChange(hWnd, (BYTE)pJoyConfig->hwc.hws.dwFlags);
  329. // No more backing up!
  330. if( nCalState == JCS_XY_CENTER1 )
  331. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT);
  332. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_XY_CENTER1) ? IDD_INITIAL : -1);
  333. return(nCalState < JCS_XY_CENTER1) ? IDD_INITIAL : -1;
  334. case PSN_WIZNEXT:
  335. nPrevCalState = nCalState;
  336. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT | PSWIZB_BACK);
  337. #if 0
  338. // Determine what the next calibration stage is!
  339. #ifndef DEADZONE
  340. //while ((!(pdiCpl->GetStateFlags()->nAxis & 1<<nCalState++)) && (nCalState < JCS_FINI));
  341. nCalState++;
  342. #else
  343. nCalState++;
  344. #endif // DEADZONE
  345. #endif
  346. while( (!(pdiCpl->GetStateFlags()->nAxis & (1<<nCalState++) )) && (nCalState < JCS_FINI) );
  347. if( nCalState > JCS_FINI )
  348. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH | PSWIZB_BACK);
  349. else if( nCalState < JCS_Z_MOVE )
  350. CalStateChange( hWnd, (BYTE)pJoyConfig->hwc.hws.dwFlags );
  351. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_Z_MOVE) ? -1 : IDD_SLIDER );
  352. return(nCalState < JCS_Z_MOVE) ? -1 : IDD_SLIDER;
  353. default:
  354. return(FALSE);
  355. }
  356. break;
  357. // OnCommand
  358. case WM_COMMAND:
  359. switch( LOWORD(wParam) ) {
  360. case IDC_RAWDATA:
  361. RawDataSelected(hWnd, bShowRawData = !bShowRawData);
  362. break;
  363. }
  364. break;
  365. // OnDestroy
  366. case WM_DESTROY:
  367. if( pRanges ) {
  368. delete (pRanges);
  369. pRanges = NULL;
  370. }
  371. break;
  372. default:
  373. return(FALSE);
  374. }
  375. return(TRUE);
  376. }
  377. //****************************************************************************
  378. //
  379. // FUNCTION: CalSliderProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  380. //
  381. // PURPOSE: Procedure
  382. //
  383. // COMMENTS:
  384. //
  385. // This function creates the wizard property sheet.
  386. //****************************************************************************
  387. LRESULT CALLBACK CalSliderProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  388. {
  389. switch( uMsg ) {
  390. case WM_LBUTTONDOWN:
  391. // Click Drag service for PropSheets!
  392. PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam);
  393. break;
  394. case WM_INITDIALOG:
  395. // Set the Control font!
  396. ::SendDlgItemMessage(hWnd,IDC_WIZARD_MSG_HDR, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
  397. #ifdef DEADZONE
  398. ::SendDlgItemMessage(hWnd, IDC_DEADZONE_TITLE, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
  399. ::SendDlgItemMessage(hWnd, IDC_SATURATION_TITLE, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
  400. #endif //DEADZONE
  401. // Setup the Progress bar!
  402. ProgWndCal = GetDlgItem(hWnd, IDC_SLIDER);
  403. // do the Gradient fill maddness!
  404. {
  405. HDC hDC = ::GetWindowDC(hWnd);
  406. if( hDC ) {
  407. bGradient = (BOOL)(GetDeviceCaps(hDC, NUMCOLORS) < 0);
  408. if( bGradient ) {
  409. pGradient = new (CGradientProgressCtrl);
  410. pGradient->SubclassWindow(GetDlgItem(hWnd, IDC_SLIDER));
  411. pGradient->SetDirection(HORIZONTAL);
  412. //pGradient->ShowPercent();
  413. pGradient->SetStartColor(COLORREF(RGB(0,0,255)));
  414. pGradient->SetEndColor(COLORREF(RGB(0,0,0)));
  415. pGradient->SetBkColor(COLORREF(RGB(180,180,180)));
  416. }
  417. ::ReleaseDC(hWnd, hDC);
  418. }
  419. }
  420. if( nCalState < JCS_FINI ) {
  421. // UpdateProgressLabel MUST be called Before CalStateChange!!!
  422. UpdateProgressLabel(hWnd);
  423. // If we're not using the gradient control, set the bar
  424. // colour PBM_SETBARCOLOR is WM_USER+9... YES, it's undocumented...
  425. if( !bGradient ) {
  426. ::PostMessage(ProgWndCal, WM_USER+9, 0, (LPARAM)ACTIVE_COLOR);
  427. }
  428. } else {
  429. ::PostMessage(GetParent(hWnd), PSM_PRESSBUTTON, (WPARAM)(int)PSBTN_NEXT, 0);
  430. }
  431. break;
  432. case WM_DESTROY:
  433. if( bGradient )
  434. if( pGradient )
  435. delete (pGradient);
  436. break;
  437. // OnCommand
  438. case WM_COMMAND:
  439. switch( LOWORD(wParam) ) {
  440. case IDC_RAWDATA:
  441. RawDataSelected(hWnd, bShowRawData = !bShowRawData);
  442. if( bGradient )
  443. pGradient->ShowPercent(bShowRawData);
  444. break;
  445. }
  446. break;
  447. // Change the background of all Static text fields to WHITE
  448. case WM_CTLCOLORSTATIC:
  449. // We only want to paint the background for the items in the top white rectangle!
  450. switch( GetDlgCtrlID((HWND)lParam) ) {
  451. case IDC_WIZARD_MSG:
  452. case IDC_HEADERFRAME:
  453. case IDC_WIZARD_MSG_HDR:
  454. return(LRESULT)GetStockObject(WHITE_BRUSH);
  455. }
  456. return(FALSE);
  457. case WM_NOTIFY:
  458. switch( ((NMHDR FAR *) lParam)->code ) {
  459. case PSN_KILLACTIVE:
  460. KillTimer(hWnd, ID_CAL_TIMER);
  461. break;
  462. case PSN_SETACTIVE:
  463. // Set up for first round
  464. CalStateChange( hWnd, (BYTE)NULL );
  465. SetTimer( hWnd, ID_CAL_TIMER, CALIBRATION_INTERVAL, (TIMERPROC)TimerProc);
  466. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT | PSWIZB_BACK);
  467. break;
  468. case PSN_WIZBACK:
  469. // Determine what the previous calibration stage is!
  470. if( nCalState == nPrevCalState ) {
  471. DWORD dwAxis = pdiCpl->GetStateFlags()->nAxis;
  472. nPrevCalState --;
  473. while( ( !(dwAxis & (1<<(--nPrevCalState)) ) ) && (nPrevCalState > JCS_XY_CENTER2) ){
  474. ;
  475. }
  476. nPrevCalState ++;
  477. }
  478. nCalState = nPrevCalState;
  479. if( nCalState > JCS_XY_CENTER2 ) {
  480. // UpdateProgressLabel MUST be called Before CalStateChange!!!
  481. UpdateProgressLabel(hWnd);
  482. CalStateChange( hWnd, (BYTE)NULL );
  483. }
  484. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_Z_MOVE) ? IDD_XY : -1);
  485. return(nCalState < JCS_Z_MOVE) ? IDD_XY : -1;
  486. case PSN_WIZNEXT:
  487. nPrevCalState = nCalState;
  488. // Determine what the next calibration stage is!
  489. while( (!(pdiCpl->GetStateFlags()->nAxis & 1<<nCalState++)) && (nCalState < JCS_FINI) );
  490. if( nCalState <= JCS_S1_MOVE ) {
  491. UpdateProgressLabel(hWnd);
  492. #ifdef WE_SUPPORT_CALIBRATING_POVS
  493. } else if( bPolledPOV ) {
  494. nCalState = JCS_S1_MOVE + 1;
  495. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, IDD_POV );
  496. return(IDD_POV);
  497. #endif
  498. } else {
  499. // Remove the dialog items you no longer need...
  500. //EnableSliderWindows(hWnd, FALSE);
  501. const short nCtrlArray[] = {IDC_SLIDER, IDC_RAWDATA, IDC_RAWX, IDC_RAWXOUTPUT, IDC_JOYLIST2_LABEL};
  502. BYTE nSize = sizeof(nCtrlArray)/sizeof(short);
  503. do {
  504. SetWindowPos( GetDlgItem(hWnd, nCtrlArray[--nSize]), NULL, NULL, NULL, NULL, NULL,
  505. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW );
  506. } while( nSize );
  507. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH);
  508. }
  509. CalStateChange( hWnd, (BYTE)NULL );
  510. // we have no further pages, so don't allow them to go any further!
  511. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, -1);
  512. return(-1);
  513. case PSN_WIZFINISH:
  514. WizFinish(hWnd);
  515. break;
  516. default:
  517. return(FALSE);
  518. }
  519. break;
  520. default:
  521. return(FALSE);
  522. }
  523. return(TRUE);
  524. }
  525. //*******************************************************************************
  526. //
  527. // FUNCTION: EnableSliderWindows(HWND hWnd, BOOL bEnable)
  528. //
  529. // PURPOSE: Procedure to Show/Hide dialog controls during CalSliderProc's life
  530. //
  531. // COMMENTS:
  532. //
  533. //*******************************************************************************
  534. /*
  535. void EnableSliderWindows(const HWND hWnd, BOOL bEnable)
  536. {
  537. const short nCtrlArray[] = {IDC_SLIDER, IDC_RAWDATA, IDC_RAWX, IDC_RAWXOUTPUT, IDC_JOYLIST2_LABEL};
  538. BYTE nSize = sizeof(nCtrlArray)/sizeof(short);
  539. do
  540. {
  541. SetWindowPos( GetDlgItem(hWnd, nCtrlArray[--nSize]), NULL, NULL, NULL, NULL, NULL,
  542. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | (bEnable ? SWP_SHOWWINDOW : SWP_HIDEWINDOW ));
  543. } while (nSize);
  544. }
  545. */
  546. #ifdef WE_SUPPORT_CALIBRATING_POVS
  547. //****************************************************************************
  548. //
  549. // FUNCTION: CalPovProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  550. //
  551. // PURPOSE: Procedure
  552. //
  553. // COMMENTS:
  554. //
  555. // This function creates the wizard property sheet.
  556. //****************************************************************************
  557. LRESULT CALLBACK CalPovProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  558. {
  559. switch( uMsg ) {
  560. case WM_ACTIVATEAPP:
  561. if( lpDIJoyState )
  562. DoTestPOV(FORCE_POV_REFRESH, lpDIJoyState->rgdwPOV, hWnd);
  563. break;
  564. case WM_INITDIALOG:
  565. {
  566. // Set the POV position to the Up position and Set the Text!
  567. nCalState = JCS_POV_MOVEUP;
  568. HWND hwndPOV = GetDlgItem(hWnd, IDC_JOYPOV);
  569. // Disable RTL flag
  570. SetWindowLongPtr(hwndPOV, GWL_EXSTYLE, GetWindowLongPtr(hwndPOV,GWL_EXSTYLE)&~WS_EX_LAYOUTRTL);
  571. // Set the Control font!
  572. ::SendDlgItemMessage(hWnd,IDC_WIZARD_MSG_HDR, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
  573. break;
  574. }
  575. case WM_DESTROY:
  576. break;
  577. case WM_COMMAND:
  578. switch( LOWORD(wParam) ) {
  579. case IDC_RAWDATA:
  580. RawDataSelected(hWnd, bShowRawData = !bShowRawData);
  581. break;
  582. case IDC_SETPOV:
  583. //if( joyGetPosEx(pdiCpl->GetID(), lpJoyInfo) == JOYERR_NOERROR ) {
  584. if( SUCCEEDED(DIUtilPollJoystick(pdiDevice2, lpDIJoyState)) ) {
  585. CollectCalInfo(hWnd, lpDIJoyState);
  586. // Insert the POV information!
  587. switch( nCalState ) {
  588. case JCS_POV_MOVEUP:
  589. // Store what we got!
  590. pRanges->dwPOV[JOY_POVVAL_FORWARD] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_FORWARD] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0;
  591. // Once you're here... disable the buttons... no going back and forth...
  592. ::SendMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_DISABLEDFINISH);
  593. break;
  594. case JCS_POV_MOVERIGHT:
  595. // Store what we got!
  596. pRanges->dwPOV[JOY_POVVAL_RIGHT] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_RIGHT] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0;
  597. break;
  598. case JCS_POV_MOVEDOWN:
  599. // Store what we got!
  600. pRanges->dwPOV[JOY_POVVAL_BACKWARD] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_BACKWARD] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0;
  601. break;
  602. case JCS_POV_MOVELEFT:
  603. // Store what we got!
  604. pRanges->dwPOV[JOY_POVVAL_LEFT] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_LEFT] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0;
  605. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH);
  606. // Take away the controls... it's all over!
  607. DestroyWindow(GetDlgItem(hWnd, IDC_JOYPOV));
  608. DestroyWindow(GetDlgItem(hWnd, IDC_SETPOV));
  609. break;
  610. }
  611. }
  612. nCalState++;
  613. CalStateChange(hWnd, NULL);
  614. // Set the focus back to IDC_SETPOV button!
  615. SendMessage(hWnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hWnd, IDC_SETPOV), (LPARAM)TRUE);
  616. break;
  617. }
  618. break;
  619. // Change the background of all Static text fields to WHITE
  620. case WM_CTLCOLORSTATIC:
  621. // We only want to paint the background for the items in the top white rectangle!
  622. switch( GetDlgCtrlID((HWND)lParam) ) {
  623. case IDC_WIZARD_MSG:
  624. case IDC_HEADERFRAME:
  625. case IDC_WIZARD_MSG_HDR:
  626. return(LRESULT)GetStockObject(WHITE_BRUSH);
  627. }
  628. return(FALSE);
  629. case WM_NOTIFY:
  630. switch( ((NMHDR FAR *) lParam)->code ) {
  631. case PSN_KILLACTIVE:
  632. KillTimer(hWnd, ID_CAL_TIMER);
  633. return(TRUE);
  634. case PSN_RESET:
  635. break;
  636. case PSN_SETACTIVE:
  637. if( nCalState == JCS_POV_MOVEUP ) {
  638. DoTestPOV(FORCE_POV_REFRESH, lpDIJoyState->rgdwPOV, hWnd);
  639. }
  640. CalStateChange(hWnd, NULL);
  641. break;
  642. case PSN_WIZFINISH:
  643. WizFinish(hWnd);
  644. break;
  645. case PSN_WIZBACK:
  646. // Determine what the next calibration stage is!
  647. if( nCalState == nPrevCalState ) {
  648. DWORD dwAxis = pdiCpl->GetStateFlags()->nAxis;
  649. nPrevCalState --;
  650. while( ( !(dwAxis & (1<<(--nPrevCalState)) ) ) && (nPrevCalState > JCS_XY_CENTER2) ){
  651. ;
  652. }
  653. nPrevCalState ++;
  654. }
  655. nCalState = nPrevCalState;
  656. if( nCalState > JCS_XY_CENTER2 ) {
  657. if( nCalState <= JCS_S1_MOVE ) {
  658. UpdateProgressLabel(hWnd);
  659. CalStateChange( hWnd, (BYTE)NULL );
  660. } else if( bPolledPOV ) {
  661. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, IDD_POV );
  662. return(IDD_POV);
  663. }
  664. } else {
  665. SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_Z_MOVE) ? IDD_XY : -1);
  666. return(nCalState < JCS_Z_MOVE) ? IDD_XY : -1;
  667. }
  668. break;
  669. case PSN_WIZNEXT:
  670. // Take away the controls... it's all over!
  671. DestroyWindow(GetDlgItem(hWnd, IDC_JOYPOV));
  672. DestroyWindow(GetDlgItem(hWnd, IDC_SETPOV));
  673. // Go on to Finish!
  674. nCalState = JCS_FINI;
  675. CalStateChange(hWnd, NULL);
  676. // Get rid of Back and bring on Finish!
  677. ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH);
  678. break;
  679. default:
  680. return(FALSE);
  681. }
  682. break;
  683. default:
  684. return(FALSE);
  685. }
  686. return(TRUE);
  687. }
  688. #endif // WE_SUPPORT_CALIBRATING_POVS
  689. //*******************************************************************************
  690. //
  691. // FUNCTION: CalStateChange( HWND hDlg, BYTE nDeviceFlags )
  692. //
  693. // PURPOSE: Procedure to set up the dialog for its' Next stage
  694. //
  695. // COMMENTS:
  696. //
  697. //*******************************************************************************
  698. void CalStateChange( HWND hDlg, BYTE nDeviceFlags )
  699. {
  700. short nMsgID = IDS_JOYCAL_MOVE;
  701. short nTitleID = IDS_AXIS_CALIBRATION;
  702. #define MAX_CAL_VAL 0xfffffff
  703. switch( nCalState ) {
  704. case JCS_XY_CENTER1:
  705. case JCS_XY_CENTER2:
  706. // Set up the string ID
  707. if( nDeviceFlags & JOY_HWS_ISYOKE )
  708. nMsgID = IDS_JOYCALXY_CENTERYOKE;
  709. else if( nDeviceFlags & JOY_HWS_ISCARCTRL )
  710. nMsgID = IDS_JOYCALXY_CENTERCAR;
  711. else if( nDeviceFlags & JOY_HWS_ISGAMEPAD )
  712. nMsgID = IDS_JOYCALXY_CENTERGAMEPAD;
  713. else nMsgID = IDS_JOYCALXY_CENTER;
  714. // Setup the Header TextID
  715. nTitleID = (nCalState == JCS_XY_CENTER1) ? IDS_CENTER_HDR : IDS_VERIFY_CENTER_HDR;
  716. EnableXYWindows( hDlg );
  717. break;
  718. case JCS_XY_MOVE:
  719. // Set up the string ID
  720. if( nDeviceFlags & JOY_HWS_ISYOKE )
  721. nMsgID = IDS_JOYCALXY_MOVEYOKE;
  722. else if( nDeviceFlags & JOY_HWS_ISCARCTRL )
  723. nMsgID = IDS_JOYCALXY_MOVECAR;
  724. else if( nDeviceFlags & JOY_HWS_ISGAMEPAD )
  725. nMsgID = IDS_JOYCALXY_MOVEGAMEPAD;
  726. else nMsgID = IDS_JOYCALXY_MOVE;
  727. // Blast the data so we are sure to get the correct data!
  728. pRanges->jpMin.dwX = MAX_CAL_VAL;
  729. pRanges->jpMax.dwX = -MAX_CAL_VAL;
  730. pRanges->jpMin.dwY = MAX_CAL_VAL;
  731. pRanges->jpMax.dwY = -MAX_CAL_VAL;
  732. EnableXYWindows( hDlg );
  733. break;
  734. /*
  735. case JCS_XY_CENTER1:
  736. // Set up the string ID
  737. if ( nDeviceFlags & JOY_HWS_ISYOKE )
  738. nMsgID = IDS_JOYCALXY_CENTERYOKE;
  739. else if( nDeviceFlags & JOY_HWS_ISCARCTRL )
  740. nMsgID = IDS_JOYCALXY_CENTERCAR;
  741. else if( nDeviceFlags & JOY_HWS_ISGAMEPAD )
  742. nMsgID = IDS_JOYCALXY_CENTERGAMEPAD;
  743. else nMsgID = IDS_JOYCALXY_CENTER;
  744. // Setup the Header TextID
  745. nTitleID = IDS_CENTER_HDR;
  746. EnableXYWindows( hDlg );
  747. break;
  748. case JCS_XY_MOVE:
  749. // Set up the string ID
  750. if( nDeviceFlags & JOY_HWS_ISYOKE )
  751. nMsgID = IDS_JOYCALXY_MOVEYOKE;
  752. else if( nDeviceFlags & JOY_HWS_ISCARCTRL )
  753. nMsgID = IDS_JOYCALXY_MOVECAR;
  754. else if( nDeviceFlags & JOY_HWS_ISGAMEPAD )
  755. nMsgID = IDS_JOYCALXY_MOVEGAMEPAD;
  756. else nMsgID = IDS_JOYCALXY_MOVE;
  757. // Blast the data so we are sure to get the correct data!
  758. pRanges->jpMin.dwX = MAX_CAL_VAL;
  759. pRanges->jpMax.dwX = -MAX_CAL_VAL;
  760. pRanges->jpMin.dwY = MAX_CAL_VAL;
  761. pRanges->jpMax.dwY = -MAX_CAL_VAL;
  762. EnableXYWindows( hDlg );
  763. break;
  764. case JCS_XY_CENTER2:
  765. // Set up the string ID
  766. if( nDeviceFlags & JOY_HWS_ISYOKE )
  767. nMsgID = IDS_JOYCALXY_CENTERYOKE;
  768. else if( nDeviceFlags & JOY_HWS_ISCARCTRL )
  769. nMsgID = IDS_JOYCALXY_CENTERCAR;
  770. else if( nDeviceFlags & JOY_HWS_ISGAMEPAD )
  771. nMsgID = IDS_JOYCALXY_CENTERGAMEPAD;
  772. else nMsgID = IDS_JOYCALXY_CENTER;
  773. // Setup the Header TextID
  774. nTitleID = IDS_VERIFY_CENTER_HDR;
  775. EnableXYWindows( hDlg );
  776. break;
  777. */
  778. #ifdef DEADZONE
  779. case JCS_DEADZONE:
  780. // Set up the message string.
  781. if( nDeviceFlags & JOY_HWS_ISYOKE )
  782. nMsgID = IDS_YOKE_DEADZONE;
  783. else if( nDeviceFlags & JOY_HWS_ISCARCTRL )
  784. nMsgID = IDS_CAR_DEADZONE;
  785. else if( nDeviceFlags & JOY_HWS_ISGAMEPAD )
  786. nMsgID = IDS_GAMEPAD_DEADZONE;
  787. else nMsgID = IDS_JOYSTICK_DEADZONE;
  788. // Set up the title string!
  789. nTitleID = IDS_DEADZONE_TITLE;
  790. // Setup the controls!
  791. EnableXYWindows( hDlg );
  792. // Text Labels are sent in during UpdateXYLabel!
  793. // Text fonts are set on INIT!
  794. // Setup the Spin positions!
  795. {
  796. LPDIPROPDWORD pDIPropDW = (LPDIPROPDWORD)_alloca(DIPROPDWORD);
  797. ASSERT (pDIPropDW);
  798. ZeroMemory(pDIPropDW, sizeof(DIPROPDWORD));
  799. pDIPropDW->diph.dwSize = sizeof(DIPROPDWORD);
  800. pDIPropDW->diph.dwHeaderSize = sizeof(DIPROPHEADER);
  801. pDIPropDW->diph.dwObj = DIJOFS_X;
  802. pDIPropDW->diph.dwHow = DIPH_BYOFFSET;
  803. HWND hSpinCtrl;
  804. // Deadzone first...
  805. if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_DEADZONE, &pDIPropDW->diph)) ) {
  806. // First the Deadzone...
  807. hSpinCtrl = GetDlgItem(hDlg, IDC_X_DEADZONE_SPIN);
  808. ::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1));
  809. ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L);
  810. ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0));
  811. }
  812. // Setup the DIPROPDWORD struct!
  813. pDIPropDW->diph.dwObj = DIJOFS_Y;
  814. if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_DEADZONE, &pDIPropDW->diph)) ) {
  815. // First the Deadzone...
  816. hSpinCtrl = GetDlgItem(hDlg, IDC_Y_DEADZONE_SPIN);
  817. ::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1));
  818. ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L);
  819. ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0));
  820. }
  821. // Now, the Saturation!
  822. if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_SATURATION, &pDIPropDW->diph)) ) {
  823. hSpinCtrl = GetDlgItem(hDlg, IDC_Y_SATURATION_SPIN);
  824. ::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1));
  825. ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L);
  826. ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0));
  827. }
  828. // Setup the DIPROPDWORD struct!
  829. pDIPropDW->diph.dwObj = DIJOFS_X;
  830. if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_SATURATION, &pDIPropDW->diph)) ) {
  831. hSpinCtrl = GetDlgItem(hDlg, IDC_X_SATURATION_SPIN);
  832. ::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1));
  833. ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L);
  834. ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0));
  835. }
  836. }
  837. // Draw the rectangle!
  838. break;
  839. #endif //DEADZONE
  840. case JCS_Z_MOVE:
  841. {
  842. static long nMin = pRanges->jpMin.dwZ;
  843. static long nMax = pRanges->jpMax.dwZ;
  844. // Set the Range
  845. if( bGradient )
  846. pGradient->SetRange(nMin, nMax);
  847. ::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
  848. // Blast the data so we are sure to get the correct data!
  849. pRanges->jpMin.dwZ = MAX_CAL_VAL;
  850. pRanges->jpMax.dwZ = -MAX_CAL_VAL;
  851. }
  852. break;
  853. case JCS_R_MOVE:
  854. {
  855. static long nMin = pRanges->jpMin.dwRx;
  856. static long nMax = pRanges->jpMax.dwRx;
  857. // Set the Range
  858. if( bGradient )
  859. pGradient->SetRange(nMin, nMax);
  860. ::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
  861. // Blast the data so we are sure to get the correct data!
  862. pRanges->jpMin.dwRx = MAX_CAL_VAL;
  863. pRanges->jpMax.dwRx = -MAX_CAL_VAL;
  864. }
  865. break;
  866. case JCS_U_MOVE:
  867. {
  868. static long nMin = pRanges->jpMin.dwRy;
  869. static long nMax = pRanges->jpMax.dwRy;
  870. // Set the Range
  871. if( bGradient )
  872. pGradient->SetRange(nMin, nMax);
  873. ::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
  874. // Blast the data so we are sure to get the correct data!
  875. pRanges->jpMin.dwRy = MAX_CAL_VAL;
  876. pRanges->jpMax.dwRy = -MAX_CAL_VAL;
  877. }
  878. break;
  879. case JCS_V_MOVE:
  880. {
  881. static long nMin = pRanges->jpMin.dwRz;
  882. static long nMax = pRanges->jpMax.dwRz;
  883. // Set the Range
  884. if( bGradient )
  885. pGradient->SetRange(nMin, nMax);
  886. ::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
  887. // Blast the data so we are sure to get the correct data!
  888. pRanges->jpMin.dwRz = MAX_CAL_VAL;
  889. pRanges->jpMax.dwRz = -MAX_CAL_VAL;
  890. }
  891. break;
  892. case JCS_S0_MOVE:
  893. {
  894. static long nMin = pRanges->jpMin.dwS0;
  895. static long nMax = pRanges->jpMax.dwS0;
  896. // Set the Range
  897. if( bGradient )
  898. pGradient->SetRange(nMin, nMax);
  899. ::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
  900. // Blast the data so we are sure to get the correct data!
  901. pRanges->jpMin.dwS0 = MAX_CAL_VAL;
  902. pRanges->jpMax.dwS0 = -MAX_CAL_VAL;
  903. }
  904. break;
  905. case JCS_S1_MOVE:
  906. {
  907. static long nMin = pRanges->jpMin.dwS1;
  908. static long nMax = pRanges->jpMax.dwS1;
  909. // Set the Range
  910. if( bGradient )
  911. pGradient->SetRange(nMin, nMax);
  912. ::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
  913. // Blast the data so we are sure to get the correct data!
  914. pRanges->jpMin.dwS1 = MAX_CAL_VAL;
  915. pRanges->jpMax.dwS1 = -MAX_CAL_VAL;
  916. }
  917. break;
  918. #ifdef WE_SUPPORT_CALIBRATING_POVS
  919. case JCS_POV_MOVEUP:
  920. lpDIJoyState->rgdwPOV[0] = JOY_POVFORWARD;
  921. DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
  922. nMsgID = IDS_JOYCALPOV_MOVE;
  923. nTitleID = IDS_POV_CALIBRATION;
  924. break;
  925. case JCS_POV_MOVERIGHT:
  926. lpDIJoyState->rgdwPOV[0] = JOY_POVRIGHT;
  927. DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
  928. nMsgID = IDS_JOYCALPOV_MOVE;
  929. nTitleID = IDS_POV_CALIBRATION;
  930. break;
  931. case JCS_POV_MOVEDOWN:
  932. lpDIJoyState->rgdwPOV[0] = JOY_POVBACKWARD;
  933. DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
  934. nMsgID = IDS_JOYCALPOV_MOVE;
  935. nTitleID = IDS_POV_CALIBRATION;
  936. break;
  937. case JCS_POV_MOVELEFT:
  938. lpDIJoyState->rgdwPOV[0] = JOY_POVLEFT;
  939. DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
  940. nMsgID = IDS_JOYCALPOV_MOVE;
  941. nTitleID = IDS_POV_CALIBRATION;
  942. break;
  943. #endif //WE_SUPPORT_CALIBRATING_POVS
  944. case JCS_FINI:
  945. nMsgID = IDS_JOYCAL_DONE;
  946. nTitleID = IDS_CALIBRATION_FINI;
  947. break;
  948. default:
  949. #ifdef _DEBUG
  950. OutputDebugString(TEXT("GCDEF.DLL: CAL.CPP: CalStateChange: nCalState doesn't match any known Calibration States!\n"));
  951. #endif
  952. return;
  953. } // END OF SWITCH
  954. // load and set the text
  955. LPTSTR lptszMsg = new TCHAR[MAX_STR_LEN];
  956. DWORD nStrLen = MAX_STR_LEN - 1;
  957. // see if there is any OEM text specified
  958. if( pJoyConfig->hwc.dwUsageSettings & JOY_US_ISOEM ) {
  959. GetOEMCtrlString(lptszMsg, &nStrLen);
  960. } else {
  961. nStrLen = 0;
  962. }
  963. // nStrLen will be non-zero if GetOEMCtrlString is successfull!
  964. if( nStrLen == 0 ) {
  965. VERIFY(LoadString(ghInst, nMsgID, lptszMsg, MAX_STR_LEN));
  966. switch( nMsgID ) {
  967. case IDS_JOYCAL_MOVE:
  968. {
  969. LPTSTR lptszBuff = new TCHAR[STR_LEN_32];
  970. LPTSTR lpDup = StrDup(lptszMsg);
  971. if( lptszBuff && lpDup ) {
  972. ::SendDlgItemMessage(hDlg, IDC_JOYLIST2_LABEL, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)lptszBuff);
  973. wsprintf(lptszMsg, lpDup, lptszBuff);
  974. LocalFree(lpDup);
  975. delete []lptszBuff;
  976. }
  977. }
  978. break;
  979. }
  980. }
  981. // Send the smaller message
  982. ::SendDlgItemMessage(hDlg, IDC_WIZARD_MSG, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)lptszMsg);
  983. VERIFY(LoadString(ghInst, nTitleID, lptszMsg, MAX_STR_LEN));
  984. // Send the Bold Header message
  985. ::SendDlgItemMessage(hDlg, IDC_WIZARD_MSG_HDR, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)lptszMsg);
  986. if( lptszMsg ) {
  987. delete[] (lptszMsg);
  988. }
  989. // Take care of the RawData dialog items!
  990. switch( nCalState ) {
  991. // Don't do the raw data thing if you don't have the checkbox!
  992. case JCS_XY_CENTER1:
  993. case JCS_XY_CENTER2:
  994. case JCS_FINI:
  995. break;
  996. // Do the percent for the pages that need it!
  997. case JCS_Z_MOVE:
  998. case JCS_R_MOVE:
  999. case JCS_U_MOVE:
  1000. case JCS_V_MOVE:
  1001. case JCS_S0_MOVE:
  1002. case JCS_S1_MOVE:
  1003. if( bGradient ) {
  1004. if( pGradient ) {
  1005. pGradient->ShowPercent(bShowRawData);
  1006. }
  1007. }
  1008. // Missing break intentional!!!
  1009. default:
  1010. RawDataSelected(hDlg, bShowRawData);
  1011. ::SendDlgItemMessage(hDlg, IDC_RAWDATA, BM_SETCHECK, (bShowRawData) ? BST_CHECKED : BST_UNCHECKED, 0);
  1012. break;
  1013. }
  1014. } // *** end of CalStateChange
  1015. //*******************************************************************************
  1016. //
  1017. // FUNCTION: CollectCalInfo( HWND hDlg, LPDIJOYSTATE pdiJoyState )
  1018. //
  1019. // PURPOSE: Procedure to Collect Calibration Data
  1020. //
  1021. // COMMENTS:
  1022. //
  1023. //*******************************************************************************
  1024. BOOL CollectCalInfo( HWND hDlg, LPDIJOYSTATE pdiJoyState )
  1025. {
  1026. TCHAR tsz[16];
  1027. switch( nCalState ) {
  1028. // remember XY center
  1029. case JCS_XY_CENTER1:
  1030. // store the initial centres!
  1031. pRanges->jpCenter.dwY = pdiJoyState->lY;
  1032. pRanges->jpCenter.dwX = pdiJoyState->lX;
  1033. // We Have an X/Y, so let's check for our Pens!
  1034. CreatePens();
  1035. break;
  1036. // remember max/min XY values
  1037. case JCS_XY_MOVE:
  1038. if( pdiJoyState->lX > pRanges->jpMax.dwX )
  1039. pRanges->jpMax.dwX = pdiJoyState->lX;
  1040. else if( pdiJoyState->lX < pRanges->jpMin.dwX )
  1041. pRanges->jpMin.dwX = pdiJoyState->lX;
  1042. if( pdiJoyState->lY > pRanges->jpMax.dwY )
  1043. pRanges->jpMax.dwY = pdiJoyState->lY;
  1044. else if( pdiJoyState->lY < pRanges->jpMin.dwY )
  1045. pRanges->jpMin.dwY = pdiJoyState->lY;
  1046. // if IDC_RAWXOUTPUT is visible, then so is IDC_RAWYOUTPUT...
  1047. // no bother to even ask.
  1048. if( bShowRawData ) {
  1049. static POINT ptOld = {DELTA,DELTA};
  1050. if( (ptOld.x != pdiJoyState->lX) || (ptOld.y != pdiJoyState->lY) ) {
  1051. myitoa(pdiJoyState->lX, &tsz[0]);
  1052. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1053. myitoa(pdiJoyState->lY, &tsz[0]);
  1054. ::SendDlgItemMessage(hDlg, IDC_RAWYOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1055. ptOld.x = pdiJoyState->lX;
  1056. ptOld.y = pdiJoyState->lY;
  1057. }
  1058. }
  1059. // Scale before send it to DoJoyMove!
  1060. {
  1061. RECT rc;
  1062. GetClientRect(GetDlgItem(hDlg, IDC_JOYLIST1), &rc);
  1063. // Casting to the UINT will change the sign!
  1064. UINT nRange = (UINT)(pRanges->jpMax.dwX - pRanges->jpMin.dwX);
  1065. float nScaledRange = (float)(rc.right-DELTA);
  1066. if( nRange )
  1067. nScaledRange /= (float)nRange;
  1068. // Scale X
  1069. pdiJoyState->lX = (long)((pdiJoyState->lX - pRanges->jpMin.dwX) * nScaledRange);
  1070. // Scale Y
  1071. if( nRange ) nScaledRange = (float)rc.bottom / (float)nRange;
  1072. pdiJoyState->lY = (long)((pdiJoyState->lY - pRanges->jpMin.dwY) * nScaledRange);
  1073. }
  1074. DoJoyMove( hDlg, (BYTE)HAS_X|HAS_Y );
  1075. break;
  1076. case JCS_XY_CENTER2:
  1077. // Average the Y
  1078. pRanges->jpCenter.dwY = (pRanges->jpCenter.dwY += pdiJoyState->lY)>>1;
  1079. //Average the X
  1080. pRanges->jpCenter.dwX = (pRanges->jpCenter.dwX += pdiJoyState->lX)>>1;
  1081. break;
  1082. // remember max/min Z value
  1083. case JCS_Z_MOVE:
  1084. // Set new Min's and Max's...
  1085. // Set a new Center whenever either is hit!
  1086. if( pdiJoyState->lZ > pRanges->jpMax.dwZ ) {
  1087. pRanges->jpMax.dwZ = pdiJoyState->lZ;
  1088. pRanges->jpCenter.dwZ = (pRanges->jpMax.dwZ+pRanges->jpMin.dwZ)>>1;
  1089. } else if( pdiJoyState->lZ < pRanges->jpMin.dwZ ) {
  1090. pRanges->jpMin.dwZ = pdiJoyState->lZ;
  1091. pRanges->jpCenter.dwZ = (pRanges->jpMax.dwZ+pRanges->jpMin.dwZ)>>1;
  1092. }
  1093. // Do the position status
  1094. // Update the text
  1095. if( bShowRawData ) {
  1096. myitoa(pdiJoyState->lZ, &tsz[0]);
  1097. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1098. }
  1099. if( bGradient )
  1100. pGradient->SetPos(pdiJoyState->lZ);
  1101. ::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lZ, 0L);
  1102. break;
  1103. // remember max/min Rx value
  1104. case JCS_R_MOVE:
  1105. // Set new Min's and Max's...
  1106. // Set a new Center whenever either is hit!
  1107. if( pdiJoyState->lRx > pRanges->jpMax.dwRx ) {
  1108. pRanges->jpMax.dwRx = pdiJoyState->lRx;
  1109. pRanges->jpCenter.dwRx = (pRanges->jpMax.dwRx+pRanges->jpMin.dwRx)>>1;
  1110. } else if( pdiJoyState->lRx < pRanges->jpMin.dwRx ) {
  1111. pRanges->jpMin.dwRx = pdiJoyState->lRx;
  1112. pRanges->jpCenter.dwRx = (pRanges->jpMax.dwRx+pRanges->jpMin.dwRx)>>1;
  1113. }
  1114. // Do the position status
  1115. // Update the text
  1116. if( bShowRawData ) {
  1117. myitoa(pdiJoyState->lRx, &tsz[0]);
  1118. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1119. }
  1120. if( bGradient )
  1121. pGradient->SetPos(pdiJoyState->lRx);
  1122. ::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lRx, 0L);
  1123. break;
  1124. // remember max/min Ry value
  1125. case JCS_U_MOVE:
  1126. // Set new Min's and Max's...
  1127. // Set a new Center whenever either is hit!
  1128. if( pdiJoyState->lRy > pRanges->jpMax.dwRy ) {
  1129. pRanges->jpMax.dwRy = pdiJoyState->lRy;
  1130. pRanges->jpCenter.dwRy = (pRanges->jpMax.dwRy+pRanges->jpMin.dwRy)>>1;
  1131. } else if( pdiJoyState->lRy < pRanges->jpMin.dwRy ) {
  1132. pRanges->jpMin.dwRy = pdiJoyState->lRy;
  1133. pRanges->jpCenter.dwRy = (pRanges->jpMax.dwRy+pRanges->jpMin.dwRy)>>1;
  1134. }
  1135. // Do the position status
  1136. if( bShowRawData ) {
  1137. myitoa(pdiJoyState->lRy, &tsz[0]);
  1138. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1139. }
  1140. if( bGradient )
  1141. pGradient->SetPos(pdiJoyState->lRy);
  1142. ::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lRy, 0L);
  1143. break;
  1144. // remember max/min Rz value
  1145. case JCS_V_MOVE:
  1146. // Set new Min's and Max's...
  1147. // Set a new Center whenever either is hit!
  1148. if( pdiJoyState->lRz > pRanges->jpMax.dwRz ) {
  1149. pRanges->jpMax.dwRz = pdiJoyState->lRz;
  1150. pRanges->jpCenter.dwRz = (pRanges->jpMax.dwRz+pRanges->jpMin.dwRz)>>1;
  1151. } else if( pdiJoyState->lRz < pRanges->jpMin.dwRz ) {
  1152. pRanges->jpMin.dwRz = pdiJoyState->lRz;
  1153. pRanges->jpCenter.dwRz = (pRanges->jpMax.dwRz+pRanges->jpMin.dwRz)>>1;
  1154. }
  1155. // Do the position status
  1156. if( bShowRawData ) {
  1157. myitoa(pdiJoyState->lRz, &tsz[0]);
  1158. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1159. }
  1160. if( bGradient )
  1161. pGradient->SetPos(pdiJoyState->lRz);
  1162. ::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lRz, 0L);
  1163. break;
  1164. // remember max/min S0 value
  1165. case JCS_S0_MOVE:
  1166. // Set new Min's and Max's...
  1167. // Set a new Center whenever either is hit!
  1168. if( pdiJoyState->rglSlider[0] > pRanges->jpMax.dwS0 ) {
  1169. pRanges->jpMax.dwS0 = pdiJoyState->rglSlider[0];
  1170. pRanges->jpCenter.dwS0 = (pRanges->jpMax.dwS0+pRanges->jpMin.dwS0)>>1;
  1171. } else if( pdiJoyState->rglSlider[0] < pRanges->jpMin.dwS0 ) {
  1172. pRanges->jpMin.dwS0 = pdiJoyState->rglSlider[0];
  1173. pRanges->jpCenter.dwS0 = (pRanges->jpMax.dwS0+pRanges->jpMin.dwS0)>>1;
  1174. }
  1175. // Do the position status
  1176. if( bShowRawData ) {
  1177. myitoa(pdiJoyState->rglSlider[0], &tsz[0]);
  1178. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1179. }
  1180. if( bGradient )
  1181. pGradient->SetPos(pdiJoyState->rglSlider[0]);
  1182. ::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->rglSlider[0], 0L);
  1183. break;
  1184. // remember max/min S1 value
  1185. case JCS_S1_MOVE:
  1186. // Set new Min's and Max's...
  1187. // Set a new Center whenever either is hit!
  1188. if( pdiJoyState->rglSlider[1] > pRanges->jpMax.dwS1 ) {
  1189. pRanges->jpMax.dwS1 = pdiJoyState->rglSlider[1];
  1190. pRanges->jpCenter.dwS1 = (pRanges->jpMax.dwS1+pRanges->jpMin.dwS1)>>1;
  1191. } else if( pdiJoyState->rglSlider[1] < pRanges->jpMin.dwS1 ) {
  1192. pRanges->jpMin.dwS1 = pdiJoyState->rglSlider[1];
  1193. pRanges->jpCenter.dwS1 = (pRanges->jpMax.dwS1+pRanges->jpMin.dwS1)>>1;
  1194. }
  1195. // Do the position status
  1196. if( bShowRawData ) {
  1197. myitoa(pdiJoyState->rglSlider[1], &tsz[0]);
  1198. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1199. }
  1200. if( bGradient )
  1201. pGradient->SetPos(pdiJoyState->rglSlider[1]);
  1202. ::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->rglSlider[1], 0L);
  1203. break;
  1204. case JCS_POV_MOVEUP:
  1205. case JCS_POV_MOVERIGHT:
  1206. case JCS_POV_MOVEDOWN:
  1207. case JCS_POV_MOVELEFT:
  1208. // Do the position status
  1209. /*
  1210. if( bShowRawData ) {
  1211. myitoa(pdiJoyState->rgdwPOV[0], &tsz[0]);
  1212. ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
  1213. }
  1214. */
  1215. break;
  1216. }
  1217. return(TRUE);
  1218. } // CollectCalInfo
  1219. //*******************************************************************************
  1220. //
  1221. // FUNCTION: EnableXYWindows( HWND hDlg)
  1222. //
  1223. // PURPOSE: Enables X/Y Windows
  1224. //
  1225. // COMMENTS:
  1226. //
  1227. //*******************************************************************************
  1228. void EnableXYWindows( HWND hDlg )
  1229. {
  1230. ////// set up the XY window controls ///////
  1231. USHORT nCtrls[] = {IDC_RAWX, IDC_RAWY, IDC_RAWXOUTPUT, IDC_RAWYOUTPUT};
  1232. BYTE nNumCtrls = sizeof(nCtrls)/sizeof(short);
  1233. do {
  1234. SetWindowPos( GetDlgItem( hDlg, nCtrls[--nNumCtrls]), NULL, NULL, NULL, NULL, NULL,
  1235. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW);
  1236. } while( nNumCtrls );
  1237. #ifdef DEADZONE
  1238. {
  1239. USHORT nDZCtrls[] = {IDC_X_DEADZONE_SPIN, IDC_Y_DEADZONE_SPIN, IDC_X_SATURATION_SPIN,
  1240. IDC_Y_SATURATION_SPIN, IDC_DEADZONE_TITLE, IDC_X_DEADZONE,
  1241. IDC_Y_DEADZONE, IDC_X_AXIS_LABEL, IDC_X_AXIS_LABEL,
  1242. IDC_Y_AXIS_LABEL, IDC_SATURATION_TITLE,IDC_X_SATURATION,
  1243. IDC_Y_SATURATION, IDC_X_AXIS_LABEL_SATURATION, IDC_Y_AXIS_LABEL_SATURATION};
  1244. nNumCtrls = sizeof(nCtrls)/sizeof(short);
  1245. do {
  1246. // Use SetWindowPos here because internally, ShowWindow calls it!
  1247. SetWindowPos( GetDlgItem( hDlg, nCtrls[nNumCtrls]), NULL, NULL, NULL, NULL, NULL,
  1248. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((nCalState == JCS_DEADZONE) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  1249. } while( nNumCtrls-- );
  1250. }
  1251. #endif // DEADZONE
  1252. nCtrls[0] = IDC_JOYLIST1;
  1253. nCtrls[1] = IDC_JOYLIST1_LABEL;
  1254. nCtrls[2] = IDC_RAWDATA;
  1255. nNumCtrls = 2;
  1256. do {
  1257. // Use SetWindowPos here because internally, ShowWindow calls it!
  1258. SetWindowPos( GetDlgItem( hDlg, nCtrls[nNumCtrls]), NULL, NULL, NULL, NULL, NULL,
  1259. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | (((nCalState == JCS_XY_MOVE)
  1260. #ifdef DEADZONE
  1261. || (nCalState == JCS_DEADZONE)
  1262. #endif
  1263. ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  1264. } while( nNumCtrls-- );
  1265. HWND hwndXY = GetDlgItem(hDlg, IDC_JOYLIST1);
  1266. // Disable RTL flag
  1267. SetWindowLongPtr( hwndXY, GWL_EXSTYLE, GetWindowLongPtr(hwndXY,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL );
  1268. }
  1269. //*******************************************************************************
  1270. //
  1271. // FUNCTION: GetOEMCtrlString(LPTSTR lptStr, BYTE *nStrLen)
  1272. //
  1273. // PURPOSE: Gets string and string length for OEM controls
  1274. //
  1275. // COMMENTS:
  1276. //
  1277. //*******************************************************************************
  1278. BOOL GetOEMCtrlString(LPTSTR lptStr, LPDWORD nStrLen)
  1279. {
  1280. // there's no REGSTR_VAL_JOYOEM for the sliders so return false and take the defaults
  1281. switch( nCalState ) {
  1282. case JCS_S0_MOVE:
  1283. case JCS_S1_MOVE:
  1284. *nStrLen = 0;
  1285. return(FALSE);
  1286. }
  1287. // Get the DIJOYCONFIG interface pointer!
  1288. LPDIRECTINPUTJOYCONFIG pdiJoyConfig;
  1289. pdiCpl->GetJoyConfig(&pdiJoyConfig);
  1290. BOOL bRet = FALSE;
  1291. if( SUCCEEDED(pdiJoyConfig->Acquire()) ) {
  1292. HKEY hKey;
  1293. // Open the TypeKey
  1294. if( SUCCEEDED(pdiJoyConfig->OpenTypeKey( lpwszTypeName, KEY_ALL_ACCESS, &hKey)) ) {
  1295. // registry strings for calibration messages
  1296. static LPCTSTR pszOEMCalRegStrs[] = {
  1297. REGSTR_VAL_JOYOEMCAL1, REGSTR_VAL_JOYOEMCAL2,
  1298. REGSTR_VAL_JOYOEMCAL3, REGSTR_VAL_JOYOEMCAL4,
  1299. REGSTR_VAL_JOYOEMCAL5, REGSTR_VAL_JOYOEMCAL6,
  1300. REGSTR_VAL_JOYOEMCAL7,
  1301. #ifdef WE_SUPPORT_CALIBRATING_POVS
  1302. REGSTR_VAL_JOYOEMCAL8, REGSTR_VAL_JOYOEMCAL9,
  1303. REGSTR_VAL_JOYOEMCAL10,REGSTR_VAL_JOYOEMCAL11,
  1304. #endif // WE_SUPPORT_CALIBRATING_POVS
  1305. REGSTR_VAL_JOYOEMCAL12
  1306. };
  1307. if( nCalState < (sizeof(pszOEMCalRegStrs)/sizeof(pszOEMCalRegStrs[0])) )
  1308. {
  1309. DWORD dwType = REG_SZ;
  1310. // the -2 is because of JCS_S0_MOVE and JCS_S1_MOVE!
  1311. if( RegQueryValueEx( hKey, pszOEMCalRegStrs[(nCalState == JCS_FINI) ? nCalState-2 : nCalState], NULL, &dwType, (CONST LPBYTE)lptStr, nStrLen ) == ERROR_SUCCESS )
  1312. bRet = TRUE;
  1313. else
  1314. *nStrLen = 0;
  1315. }
  1316. else
  1317. {
  1318. *nStrLen = 0;
  1319. }
  1320. RegCloseKey(hKey);
  1321. } else
  1322. {
  1323. *nStrLen = 0;
  1324. #ifdef _DEBUG
  1325. OutputDebugString(TEXT("Test.cpp: GetOEMCtrlString: OpenTypeKey FAILED!\n"));
  1326. #endif
  1327. }
  1328. pdiJoyConfig->Unacquire();
  1329. }
  1330. return(bRet);
  1331. } // *** end of GetOEMCtrlString
  1332. #ifdef WE_SUPPORT_CALIBRATING_POVS
  1333. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  1334. //
  1335. // SetDefaultButton( HWND hwdb )
  1336. //
  1337. //////////////////////////////////////////////////////////////////////////////////////////////////////
  1338. void SetDefaultButton( HWND hDlg, HWND hCtrl )
  1339. {
  1340. // make the specified button the default
  1341. DWORD style = GetWindowLong( hCtrl, GWL_STYLE );
  1342. style &= ~(BS_PUSHBUTTON|BS_DEFPUSHBUTTON);
  1343. style |= BS_DEFPUSHBUTTON;
  1344. SetWindowLong( hCtrl, GWL_STYLE, style );
  1345. } // SetDefaultButton
  1346. #endif //WE_SUPPORT_CALIBRATING_POVS
  1347. //===========================================================================
  1348. // SetCalibrationMode ( BOOL bSet )
  1349. //
  1350. // Sets DirectInput Calibration mode (RAW/COOKED)
  1351. //
  1352. // Parameters:
  1353. // BOOL bSet - TRUE for RAW, FALSE for COOKED
  1354. //
  1355. // Returns: return value from SetProperty (standard COM stuff)
  1356. //
  1357. //===========================================================================
  1358. HRESULT SetCalibrationMode( BOOL bSet)
  1359. {
  1360. LPDIPROPDWORD pDIPropDword = (LPDIPROPDWORD)_alloca(sizeof(DIPROPDWORD));
  1361. assert (pDIPropDword);
  1362. pDIPropDword->diph.dwSize = sizeof(DIPROPDWORD);
  1363. pDIPropDword->diph.dwHeaderSize = sizeof(DIPROPHEADER);
  1364. pDIPropDword->diph.dwObj = 0x0;
  1365. pDIPropDword->diph.dwHow = DIPH_DEVICE;
  1366. pDIPropDword->dwData = bSet ? DIPROPCALIBRATIONMODE_RAW : DIPROPCALIBRATIONMODE_COOKED;
  1367. // Set the mode to Raw Data during Calibration!
  1368. HRESULT hr = pdiDevice2->SetProperty(DIPROP_CALIBRATIONMODE, &pDIPropDword->diph);
  1369. #ifdef _DEBUG
  1370. if( FAILED(hr) ) {
  1371. OutputDebugString(TEXT("GCDEF.DLL: CAL.CPP: SetCalibrationMode: SetProperty Failed with a return of "));
  1372. switch( hr ) {
  1373. case DI_PROPNOEFFECT:
  1374. OutputDebugString(TEXT("DI_PROPNOEFFECT\n"));
  1375. break;
  1376. case DIERR_INVALIDPARAM:
  1377. OutputDebugString(TEXT("DIERR_INVALIDPARAM\n"));
  1378. break;
  1379. case DIERR_OBJECTNOTFOUND:
  1380. OutputDebugString(TEXT("DIERR_OBJECTNOTFOUND\n"));
  1381. break;
  1382. case DIERR_UNSUPPORTED:
  1383. OutputDebugString(TEXT("DIERR_UNSUPPORTED\n"));
  1384. break;
  1385. default:
  1386. {
  1387. TCHAR szTmp[32];
  1388. wsprintf(szTmp, TEXT("%x"), hr);
  1389. OutputDebugString(szTmp);
  1390. }
  1391. }
  1392. }
  1393. #endif
  1394. return(hr);
  1395. }
  1396. //===========================================================================
  1397. // UpdateXYLabel(HWND hWnd)
  1398. //
  1399. // Displays the number and names of the device Axis in the provided dialog.
  1400. // This EXPECTS that the controls are not visible by default!
  1401. //
  1402. // Parameters:
  1403. // HWND hDlg - Dialog handle
  1404. //
  1405. // Returns:
  1406. //
  1407. //===========================================================================
  1408. void UpdateXYLabel(const HWND hDlg)
  1409. {
  1410. BYTE nAxisFlags = pdiCpl->GetStateFlags()->nAxis;
  1411. // X and Y use the same control so they are isolated!
  1412. if( (nAxisFlags & HAS_X) || (nAxisFlags & HAS_Y) ) {
  1413. LPDIDEVICEOBJECTINSTANCE_DX3 pDevObjInst = new (DIDEVICEOBJECTINSTANCE_DX3);
  1414. assert (pDevObjInst);
  1415. ZeroMemory(pDevObjInst, sizeof(DIDEVICEOBJECTINSTANCE_DX3));
  1416. pDevObjInst->dwSize = sizeof(DIDEVICEOBJECTINSTANCE_DX3);
  1417. LPTSTR ptszBuff = (LPTSTR) _alloca(sizeof(TCHAR[STR_LEN_32]));
  1418. assert (ptszBuff);
  1419. ZeroMemory(ptszBuff, sizeof(TCHAR[STR_LEN_32]));
  1420. // Set it's text
  1421. if( nAxisFlags & HAS_X ) {
  1422. if( FAILED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, DIJOFS_X, DIPH_BYOFFSET)) ) {
  1423. #ifdef _DEBUG
  1424. OutputDebugString(TEXT("GCDEF.DLL: DisplayAvailableAxis: GetObjectInfo Failed to find DIJOFS_X!\n"));
  1425. #endif
  1426. }
  1427. int nLen=lstrlen(pDevObjInst->tszName)+1;
  1428. if(nLen>STR_LEN_32)
  1429. nLen=STR_LEN_32;
  1430. StrCpyN(ptszBuff, pDevObjInst->tszName, nLen);
  1431. // Set the Output Label!
  1432. ::SendDlgItemMessage(hDlg, IDC_RAWX, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1433. #ifdef DEADZONE
  1434. // Set text labels!
  1435. ::SendDlgItemMessage(hDlg, IDC_X_AXIS_LABEL_DEADZONE, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1436. ::SendDlgItemMessage(hDlg, IDC_X_AXIS_LABEL_SATURATION, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1437. #endif //DEADZONE
  1438. // Remove the HAS_X flag
  1439. nAxisFlags &= ~HAS_X;
  1440. }
  1441. if( nAxisFlags & HAS_Y ) {
  1442. if( FAILED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, DIJOFS_Y, DIPH_BYOFFSET)) ) {
  1443. #ifdef _DEBUG
  1444. OutputDebugString(TEXT("GCDEF.DLL: DisplayAvailableAxis: GetObjectInfo Failed to find DIJOFS_Y!\n"));
  1445. #endif
  1446. }
  1447. #ifdef DEADZONE
  1448. // Set text labels!
  1449. ::SendDlgItemMessage(hDlg, IDC_Y_AXIS_LABEL_DEADZONE, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1450. ::SendDlgItemMessage(hDlg, IDC_Y_AXIS_LABEL_SATURATION, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1451. #endif //DEADZONE
  1452. // just in case it has Y but not X
  1453. if( ptszBuff && lstrlen(ptszBuff) ) { // Whisltler PREFIX 45092
  1454. int nLen=STR_LEN_32-lstrlen(ptszBuff);
  1455. StrNCat(ptszBuff, TEXT(" / "), nLen);
  1456. }
  1457. int nLen=STR_LEN_32-lstrlen(ptszBuff);
  1458. StrNCat(ptszBuff, pDevObjInst->tszName, nLen);
  1459. // Set the Output Label!
  1460. ::SendDlgItemMessage(hDlg, IDC_RAWY, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1461. // Remove the HAS_Y flag
  1462. nAxisFlags &= ~HAS_Y;
  1463. }
  1464. if( pDevObjInst )
  1465. delete (pDevObjInst);
  1466. ::SendDlgItemMessage(hDlg, IDC_JOYLIST1_LABEL, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)ptszBuff);
  1467. // if (ptszBuff)
  1468. // delete[] (ptszBuff);
  1469. }
  1470. } //*** end of UpdateXYLabel
  1471. //*******************************************************************************
  1472. //
  1473. // FUNCTION: UpdateProgressLabel(HWND hDlg)
  1474. //
  1475. // PURPOSE: Updates Axis specific labels based on the current Calibration stage.
  1476. //
  1477. // COMMENTS:
  1478. //
  1479. //*******************************************************************************
  1480. BOOL UpdateProgressLabel(const HWND hDlg)
  1481. {
  1482. // Array of supported axis!
  1483. const DWORD dwOffsetArray[] = {DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1)};
  1484. BOOL bRet = FALSE;
  1485. LPDIDEVICEOBJECTINSTANCE_DX3 pDevObjInst = (LPDIDEVICEOBJECTINSTANCE_DX3)_alloca(sizeof(DIDEVICEOBJECTINSTANCE_DX3));
  1486. assert (pDevObjInst);
  1487. ZeroMemory(pDevObjInst, sizeof(DIDEVICEOBJECTINSTANCE_DX3));
  1488. pDevObjInst->dwSize = sizeof(DIDEVICEOBJECTINSTANCE_DX3);
  1489. // Get it's text
  1490. if( SUCCEEDED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, dwOffsetArray[nCalState-3], DIPH_BYOFFSET)) ) {
  1491. // Set it's text
  1492. ::SendDlgItemMessage(hDlg, IDC_JOYLIST2_LABEL, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1493. ::SendDlgItemMessage(hDlg, IDC_RAWX, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
  1494. bRet = TRUE;
  1495. }
  1496. return(bRet);
  1497. }
  1498. ///////////////////////////////////////////////////////////////////////////////
  1499. // FUNCTION: myitoa(long n, LPTSTR lpStr)
  1500. //
  1501. // PARAMETERS: BYTE n - Number to be translated
  1502. // LPTSTR lpStr - Buffer to recieve translated value
  1503. //
  1504. // PURPOSE: Convert BYTE values < 20 to strings.
  1505. ///////////////////////////////////////////////////////////////////////////////
  1506. void myitoa(long n, LPTSTR lpStr)
  1507. {
  1508. long sign = n;
  1509. if( n < 0 )
  1510. n = - n;
  1511. LPTSTR pchStart = lpStr;
  1512. do {
  1513. *lpStr++ = (TCHAR)(n % 10 + '0');
  1514. } while( (n /= 10) > 0 );
  1515. if( sign < 0 )
  1516. *lpStr++ = '-';
  1517. *lpStr = '\0';
  1518. reverse(pchStart);
  1519. }
  1520. void reverse(LPTSTR string)
  1521. {
  1522. TCHAR c;
  1523. short i, j;
  1524. for( i = 0, j = lstrlen(string) - 1; i < j; i++, j-- ) {
  1525. c = string[j];
  1526. string[j] = string[i];
  1527. string[i] = c;
  1528. }
  1529. }
  1530. //*******************************************************************************
  1531. //
  1532. // FUNCTION: RawDataSelected( HWND hWnd, BOOL bEnable )
  1533. //
  1534. // PURPOSE: Shows/Hides Raw data associated windows.
  1535. //
  1536. // COMMENTS:
  1537. //
  1538. //*******************************************************************************
  1539. void RawDataSelected( const HWND hWnd, BOOL bEnable )
  1540. {
  1541. const USHORT nCtrlArray[] = {IDC_RAWX, IDC_RAWY, IDC_RAWXOUTPUT, IDC_RAWYOUTPUT};
  1542. BYTE nCtrls = sizeof(nCtrlArray)/sizeof(short);
  1543. do {
  1544. SetWindowPos( GetDlgItem( hWnd, nCtrlArray[--nCtrls]), NULL, NULL, NULL, NULL, NULL,
  1545. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((bEnable) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  1546. } while( nCtrls );
  1547. }
  1548. //*******************************************************************************
  1549. //
  1550. // FUNCTION: TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  1551. //
  1552. // PURPOSE: TimerProc for the Calibration Wizard.
  1553. // Searches for button presses, then moves to next stage/finish.
  1554. //
  1555. // COMMENTS:
  1556. //
  1557. //*******************************************************************************
  1558. VOID CALLBACK TimerProc(const HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  1559. {
  1560. if( SUCCEEDED(DIUtilPollJoystick(pdiDevice2, lpDIJoyState)) ) {
  1561. CollectCalInfo(hWnd, lpDIJoyState);
  1562. // Don't bother checking for key presses if the user is in the POV stage!
  1563. if( nCalState <= JCS_S1_MOVE ) {
  1564. // Catch button presses...
  1565. static BYTE nDownButton = 0xff;
  1566. BYTE i = 0;
  1567. int nButtons = pdiCpl->GetStateFlags()->nButtons;
  1568. // only attempt to check buttons we KNOW we have!!!
  1569. while( nButtons ) {
  1570. // check for a button press
  1571. if( lpDIJoyState->rgbButtons[i] & 0x80 ) {
  1572. if( nDownButton != 0xff )
  1573. break;
  1574. // Let the Next button handle the processing
  1575. ::PostMessage(GetParent(hWnd), PSM_PRESSBUTTON, (WPARAM)(int)(nCalState > JCS_S1_MOVE) ? PSBTN_FINISH : PSBTN_NEXT, 0);
  1576. // Store the button that went down!
  1577. nDownButton = i;
  1578. // mission accomplished!
  1579. return;
  1580. }
  1581. // reset the nDownButton flag
  1582. else if( i == nDownButton )
  1583. nDownButton = 0xff;
  1584. nButtons &= ~(HAS_BUTTON1<<i++);
  1585. }
  1586. // end of catch for button presses!
  1587. }
  1588. }
  1589. }
  1590. // This is because PSN_WIZFINISH is Documented to be sent to every page dlg proc on exit... but it doesn't!
  1591. static void WizFinish(const HWND hWnd)
  1592. {
  1593. HRESULT hres;
  1594. KillTimer(hWnd, ID_CAL_TIMER);
  1595. // assign the new ranges
  1596. SetMyRanges(pdiDevice2, pRanges, pdiCpl->GetStateFlags()->nAxis);
  1597. LPDIRECTINPUTJOYCONFIG pdiJoyConfig;
  1598. pdiCpl->GetJoyConfig(&pdiJoyConfig);
  1599. if( pdiCpl->GetStateFlags()->nPOVs ) {
  1600. pdiDevice2->Unacquire();
  1601. SetCalibrationMode( FALSE );
  1602. pdiJoyConfig->Acquire();
  1603. CopyRange( &pJoyConfig->hwc.hwv.jrvHardware, pRanges );
  1604. memcpy( pJoyConfig->hwc.hwv.dwPOVValues, pRanges->dwPOV, sizeof(DWORD)*4 );
  1605. hres = pdiJoyConfig->SetConfig(pdiCpl->GetID(), (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE);
  1606. #ifdef WE_SUPPORT_CALIBRATING_POVS
  1607. if( SUCCEEDED(hres) ) {
  1608. CalibratePolledPOV( &pJoyConfig->hwc );
  1609. // set POV positions!
  1610. if( bPolledPOV ) {
  1611. SetMyPOVRanges(pdiDevice2);
  1612. }
  1613. }
  1614. #endif
  1615. }
  1616. pdiJoyConfig->SendNotify();
  1617. pdiDevice2->Unacquire();
  1618. }