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.

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