|
|
//===========================================================================
// CAL.CPP... Would be CALIBRATE.CPP, but that's not 8.3 compliant :(
//
// Functions:
//
// CalInitProc
// CalXYProc
// CalSliderProc
// CalPovProc
// CalStateChange
// CollectCalInfo
// EnableXYWindows
// GetOEMCtrlString
//
//===========================================================================
// This is necessary or PSH_WIZARD_LITE will not be defined!
#if (_WIN32_IE < 0x0500)
#undef _WIN32_IE
#define _WIN32_IE 0x0500
#endif
// This is necessary for UnregisterDeviceNotification!
#if (WINVER < 0x0500)
#undef WINVER
#define WINVER 0x0500
#endif
// Uncomment if we decide to calibrate the POV!
#define WE_SUPPORT_CALIBRATING_POVS 1
#include "cplsvr1.h"
//#include <windowsx.h>
#include <mmsystem.h>
#include <malloc.h>
#include "cplsvr1.h"
#ifdef _UNICODE
#include <winuser.h> // For RegisterDeviceNotification stuff!
#include <dbt.h> // for DBT_ defines!!!
#endif // _UNICODE
// remove to remove support for calibration of deadzones!
//#define DEADZONE 1
#include "resource.h"
#include "cal.h" // Data to be shared with other modules
#include "calocal.h" // Local Data to this module
#include "dicputil.h" // for OnContextMenu and OnHelp
#include "pov.h" // for SetDegrees()
#include <prsht.h> // includes the property sheet functionality
#include <shlwapi.h> // for the Str... functions!
#include <regstr.h> // for pre-defined Registry string names
#include "Gradient.h" // for Gradient Fill Slider!
// Local function prototypes!
static void UpdateXYLabel (const HWND hDlg); static BOOL UpdateProgressLabel (const HWND hDlg); // myitoa prototype is in cplsvr1.h
static void reverse (LPTSTR string); static void RawDataSelected (const HWND hWnd, BOOL bEnable); static void WizFinish (const HWND hWnd);
// Calibration procedures!
LRESULT CALLBACK CalInitProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK CalXYProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK CalSliderProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#ifdef WE_SUPPORT_CALIBRATING_POVS
LRESULT CALLBACK CalPovProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); #endif //WE_SUPPORT_CALIBRATING_POVS
VOID CALLBACK TimerProc (const HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
//static void EnableSliderWindows (const HWND hWnd, BOOL bEnable);
HWND ProgWndCal; // Handle to Progress Control Window
//DWORD dwUsage; // Usage flags for the device being calibrated!
char nCalState; // Flag state variable!
char nPrevCalState; LPMYJOYRANGE pRanges; // Ranges recieved by the Calibration!
BOOL bShowRawData; LPWSTR lpwszTypeName; // Set in WM_INIT, Used in GetOEMCtrlString
LPDIJOYCONFIG_DX5 pJoyConfig; // DIJC_REGHWCONFIGTYPE information about the device!
//
extern LPMYJOYRANGE lpCurrentRanges; extern LPDIJOYSTATE lpDIJoyState; // Defined in TEST.CPP
extern CDIGameCntrlPropSheet_X *pdiCpl; extern HINSTANCE ghInst;
HFONT hTitleFont;
static LPDIRECTINPUTDEVICE2 pdiDevice2; static CGradientProgressCtrl *pGradient; static BOOL bGradient;
//****************************************************************************
//
// FUNCTION: CreateWizard(HWND hwndOwner, LPARAM lParam)
//
// PURPOSE: Create the Wizard control.
//
// COMMENTS:
//
// This function creates the wizard property sheet.
//****************************************************************************
short CreateWizard(const HWND hwndOwner, LPARAM lParam) { #ifdef WE_SUPPORT_CALIBRATING_POVS
const BYTE nTempArray[] = {IDD_INITIAL, IDD_XY, IDD_SLIDER, IDD_POV }; const DLGPROC pDlgProc[] = {(DLGPROC)CalInitProc, (DLGPROC)CalXYProc, (DLGPROC)CalSliderProc, (DLGPROC)CalPovProc }; #else
const BYTE nTempArray[] = {IDD_INITIAL, IDD_XY, IDD_SLIDER }; const DLGPROC pDlgProc[] = {(DLGPROC)CalInitProc, (DLGPROC)CalXYProc, (DLGPROC)CalSliderProc }; #endif
HPROPSHEETPAGE *pPages = new (HPROPSHEETPAGE[sizeof(nTempArray)/sizeof(BYTE)]); if( !pPages ) { return 0; }
// Allocate and Zero the Page header memory
PROPSHEETHEADER *ppsh = new (PROPSHEETHEADER); if( !ppsh ) { delete[] (pPages); return 0; }
ZeroMemory(ppsh, sizeof(PROPSHEETHEADER));
ppsh->dwSize = sizeof(PROPSHEETHEADER); ppsh->dwFlags = PSH_WIZARD_LITE | PSH_NOAPPLYNOW | PSH_USEICONID; ppsh->hwndParent = hwndOwner; ppsh->pszIcon = MAKEINTRESOURCE(IDI_GCICON); ppsh->hInstance = ghInst; ppsh->phpage = pPages;
ppsh->pszbmWatermark = MAKEINTRESOURCE(IDB_CALHD);
PROPSHEETPAGE *ppsp = new (PROPSHEETPAGE); if( !ppsp ) { delete[] (pPages); delete (ppsh);
return 0; }
ZeroMemory(ppsp, sizeof(PROPSHEETPAGE));
ppsp->dwSize = sizeof(PROPSHEETPAGE); // ppsp->pszTitle = MAKEINTRESOURCE(nTabID);
ppsp->hInstance = ghInst; ppsp->lParam = lParam;
while( ppsh->nPages < (sizeof(nTempArray)/sizeof(BYTE)) ) { ppsp->pfnDlgProc = pDlgProc[ppsh->nPages]; ppsp->pszTemplate = MAKEINTRESOURCE(nTempArray[ppsh->nPages]);
ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(ppsp);
ppsh->nPages++; }
if( ppsp ) delete (ppsp);
short nRet = (short)PropertySheet(ppsh);
if( pPages ) delete[] (pPages);
// Clean up!
if( ppsh ) delete (ppsh);
return(nRet); }
//*******************************************************************************
//
// FUNCTION: CalInitProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
//
// PURPOSE: Procedure for Start-up screen
//
// COMMENTS: This function is responsible for display of text and bitmap.
// Since it is also the only page that is Guarenteed to be hit,
// it is also responsible for creating, deleteing, and storing
// everything for the calibration wizard.
//
//*******************************************************************************
LRESULT CALLBACK CalInitProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HFONT hBoldFont; static PVOID hNotifyDevNode;
switch( uMsg ) { case WM_LBUTTONDOWN: // Click Drag service for PropSheets!
PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam); break;
#ifdef _UNICODE
case WM_DEVICECHANGE: if( (UINT)wParam == DBT_DEVICEREMOVECOMPLETE ) ::PostMessage(GetParent(hWnd), WM_COMMAND, IDCANCEL, 0); break; #endif
// OnInit
case WM_INITDIALOG: // Init to FALSE to turn off Gradient fill!
bGradient = FALSE;
// According to knowlege base artical Q138505, this is the prescribed method of removing
// the context sensitive help '?' from the title bar.
{ LONG style = ::GetWindowLong(GetParent(hWnd), GWL_EXSTYLE); style &= ~WS_EX_CONTEXTHELP;
HWND hParent = GetParent(hWnd);
::SetWindowLong(hParent, GWL_EXSTYLE, style);
// Set up the Device Notification
#ifdef _UNICODE
RegisterForDevChange(hWnd, &hNotifyDevNode); #endif
HDC myDC = GetDC(hWnd); if( myDC ) { // Prefix Whistler 45095
hTitleFont = CreateFont(-MulDiv(8, GetDeviceCaps(myDC, LOGPIXELSY), 72), 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("MS Shell Dlg"));
// Do the Create font thing...
hBoldFont = CreateFont(-MulDiv(15, GetDeviceCaps(myDC, LOGPIXELSY), 72), 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH | FF_ROMAN, TEXT("MS Shell Dlg"));
ReleaseDC(hWnd, myDC); } if( hBoldFont ) ::SendDlgItemMessage(hWnd, IDC_INIT_TITLE, WM_SETFONT, (WPARAM)hBoldFont, TRUE);
CenterDialog(hWnd);
::PostMessage(hParent, PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT);
bShowRawData = FALSE;
// Allocate the memory for the ranges!
pRanges = new MYJOYRANGE; assert(pRanges);
// Set Everything to
ZeroMemory(pRanges, sizeof(MYJOYRANGE));
// Get the "best guess" ranges...
CopyMemory(pRanges, lpCurrentRanges, sizeof(MYJOYRANGE));
pdiCpl->GetDevice(&pdiDevice2);
// Attempt to Set them... die if you can't!
SetMyRanges(pdiDevice2, pRanges, pdiCpl->GetStateFlags()->nAxis);
if( FAILED(GetLastError()) ) { Error(hWnd, (short)IDS_USER_MODE_TITLE, (short)IDS_USER_MODE); PostMessage(GetParent(hWnd), WM_SYSCOMMAND, SC_CLOSE, 0L); }
pJoyConfig = new(DIJOYCONFIG_DX5); assert (pJoyConfig);
pJoyConfig->dwSize = sizeof (DIJOYCONFIG_DX5);
LPDIRECTINPUTJOYCONFIG pdiJoyConfig; pdiCpl->GetJoyConfig(&pdiJoyConfig);
HRESULT hres;
// Retrieve and store Hardware Configuration about the device!
hres = pdiJoyConfig->GetConfig(pdiCpl->GetID(), (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE | DIJC_GUIDINSTANCE);
if( SUCCEEDED(hres) ) { bPolledPOV = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_HASPOV) && (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL); CalibratePolledPOV( &pJoyConfig->hwc ); }
} break;
// Change the background of all Static text fields to WHITE
case WM_CTLCOLORSTATIC: return(LRESULT)GetStockObject(WHITE_BRUSH);
case WM_DESTROY: if( pJoyConfig ) delete (pJoyConfig);
if( lpwszTypeName ) LocalFree(lpwszTypeName);
pdiDevice2->Unacquire(); SetCalibrationMode( FALSE );
if( hTitleFont ) DeleteObject((HGDIOBJ)hTitleFont);
if( hBoldFont ) DeleteObject((HGDIOBJ)hBoldFont);
// if you call this function you will hang up the system for 30 seconds or more!!!
#ifdef _UNICODE
if( hNotifyDevNode ) UnregisterDeviceNotification(hNotifyDevNode); #endif // _UNICODE
break; } return(DefWindowProc(hWnd, uMsg, wParam, lParam)); }
//*******************************************************************************
//
// FUNCTION: CalXYProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
//
// PURPOSE: Procedure for first three stages of calibration
//
// COMMENTS: This function is responsible for capture of X/Y and Center values!
//
//*******************************************************************************
LRESULT CALLBACK CalXYProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_LBUTTONDOWN: // Click Drag service for PropSheets!
PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam); break;
// OnInit
case WM_INITDIALOG: { // set up the local globals
nCalState = JCS_XY_CENTER1; nPrevCalState = JCS_INIT;
// Get the JoyConfig Interface Pointer!
LPDIRECTINPUTJOYCONFIG pdiJoyConfig; pdiCpl->GetJoyConfig(&pdiJoyConfig);
if( SUCCEEDED(pdiJoyConfig->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND)) ) { // Set the font for the
::SendDlgItemMessage(hWnd, IDC_WIZARD_MSG_HDR, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
lpwszTypeName = StrDupW(pJoyConfig->wszType);
// This sets up the Windows and the global ProgWndCal!
UpdateXYLabel(hWnd);
// Set up for first round
CalStateChange( hWnd, (BYTE)pJoyConfig->hwc.hws.dwFlags );
VERIFY(SUCCEEDED(SetCalibrationMode(TRUE))); VERIFY(FAILED(pdiDevice2->Acquire())); } } break;
// Change the background of all Static text fields to WHITE
case WM_CTLCOLORSTATIC: // We only want to paint the background for the items in the top white rectangle!
switch( GetDlgCtrlID((HWND)lParam) ) { case IDC_WIZARD_MSG: case IDC_HEADERFRAME: case IDC_WIZARD_MSG_HDR: return(LRESULT)GetStockObject(WHITE_BRUSH); } return(FALSE);
// OnNotify
case WM_NOTIFY: switch( ((NMHDR FAR *) lParam)->code ) { case PSN_KILLACTIVE: KillTimer(hWnd, ID_CAL_TIMER); break;
case PSN_RESET: // reset to the original values
KillTimer(hWnd, ID_CAL_TIMER); break;
case PSN_SETACTIVE: SetTimer( hWnd, ID_CAL_TIMER, CALIBRATION_INTERVAL, (TIMERPROC)TimerProc);
// Sorry, you can't go back to the first page...
if( nCalState > JCS_XY_CENTER1 ) ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT | PSWIZB_BACK); else ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT); break;
case PSN_WIZBACK: // Determine what the next calibration stage is!
// Look out... we're backing up!
if( nCalState == nPrevCalState ) nPrevCalState--;
nCalState = nPrevCalState;
CalStateChange(hWnd, (BYTE)pJoyConfig->hwc.hws.dwFlags);
// No more backing up!
if( nCalState == JCS_XY_CENTER1 ) ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT);
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_XY_CENTER1) ? IDD_INITIAL : -1); return(nCalState < JCS_XY_CENTER1) ? IDD_INITIAL : -1;
case PSN_WIZNEXT: nPrevCalState = nCalState;
::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT | PSWIZB_BACK);
#if 0
// Determine what the next calibration stage is!
#ifndef DEADZONE
//while ((!(pdiCpl->GetStateFlags()->nAxis & 1<<nCalState++)) && (nCalState < JCS_FINI));
nCalState++; #else
nCalState++; #endif // DEADZONE
#endif
while( (!(pdiCpl->GetStateFlags()->nAxis & (1<<nCalState++) )) && (nCalState < JCS_FINI) );
if( nCalState > JCS_FINI ) ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH | PSWIZB_BACK); else if( nCalState < JCS_Z_MOVE ) CalStateChange( hWnd, (BYTE)pJoyConfig->hwc.hws.dwFlags );
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_Z_MOVE) ? -1 : IDD_SLIDER ); return(nCalState < JCS_Z_MOVE) ? -1 : IDD_SLIDER;
default: return(FALSE); } break;
// OnCommand
case WM_COMMAND: switch( LOWORD(wParam) ) { case IDC_RAWDATA: RawDataSelected(hWnd, bShowRawData = !bShowRawData); break; } break;
// OnDestroy
case WM_DESTROY: if( pRanges ) { delete (pRanges); pRanges = NULL; } break;
default: return(FALSE); } return(TRUE); }
//****************************************************************************
//
// FUNCTION: CalSliderProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
//
// PURPOSE: Procedure
//
// COMMENTS:
//
// This function creates the wizard property sheet.
//****************************************************************************
LRESULT CALLBACK CalSliderProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_LBUTTONDOWN: // Click Drag service for PropSheets!
PostMessage(GetParent(hWnd), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam); break;
case WM_INITDIALOG: // Set the Control font!
::SendDlgItemMessage(hWnd,IDC_WIZARD_MSG_HDR, WM_SETFONT, (WPARAM)hTitleFont, TRUE);
#ifdef DEADZONE
::SendDlgItemMessage(hWnd, IDC_DEADZONE_TITLE, WM_SETFONT, (WPARAM)hTitleFont, TRUE); ::SendDlgItemMessage(hWnd, IDC_SATURATION_TITLE, WM_SETFONT, (WPARAM)hTitleFont, TRUE); #endif //DEADZONE
// Setup the Progress bar!
ProgWndCal = GetDlgItem(hWnd, IDC_SLIDER);
// do the Gradient fill maddness!
{ HDC hDC = ::GetWindowDC(hWnd); if( hDC ) { bGradient = (BOOL)(GetDeviceCaps(hDC, NUMCOLORS) < 0);
if( bGradient ) { pGradient = new (CGradientProgressCtrl); pGradient->SubclassWindow(GetDlgItem(hWnd, IDC_SLIDER)); pGradient->SetDirection(HORIZONTAL); //pGradient->ShowPercent();
pGradient->SetStartColor(COLORREF(RGB(0,0,255))); pGradient->SetEndColor(COLORREF(RGB(0,0,0))); pGradient->SetBkColor(COLORREF(RGB(180,180,180))); } ::ReleaseDC(hWnd, hDC); } }
if( nCalState < JCS_FINI ) { // UpdateProgressLabel MUST be called Before CalStateChange!!!
UpdateProgressLabel(hWnd);
// If we're not using the gradient control, set the bar
// colour PBM_SETBARCOLOR is WM_USER+9... YES, it's undocumented...
if( !bGradient ) { ::PostMessage(ProgWndCal, WM_USER+9, 0, (LPARAM)ACTIVE_COLOR); } } else { ::PostMessage(GetParent(hWnd), PSM_PRESSBUTTON, (WPARAM)(int)PSBTN_NEXT, 0); } break;
case WM_DESTROY: if( bGradient ) if( pGradient ) delete (pGradient); break;
// OnCommand
case WM_COMMAND: switch( LOWORD(wParam) ) { case IDC_RAWDATA: RawDataSelected(hWnd, bShowRawData = !bShowRawData);
if( bGradient ) pGradient->ShowPercent(bShowRawData); break; } break;
// Change the background of all Static text fields to WHITE
case WM_CTLCOLORSTATIC: // We only want to paint the background for the items in the top white rectangle!
switch( GetDlgCtrlID((HWND)lParam) ) { case IDC_WIZARD_MSG: case IDC_HEADERFRAME: case IDC_WIZARD_MSG_HDR: return(LRESULT)GetStockObject(WHITE_BRUSH); } return(FALSE);
case WM_NOTIFY: switch( ((NMHDR FAR *) lParam)->code ) { case PSN_KILLACTIVE: KillTimer(hWnd, ID_CAL_TIMER); break;
case PSN_SETACTIVE: // Set up for first round
CalStateChange( hWnd, (BYTE)NULL ); SetTimer( hWnd, ID_CAL_TIMER, CALIBRATION_INTERVAL, (TIMERPROC)TimerProc); ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_NEXT | PSWIZB_BACK); break;
case PSN_WIZBACK: // Determine what the previous calibration stage is!
if( nCalState == nPrevCalState ) { DWORD dwAxis = pdiCpl->GetStateFlags()->nAxis; nPrevCalState --;
while( ( !(dwAxis & (1<<(--nPrevCalState)) ) ) && (nPrevCalState > JCS_XY_CENTER2) ){ ; } nPrevCalState ++; }
nCalState = nPrevCalState;
if( nCalState > JCS_XY_CENTER2 ) { // UpdateProgressLabel MUST be called Before CalStateChange!!!
UpdateProgressLabel(hWnd);
CalStateChange( hWnd, (BYTE)NULL ); }
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_Z_MOVE) ? IDD_XY : -1); return(nCalState < JCS_Z_MOVE) ? IDD_XY : -1;
case PSN_WIZNEXT: nPrevCalState = nCalState;
// Determine what the next calibration stage is!
while( (!(pdiCpl->GetStateFlags()->nAxis & 1<<nCalState++)) && (nCalState < JCS_FINI) );
if( nCalState <= JCS_S1_MOVE ) { UpdateProgressLabel(hWnd); #ifdef WE_SUPPORT_CALIBRATING_POVS
} else if( bPolledPOV ) { nCalState = JCS_S1_MOVE + 1; SetWindowLongPtr(hWnd, DWLP_MSGRESULT, IDD_POV );
return(IDD_POV); #endif
} else { // Remove the dialog items you no longer need...
//EnableSliderWindows(hWnd, FALSE);
const short nCtrlArray[] = {IDC_SLIDER, IDC_RAWDATA, IDC_RAWX, IDC_RAWXOUTPUT, IDC_JOYLIST2_LABEL}; BYTE nSize = sizeof(nCtrlArray)/sizeof(short);
do { SetWindowPos( GetDlgItem(hWnd, nCtrlArray[--nSize]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW ); } while( nSize );
::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH); }
CalStateChange( hWnd, (BYTE)NULL );
// we have no further pages, so don't allow them to go any further!
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, -1); return(-1);
case PSN_WIZFINISH: WizFinish(hWnd); break;
default: return(FALSE);
} break;
default: return(FALSE); } return(TRUE); }
//*******************************************************************************
//
// FUNCTION: EnableSliderWindows(HWND hWnd, BOOL bEnable)
//
// PURPOSE: Procedure to Show/Hide dialog controls during CalSliderProc's life
//
// COMMENTS:
//
//*******************************************************************************
/*
void EnableSliderWindows(const HWND hWnd, BOOL bEnable) { const short nCtrlArray[] = {IDC_SLIDER, IDC_RAWDATA, IDC_RAWX, IDC_RAWXOUTPUT, IDC_JOYLIST2_LABEL}; BYTE nSize = sizeof(nCtrlArray)/sizeof(short);
do { SetWindowPos( GetDlgItem(hWnd, nCtrlArray[--nSize]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | (bEnable ? SWP_SHOWWINDOW : SWP_HIDEWINDOW )); } while (nSize); } */ #ifdef WE_SUPPORT_CALIBRATING_POVS
//****************************************************************************
//
// FUNCTION: CalPovProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
//
// PURPOSE: Procedure
//
// COMMENTS:
//
// This function creates the wizard property sheet.
//****************************************************************************
LRESULT CALLBACK CalPovProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_ACTIVATEAPP: if( lpDIJoyState ) DoTestPOV(FORCE_POV_REFRESH, lpDIJoyState->rgdwPOV, hWnd); break;
case WM_INITDIALOG: { // Set the POV position to the Up position and Set the Text!
nCalState = JCS_POV_MOVEUP;
HWND hwndPOV = GetDlgItem(hWnd, IDC_JOYPOV); // Disable RTL flag
SetWindowLongPtr(hwndPOV, GWL_EXSTYLE, GetWindowLongPtr(hwndPOV,GWL_EXSTYLE)&~WS_EX_LAYOUTRTL);
// Set the Control font!
::SendDlgItemMessage(hWnd,IDC_WIZARD_MSG_HDR, WM_SETFONT, (WPARAM)hTitleFont, TRUE); break; } case WM_DESTROY: break;
case WM_COMMAND: switch( LOWORD(wParam) ) { case IDC_RAWDATA: RawDataSelected(hWnd, bShowRawData = !bShowRawData); break;
case IDC_SETPOV:
//if( joyGetPosEx(pdiCpl->GetID(), lpJoyInfo) == JOYERR_NOERROR ) {
if( SUCCEEDED(DIUtilPollJoystick(pdiDevice2, lpDIJoyState)) ) { CollectCalInfo(hWnd, lpDIJoyState); // Insert the POV information!
switch( nCalState ) { case JCS_POV_MOVEUP: // Store what we got!
pRanges->dwPOV[JOY_POVVAL_FORWARD] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_FORWARD] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0; // Once you're here... disable the buttons... no going back and forth...
::SendMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_DISABLEDFINISH); break;
case JCS_POV_MOVERIGHT: // Store what we got!
pRanges->dwPOV[JOY_POVVAL_RIGHT] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_RIGHT] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0; break;
case JCS_POV_MOVEDOWN: // Store what we got!
pRanges->dwPOV[JOY_POVVAL_BACKWARD] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_BACKWARD] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0; break;
case JCS_POV_MOVELEFT: // Store what we got!
pRanges->dwPOV[JOY_POVVAL_LEFT] = pJoyConfig->hwc.hwv.dwPOVValues[JOY_POVVAL_LEFT] = (pJoyConfig->hwc.hws.dwFlags & JOY_HWS_POVISPOLL) ? lpDIJoyState->rgdwPOV[0] : 0; ::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH);
// Take away the controls... it's all over!
DestroyWindow(GetDlgItem(hWnd, IDC_JOYPOV)); DestroyWindow(GetDlgItem(hWnd, IDC_SETPOV)); break; } }
nCalState++; CalStateChange(hWnd, NULL);
// Set the focus back to IDC_SETPOV button!
SendMessage(hWnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hWnd, IDC_SETPOV), (LPARAM)TRUE); break; } break;
// Change the background of all Static text fields to WHITE
case WM_CTLCOLORSTATIC: // We only want to paint the background for the items in the top white rectangle!
switch( GetDlgCtrlID((HWND)lParam) ) { case IDC_WIZARD_MSG: case IDC_HEADERFRAME: case IDC_WIZARD_MSG_HDR: return(LRESULT)GetStockObject(WHITE_BRUSH); } return(FALSE);
case WM_NOTIFY: switch( ((NMHDR FAR *) lParam)->code ) { case PSN_KILLACTIVE: KillTimer(hWnd, ID_CAL_TIMER); return(TRUE);
case PSN_RESET: break;
case PSN_SETACTIVE: if( nCalState == JCS_POV_MOVEUP ) { DoTestPOV(FORCE_POV_REFRESH, lpDIJoyState->rgdwPOV, hWnd); } CalStateChange(hWnd, NULL); break;
case PSN_WIZFINISH: WizFinish(hWnd); break;
case PSN_WIZBACK: // Determine what the next calibration stage is!
if( nCalState == nPrevCalState ) { DWORD dwAxis = pdiCpl->GetStateFlags()->nAxis; nPrevCalState --;
while( ( !(dwAxis & (1<<(--nPrevCalState)) ) ) && (nPrevCalState > JCS_XY_CENTER2) ){ ; } nPrevCalState ++; }
nCalState = nPrevCalState;
if( nCalState > JCS_XY_CENTER2 ) { if( nCalState <= JCS_S1_MOVE ) { UpdateProgressLabel(hWnd); CalStateChange( hWnd, (BYTE)NULL ); } else if( bPolledPOV ) { SetWindowLongPtr(hWnd, DWLP_MSGRESULT, IDD_POV );
return(IDD_POV); } } else { SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (nCalState < JCS_Z_MOVE) ? IDD_XY : -1); return(nCalState < JCS_Z_MOVE) ? IDD_XY : -1; }
break;
case PSN_WIZNEXT: // Take away the controls... it's all over!
DestroyWindow(GetDlgItem(hWnd, IDC_JOYPOV)); DestroyWindow(GetDlgItem(hWnd, IDC_SETPOV));
// Go on to Finish!
nCalState = JCS_FINI; CalStateChange(hWnd, NULL);
// Get rid of Back and bring on Finish!
::PostMessage(GetParent(hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_FINISH);
break;
default: return(FALSE);
} break;
default: return(FALSE); } return(TRUE); } #endif // WE_SUPPORT_CALIBRATING_POVS
//*******************************************************************************
//
// FUNCTION: CalStateChange( HWND hDlg, BYTE nDeviceFlags )
//
// PURPOSE: Procedure to set up the dialog for its' Next stage
//
// COMMENTS:
//
//*******************************************************************************
void CalStateChange( HWND hDlg, BYTE nDeviceFlags ) { short nMsgID = IDS_JOYCAL_MOVE; short nTitleID = IDS_AXIS_CALIBRATION;
#define MAX_CAL_VAL 0xfffffff
switch( nCalState ) { case JCS_XY_CENTER1: case JCS_XY_CENTER2: // Set up the string ID
if( nDeviceFlags & JOY_HWS_ISYOKE ) nMsgID = IDS_JOYCALXY_CENTERYOKE; else if( nDeviceFlags & JOY_HWS_ISCARCTRL ) nMsgID = IDS_JOYCALXY_CENTERCAR; else if( nDeviceFlags & JOY_HWS_ISGAMEPAD ) nMsgID = IDS_JOYCALXY_CENTERGAMEPAD; else nMsgID = IDS_JOYCALXY_CENTER;
// Setup the Header TextID
nTitleID = (nCalState == JCS_XY_CENTER1) ? IDS_CENTER_HDR : IDS_VERIFY_CENTER_HDR;
EnableXYWindows( hDlg ); break;
case JCS_XY_MOVE:
// Set up the string ID
if( nDeviceFlags & JOY_HWS_ISYOKE ) nMsgID = IDS_JOYCALXY_MOVEYOKE; else if( nDeviceFlags & JOY_HWS_ISCARCTRL ) nMsgID = IDS_JOYCALXY_MOVECAR; else if( nDeviceFlags & JOY_HWS_ISGAMEPAD ) nMsgID = IDS_JOYCALXY_MOVEGAMEPAD; else nMsgID = IDS_JOYCALXY_MOVE;
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwX = MAX_CAL_VAL; pRanges->jpMax.dwX = -MAX_CAL_VAL;
pRanges->jpMin.dwY = MAX_CAL_VAL; pRanges->jpMax.dwY = -MAX_CAL_VAL;
EnableXYWindows( hDlg ); break;
/*
case JCS_XY_CENTER1: // Set up the string ID
if ( nDeviceFlags & JOY_HWS_ISYOKE ) nMsgID = IDS_JOYCALXY_CENTERYOKE; else if( nDeviceFlags & JOY_HWS_ISCARCTRL ) nMsgID = IDS_JOYCALXY_CENTERCAR; else if( nDeviceFlags & JOY_HWS_ISGAMEPAD ) nMsgID = IDS_JOYCALXY_CENTERGAMEPAD; else nMsgID = IDS_JOYCALXY_CENTER;
// Setup the Header TextID
nTitleID = IDS_CENTER_HDR;
EnableXYWindows( hDlg ); break;
case JCS_XY_MOVE:
// Set up the string ID
if( nDeviceFlags & JOY_HWS_ISYOKE ) nMsgID = IDS_JOYCALXY_MOVEYOKE; else if( nDeviceFlags & JOY_HWS_ISCARCTRL ) nMsgID = IDS_JOYCALXY_MOVECAR; else if( nDeviceFlags & JOY_HWS_ISGAMEPAD ) nMsgID = IDS_JOYCALXY_MOVEGAMEPAD; else nMsgID = IDS_JOYCALXY_MOVE;
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwX = MAX_CAL_VAL; pRanges->jpMax.dwX = -MAX_CAL_VAL;
pRanges->jpMin.dwY = MAX_CAL_VAL; pRanges->jpMax.dwY = -MAX_CAL_VAL;
EnableXYWindows( hDlg ); break;
case JCS_XY_CENTER2:
// Set up the string ID
if( nDeviceFlags & JOY_HWS_ISYOKE ) nMsgID = IDS_JOYCALXY_CENTERYOKE; else if( nDeviceFlags & JOY_HWS_ISCARCTRL ) nMsgID = IDS_JOYCALXY_CENTERCAR; else if( nDeviceFlags & JOY_HWS_ISGAMEPAD ) nMsgID = IDS_JOYCALXY_CENTERGAMEPAD; else nMsgID = IDS_JOYCALXY_CENTER;
// Setup the Header TextID
nTitleID = IDS_VERIFY_CENTER_HDR;
EnableXYWindows( hDlg ); break; */ #ifdef DEADZONE
case JCS_DEADZONE: // Set up the message string.
if( nDeviceFlags & JOY_HWS_ISYOKE ) nMsgID = IDS_YOKE_DEADZONE; else if( nDeviceFlags & JOY_HWS_ISCARCTRL ) nMsgID = IDS_CAR_DEADZONE; else if( nDeviceFlags & JOY_HWS_ISGAMEPAD ) nMsgID = IDS_GAMEPAD_DEADZONE; else nMsgID = IDS_JOYSTICK_DEADZONE;
// Set up the title string!
nTitleID = IDS_DEADZONE_TITLE;
// Setup the controls!
EnableXYWindows( hDlg );
// Text Labels are sent in during UpdateXYLabel!
// Text fonts are set on INIT!
// Setup the Spin positions!
{ LPDIPROPDWORD pDIPropDW = (LPDIPROPDWORD)_alloca(DIPROPDWORD); ASSERT (pDIPropDW);
ZeroMemory(pDIPropDW, sizeof(DIPROPDWORD));
pDIPropDW->diph.dwSize = sizeof(DIPROPDWORD); pDIPropDW->diph.dwHeaderSize = sizeof(DIPROPHEADER); pDIPropDW->diph.dwObj = DIJOFS_X; pDIPropDW->diph.dwHow = DIPH_BYOFFSET;
HWND hSpinCtrl;
// Deadzone first...
if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_DEADZONE, &pDIPropDW->diph)) ) { // First the Deadzone...
hSpinCtrl = GetDlgItem(hDlg, IDC_X_DEADZONE_SPIN);
::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1)); ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L); ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0)); }
// Setup the DIPROPDWORD struct!
pDIPropDW->diph.dwObj = DIJOFS_Y;
if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_DEADZONE, &pDIPropDW->diph)) ) { // First the Deadzone...
hSpinCtrl = GetDlgItem(hDlg, IDC_Y_DEADZONE_SPIN);
::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1)); ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L); ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0)); }
// Now, the Saturation!
if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_SATURATION, &pDIPropDW->diph)) ) { hSpinCtrl = GetDlgItem(hDlg, IDC_Y_SATURATION_SPIN);
::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1)); ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L); ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0)); }
// Setup the DIPROPDWORD struct!
pDIPropDW->diph.dwObj = DIJOFS_X;
if( SUCCEEDED(pdiDevice2->GetProperty(DIPROP_SATURATION, &pDIPropDW->diph)) ) { hSpinCtrl = GetDlgItem(hDlg, IDC_X_SATURATION_SPIN);
::PostMessage(hSpinCtrl, UDM_SETRANGE, 0, MAKELPARAM(1000, 1)); ::PostMessage(hSpinCtrl, UDM_SETBASE, 10, 0L); ::PostMessage(hSpinCtrl, UDM_SETPOS, 0, MAKELPARAM(pDIPropDW->dwData, 0)); } }
// Draw the rectangle!
break; #endif //DEADZONE
case JCS_Z_MOVE: { static long nMin = pRanges->jpMin.dwZ; static long nMax = pRanges->jpMax.dwZ;
// Set the Range
if( bGradient ) pGradient->SetRange(nMin, nMax);
::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwZ = MAX_CAL_VAL; pRanges->jpMax.dwZ = -MAX_CAL_VAL; } break;
case JCS_R_MOVE: { static long nMin = pRanges->jpMin.dwRx; static long nMax = pRanges->jpMax.dwRx;
// Set the Range
if( bGradient ) pGradient->SetRange(nMin, nMax);
::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwRx = MAX_CAL_VAL; pRanges->jpMax.dwRx = -MAX_CAL_VAL; } break;
case JCS_U_MOVE: { static long nMin = pRanges->jpMin.dwRy; static long nMax = pRanges->jpMax.dwRy;
// Set the Range
if( bGradient ) pGradient->SetRange(nMin, nMax);
::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwRy = MAX_CAL_VAL; pRanges->jpMax.dwRy = -MAX_CAL_VAL; } break;
case JCS_V_MOVE: { static long nMin = pRanges->jpMin.dwRz; static long nMax = pRanges->jpMax.dwRz;
// Set the Range
if( bGradient ) pGradient->SetRange(nMin, nMax);
::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwRz = MAX_CAL_VAL; pRanges->jpMax.dwRz = -MAX_CAL_VAL; } break;
case JCS_S0_MOVE: { static long nMin = pRanges->jpMin.dwS0; static long nMax = pRanges->jpMax.dwS0;
// Set the Range
if( bGradient ) pGradient->SetRange(nMin, nMax);
::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwS0 = MAX_CAL_VAL; pRanges->jpMax.dwS0 = -MAX_CAL_VAL; } break;
case JCS_S1_MOVE: { static long nMin = pRanges->jpMin.dwS1; static long nMax = pRanges->jpMax.dwS1;
// Set the Range
if( bGradient ) pGradient->SetRange(nMin, nMax);
::PostMessage(ProgWndCal, PBM_SETRANGE32, (WPARAM)nMin, (LPARAM)nMax);
// Blast the data so we are sure to get the correct data!
pRanges->jpMin.dwS1 = MAX_CAL_VAL; pRanges->jpMax.dwS1 = -MAX_CAL_VAL; } break;
#ifdef WE_SUPPORT_CALIBRATING_POVS
case JCS_POV_MOVEUP: lpDIJoyState->rgdwPOV[0] = JOY_POVFORWARD; DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
nMsgID = IDS_JOYCALPOV_MOVE; nTitleID = IDS_POV_CALIBRATION; break;
case JCS_POV_MOVERIGHT: lpDIJoyState->rgdwPOV[0] = JOY_POVRIGHT; DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
nMsgID = IDS_JOYCALPOV_MOVE; nTitleID = IDS_POV_CALIBRATION; break;
case JCS_POV_MOVEDOWN: lpDIJoyState->rgdwPOV[0] = JOY_POVBACKWARD; DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
nMsgID = IDS_JOYCALPOV_MOVE; nTitleID = IDS_POV_CALIBRATION; break;
case JCS_POV_MOVELEFT: lpDIJoyState->rgdwPOV[0] = JOY_POVLEFT; DoTestPOV(HAS_POV1 | HAS_CALIBRATED, lpDIJoyState->rgdwPOV, hDlg);
nMsgID = IDS_JOYCALPOV_MOVE; nTitleID = IDS_POV_CALIBRATION; break; #endif //WE_SUPPORT_CALIBRATING_POVS
case JCS_FINI: nMsgID = IDS_JOYCAL_DONE; nTitleID = IDS_CALIBRATION_FINI; break;
default: #ifdef _DEBUG
OutputDebugString(TEXT("GCDEF.DLL: CAL.CPP: CalStateChange: nCalState doesn't match any known Calibration States!\n")); #endif
return;
} // END OF SWITCH
// load and set the text
LPTSTR lptszMsg = new TCHAR[MAX_STR_LEN];
DWORD nStrLen = MAX_STR_LEN - 1;
// see if there is any OEM text specified
if( pJoyConfig->hwc.dwUsageSettings & JOY_US_ISOEM ) { GetOEMCtrlString(lptszMsg, &nStrLen); } else { nStrLen = 0; }
// nStrLen will be non-zero if GetOEMCtrlString is successfull!
if( nStrLen == 0 ) { VERIFY(LoadString(ghInst, nMsgID, lptszMsg, MAX_STR_LEN));
switch( nMsgID ) { case IDS_JOYCAL_MOVE: { LPTSTR lptszBuff = new TCHAR[STR_LEN_32]; LPTSTR lpDup = StrDup(lptszMsg);
if( lptszBuff && lpDup ) { ::SendDlgItemMessage(hDlg, IDC_JOYLIST2_LABEL, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)lptszBuff); wsprintf(lptszMsg, lpDup, lptszBuff); LocalFree(lpDup); delete []lptszBuff; } } break; } }
// Send the smaller message
::SendDlgItemMessage(hDlg, IDC_WIZARD_MSG, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)lptszMsg);
VERIFY(LoadString(ghInst, nTitleID, lptszMsg, MAX_STR_LEN));
// Send the Bold Header message
::SendDlgItemMessage(hDlg, IDC_WIZARD_MSG_HDR, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)lptszMsg);
if( lptszMsg ) { delete[] (lptszMsg); }
// Take care of the RawData dialog items!
switch( nCalState ) { // Don't do the raw data thing if you don't have the checkbox!
case JCS_XY_CENTER1: case JCS_XY_CENTER2: case JCS_FINI: break;
// Do the percent for the pages that need it!
case JCS_Z_MOVE: case JCS_R_MOVE: case JCS_U_MOVE: case JCS_V_MOVE: case JCS_S0_MOVE: case JCS_S1_MOVE: if( bGradient ) { if( pGradient ) { pGradient->ShowPercent(bShowRawData); } } // Missing break intentional!!!
default: RawDataSelected(hDlg, bShowRawData); ::SendDlgItemMessage(hDlg, IDC_RAWDATA, BM_SETCHECK, (bShowRawData) ? BST_CHECKED : BST_UNCHECKED, 0); break; }
} // *** end of CalStateChange
//*******************************************************************************
//
// FUNCTION: CollectCalInfo( HWND hDlg, LPDIJOYSTATE pdiJoyState )
//
// PURPOSE: Procedure to Collect Calibration Data
//
// COMMENTS:
//
//*******************************************************************************
BOOL CollectCalInfo( HWND hDlg, LPDIJOYSTATE pdiJoyState ) { TCHAR tsz[16];
switch( nCalState ) { // remember XY center
case JCS_XY_CENTER1: // store the initial centres!
pRanges->jpCenter.dwY = pdiJoyState->lY; pRanges->jpCenter.dwX = pdiJoyState->lX;
// We Have an X/Y, so let's check for our Pens!
CreatePens(); break;
// remember max/min XY values
case JCS_XY_MOVE: if( pdiJoyState->lX > pRanges->jpMax.dwX ) pRanges->jpMax.dwX = pdiJoyState->lX; else if( pdiJoyState->lX < pRanges->jpMin.dwX ) pRanges->jpMin.dwX = pdiJoyState->lX;
if( pdiJoyState->lY > pRanges->jpMax.dwY ) pRanges->jpMax.dwY = pdiJoyState->lY; else if( pdiJoyState->lY < pRanges->jpMin.dwY ) pRanges->jpMin.dwY = pdiJoyState->lY;
// if IDC_RAWXOUTPUT is visible, then so is IDC_RAWYOUTPUT...
// no bother to even ask.
if( bShowRawData ) { static POINT ptOld = {DELTA,DELTA};
if( (ptOld.x != pdiJoyState->lX) || (ptOld.y != pdiJoyState->lY) ) { myitoa(pdiJoyState->lX, &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
myitoa(pdiJoyState->lY, &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWYOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz);
ptOld.x = pdiJoyState->lX; ptOld.y = pdiJoyState->lY; } }
// Scale before send it to DoJoyMove!
{ RECT rc; GetClientRect(GetDlgItem(hDlg, IDC_JOYLIST1), &rc);
// Casting to the UINT will change the sign!
UINT nRange = (UINT)(pRanges->jpMax.dwX - pRanges->jpMin.dwX);
float nScaledRange = (float)(rc.right-DELTA);
if( nRange ) nScaledRange /= (float)nRange;
// Scale X
pdiJoyState->lX = (long)((pdiJoyState->lX - pRanges->jpMin.dwX) * nScaledRange);
// Scale Y
if( nRange ) nScaledRange = (float)rc.bottom / (float)nRange; pdiJoyState->lY = (long)((pdiJoyState->lY - pRanges->jpMin.dwY) * nScaledRange); } DoJoyMove( hDlg, (BYTE)HAS_X|HAS_Y ); break;
case JCS_XY_CENTER2: // Average the Y
pRanges->jpCenter.dwY = (pRanges->jpCenter.dwY += pdiJoyState->lY)>>1;
//Average the X
pRanges->jpCenter.dwX = (pRanges->jpCenter.dwX += pdiJoyState->lX)>>1; break;
// remember max/min Z value
case JCS_Z_MOVE: // Set new Min's and Max's...
// Set a new Center whenever either is hit!
if( pdiJoyState->lZ > pRanges->jpMax.dwZ ) { pRanges->jpMax.dwZ = pdiJoyState->lZ; pRanges->jpCenter.dwZ = (pRanges->jpMax.dwZ+pRanges->jpMin.dwZ)>>1; } else if( pdiJoyState->lZ < pRanges->jpMin.dwZ ) { pRanges->jpMin.dwZ = pdiJoyState->lZ; pRanges->jpCenter.dwZ = (pRanges->jpMax.dwZ+pRanges->jpMin.dwZ)>>1; }
// Do the position status
// Update the text
if( bShowRawData ) { myitoa(pdiJoyState->lZ, &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); }
if( bGradient ) pGradient->SetPos(pdiJoyState->lZ);
::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lZ, 0L); break;
// remember max/min Rx value
case JCS_R_MOVE: // Set new Min's and Max's...
// Set a new Center whenever either is hit!
if( pdiJoyState->lRx > pRanges->jpMax.dwRx ) { pRanges->jpMax.dwRx = pdiJoyState->lRx; pRanges->jpCenter.dwRx = (pRanges->jpMax.dwRx+pRanges->jpMin.dwRx)>>1; } else if( pdiJoyState->lRx < pRanges->jpMin.dwRx ) { pRanges->jpMin.dwRx = pdiJoyState->lRx; pRanges->jpCenter.dwRx = (pRanges->jpMax.dwRx+pRanges->jpMin.dwRx)>>1; }
// Do the position status
// Update the text
if( bShowRawData ) { myitoa(pdiJoyState->lRx, &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); }
if( bGradient ) pGradient->SetPos(pdiJoyState->lRx);
::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lRx, 0L); break;
// remember max/min Ry value
case JCS_U_MOVE: // Set new Min's and Max's...
// Set a new Center whenever either is hit!
if( pdiJoyState->lRy > pRanges->jpMax.dwRy ) { pRanges->jpMax.dwRy = pdiJoyState->lRy; pRanges->jpCenter.dwRy = (pRanges->jpMax.dwRy+pRanges->jpMin.dwRy)>>1; } else if( pdiJoyState->lRy < pRanges->jpMin.dwRy ) { pRanges->jpMin.dwRy = pdiJoyState->lRy; pRanges->jpCenter.dwRy = (pRanges->jpMax.dwRy+pRanges->jpMin.dwRy)>>1; }
// Do the position status
if( bShowRawData ) { myitoa(pdiJoyState->lRy, &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); }
if( bGradient ) pGradient->SetPos(pdiJoyState->lRy);
::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lRy, 0L); break;
// remember max/min Rz value
case JCS_V_MOVE: // Set new Min's and Max's...
// Set a new Center whenever either is hit!
if( pdiJoyState->lRz > pRanges->jpMax.dwRz ) { pRanges->jpMax.dwRz = pdiJoyState->lRz; pRanges->jpCenter.dwRz = (pRanges->jpMax.dwRz+pRanges->jpMin.dwRz)>>1; } else if( pdiJoyState->lRz < pRanges->jpMin.dwRz ) { pRanges->jpMin.dwRz = pdiJoyState->lRz; pRanges->jpCenter.dwRz = (pRanges->jpMax.dwRz+pRanges->jpMin.dwRz)>>1; }
// Do the position status
if( bShowRawData ) { myitoa(pdiJoyState->lRz, &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); }
if( bGradient ) pGradient->SetPos(pdiJoyState->lRz);
::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->lRz, 0L); break;
// remember max/min S0 value
case JCS_S0_MOVE: // Set new Min's and Max's...
// Set a new Center whenever either is hit!
if( pdiJoyState->rglSlider[0] > pRanges->jpMax.dwS0 ) { pRanges->jpMax.dwS0 = pdiJoyState->rglSlider[0]; pRanges->jpCenter.dwS0 = (pRanges->jpMax.dwS0+pRanges->jpMin.dwS0)>>1; } else if( pdiJoyState->rglSlider[0] < pRanges->jpMin.dwS0 ) { pRanges->jpMin.dwS0 = pdiJoyState->rglSlider[0]; pRanges->jpCenter.dwS0 = (pRanges->jpMax.dwS0+pRanges->jpMin.dwS0)>>1; }
// Do the position status
if( bShowRawData ) { myitoa(pdiJoyState->rglSlider[0], &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); }
if( bGradient ) pGradient->SetPos(pdiJoyState->rglSlider[0]);
::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->rglSlider[0], 0L); break;
// remember max/min S1 value
case JCS_S1_MOVE: // Set new Min's and Max's...
// Set a new Center whenever either is hit!
if( pdiJoyState->rglSlider[1] > pRanges->jpMax.dwS1 ) { pRanges->jpMax.dwS1 = pdiJoyState->rglSlider[1]; pRanges->jpCenter.dwS1 = (pRanges->jpMax.dwS1+pRanges->jpMin.dwS1)>>1; } else if( pdiJoyState->rglSlider[1] < pRanges->jpMin.dwS1 ) { pRanges->jpMin.dwS1 = pdiJoyState->rglSlider[1]; pRanges->jpCenter.dwS1 = (pRanges->jpMax.dwS1+pRanges->jpMin.dwS1)>>1; }
// Do the position status
if( bShowRawData ) { myitoa(pdiJoyState->rglSlider[1], &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); }
if( bGradient ) pGradient->SetPos(pdiJoyState->rglSlider[1]);
::PostMessage(ProgWndCal, PBM_SETPOS, (WPARAM)pdiJoyState->rglSlider[1], 0L); break;
case JCS_POV_MOVEUP: case JCS_POV_MOVERIGHT: case JCS_POV_MOVEDOWN: case JCS_POV_MOVELEFT: // Do the position status
/*
if( bShowRawData ) { myitoa(pdiJoyState->rgdwPOV[0], &tsz[0]); ::SendDlgItemMessage(hDlg, IDC_RAWXOUTPUT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)tsz); } */ break; }
return(TRUE); } // CollectCalInfo
//*******************************************************************************
//
// FUNCTION: EnableXYWindows( HWND hDlg)
//
// PURPOSE: Enables X/Y Windows
//
// COMMENTS:
//
//*******************************************************************************
void EnableXYWindows( HWND hDlg ) { ////// set up the XY window controls ///////
USHORT nCtrls[] = {IDC_RAWX, IDC_RAWY, IDC_RAWXOUTPUT, IDC_RAWYOUTPUT}; BYTE nNumCtrls = sizeof(nCtrls)/sizeof(short);
do { SetWindowPos( GetDlgItem( hDlg, nCtrls[--nNumCtrls]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW); } while( nNumCtrls );
#ifdef DEADZONE
{ USHORT nDZCtrls[] = {IDC_X_DEADZONE_SPIN, IDC_Y_DEADZONE_SPIN, IDC_X_SATURATION_SPIN, IDC_Y_SATURATION_SPIN, IDC_DEADZONE_TITLE, IDC_X_DEADZONE, IDC_Y_DEADZONE, IDC_X_AXIS_LABEL, IDC_X_AXIS_LABEL, IDC_Y_AXIS_LABEL, IDC_SATURATION_TITLE,IDC_X_SATURATION, IDC_Y_SATURATION, IDC_X_AXIS_LABEL_SATURATION, IDC_Y_AXIS_LABEL_SATURATION}; nNumCtrls = sizeof(nCtrls)/sizeof(short);
do { // Use SetWindowPos here because internally, ShowWindow calls it!
SetWindowPos( GetDlgItem( hDlg, nCtrls[nNumCtrls]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((nCalState == JCS_DEADZONE) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); } while( nNumCtrls-- ); } #endif // DEADZONE
nCtrls[0] = IDC_JOYLIST1; nCtrls[1] = IDC_JOYLIST1_LABEL; nCtrls[2] = IDC_RAWDATA; nNumCtrls = 2;
do { // Use SetWindowPos here because internally, ShowWindow calls it!
SetWindowPos( GetDlgItem( hDlg, nCtrls[nNumCtrls]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | (((nCalState == JCS_XY_MOVE) #ifdef DEADZONE
|| (nCalState == JCS_DEADZONE) #endif
) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); } while( nNumCtrls-- ); HWND hwndXY = GetDlgItem(hDlg, IDC_JOYLIST1); // Disable RTL flag
SetWindowLongPtr( hwndXY, GWL_EXSTYLE, GetWindowLongPtr(hwndXY,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL ); }
//*******************************************************************************
//
// FUNCTION: GetOEMCtrlString(LPTSTR lptStr, BYTE *nStrLen)
//
// PURPOSE: Gets string and string length for OEM controls
//
// COMMENTS:
//
//*******************************************************************************
BOOL GetOEMCtrlString(LPTSTR lptStr, LPDWORD nStrLen) { // there's no REGSTR_VAL_JOYOEM for the sliders so return false and take the defaults
switch( nCalState ) { case JCS_S0_MOVE: case JCS_S1_MOVE: *nStrLen = 0; return(FALSE); }
// Get the DIJOYCONFIG interface pointer!
LPDIRECTINPUTJOYCONFIG pdiJoyConfig; pdiCpl->GetJoyConfig(&pdiJoyConfig);
BOOL bRet = FALSE;
if( SUCCEEDED(pdiJoyConfig->Acquire()) ) { HKEY hKey;
// Open the TypeKey
if( SUCCEEDED(pdiJoyConfig->OpenTypeKey( lpwszTypeName, KEY_ALL_ACCESS, &hKey)) ) { // registry strings for calibration messages
static LPCTSTR pszOEMCalRegStrs[] = { REGSTR_VAL_JOYOEMCAL1, REGSTR_VAL_JOYOEMCAL2, REGSTR_VAL_JOYOEMCAL3, REGSTR_VAL_JOYOEMCAL4, REGSTR_VAL_JOYOEMCAL5, REGSTR_VAL_JOYOEMCAL6, REGSTR_VAL_JOYOEMCAL7,
#ifdef WE_SUPPORT_CALIBRATING_POVS
REGSTR_VAL_JOYOEMCAL8, REGSTR_VAL_JOYOEMCAL9, REGSTR_VAL_JOYOEMCAL10,REGSTR_VAL_JOYOEMCAL11, #endif // WE_SUPPORT_CALIBRATING_POVS
REGSTR_VAL_JOYOEMCAL12 };
if( nCalState < (sizeof(pszOEMCalRegStrs)/sizeof(pszOEMCalRegStrs[0])) ) { DWORD dwType = REG_SZ; // the -2 is because of JCS_S0_MOVE and JCS_S1_MOVE!
if( RegQueryValueEx( hKey, pszOEMCalRegStrs[(nCalState == JCS_FINI) ? nCalState-2 : nCalState], NULL, &dwType, (CONST LPBYTE)lptStr, nStrLen ) == ERROR_SUCCESS ) bRet = TRUE; else *nStrLen = 0; } else { *nStrLen = 0; } RegCloseKey(hKey); } else { *nStrLen = 0; #ifdef _DEBUG
OutputDebugString(TEXT("Test.cpp: GetOEMCtrlString: OpenTypeKey FAILED!\n")); #endif
}
pdiJoyConfig->Unacquire(); }
return(bRet); } // *** end of GetOEMCtrlString
#ifdef WE_SUPPORT_CALIBRATING_POVS
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SetDefaultButton( HWND hwdb )
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
void SetDefaultButton( HWND hDlg, HWND hCtrl ) { // make the specified button the default
DWORD style = GetWindowLong( hCtrl, GWL_STYLE ); style &= ~(BS_PUSHBUTTON|BS_DEFPUSHBUTTON); style |= BS_DEFPUSHBUTTON; SetWindowLong( hCtrl, GWL_STYLE, style );
} // SetDefaultButton
#endif //WE_SUPPORT_CALIBRATING_POVS
//===========================================================================
// SetCalibrationMode ( BOOL bSet )
//
// Sets DirectInput Calibration mode (RAW/COOKED)
//
// Parameters:
// BOOL bSet - TRUE for RAW, FALSE for COOKED
//
// Returns: return value from SetProperty (standard COM stuff)
//
//===========================================================================
HRESULT SetCalibrationMode( BOOL bSet) { LPDIPROPDWORD pDIPropDword = (LPDIPROPDWORD)_alloca(sizeof(DIPROPDWORD)); assert (pDIPropDword);
pDIPropDword->diph.dwSize = sizeof(DIPROPDWORD); pDIPropDword->diph.dwHeaderSize = sizeof(DIPROPHEADER); pDIPropDword->diph.dwObj = 0x0; pDIPropDword->diph.dwHow = DIPH_DEVICE; pDIPropDword->dwData = bSet ? DIPROPCALIBRATIONMODE_RAW : DIPROPCALIBRATIONMODE_COOKED;
// Set the mode to Raw Data during Calibration!
HRESULT hr = pdiDevice2->SetProperty(DIPROP_CALIBRATIONMODE, &pDIPropDword->diph); #ifdef _DEBUG
if( FAILED(hr) ) { OutputDebugString(TEXT("GCDEF.DLL: CAL.CPP: SetCalibrationMode: SetProperty Failed with a return of "));
switch( hr ) { case DI_PROPNOEFFECT: OutputDebugString(TEXT("DI_PROPNOEFFECT\n")); break;
case DIERR_INVALIDPARAM: OutputDebugString(TEXT("DIERR_INVALIDPARAM\n")); break;
case DIERR_OBJECTNOTFOUND: OutputDebugString(TEXT("DIERR_OBJECTNOTFOUND\n")); break;
case DIERR_UNSUPPORTED: OutputDebugString(TEXT("DIERR_UNSUPPORTED\n")); break;
default: { TCHAR szTmp[32]; wsprintf(szTmp, TEXT("%x"), hr); OutputDebugString(szTmp); } } } #endif
return(hr); }
//===========================================================================
// UpdateXYLabel(HWND hWnd)
//
// Displays the number and names of the device Axis in the provided dialog.
// This EXPECTS that the controls are not visible by default!
//
// Parameters:
// HWND hDlg - Dialog handle
//
// Returns:
//
//===========================================================================
void UpdateXYLabel(const HWND hDlg) { BYTE nAxisFlags = pdiCpl->GetStateFlags()->nAxis;
// X and Y use the same control so they are isolated!
if( (nAxisFlags & HAS_X) || (nAxisFlags & HAS_Y) ) { LPDIDEVICEOBJECTINSTANCE_DX3 pDevObjInst = new (DIDEVICEOBJECTINSTANCE_DX3); assert (pDevObjInst);
ZeroMemory(pDevObjInst, sizeof(DIDEVICEOBJECTINSTANCE_DX3));
pDevObjInst->dwSize = sizeof(DIDEVICEOBJECTINSTANCE_DX3);
LPTSTR ptszBuff = (LPTSTR) _alloca(sizeof(TCHAR[STR_LEN_32])); assert (ptszBuff);
ZeroMemory(ptszBuff, sizeof(TCHAR[STR_LEN_32]));
// Set it's text
if( nAxisFlags & HAS_X ) { if( FAILED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, DIJOFS_X, DIPH_BYOFFSET)) ) { #ifdef _DEBUG
OutputDebugString(TEXT("GCDEF.DLL: DisplayAvailableAxis: GetObjectInfo Failed to find DIJOFS_X!\n")); #endif
}
int nLen=lstrlen(pDevObjInst->tszName)+1; if(nLen>STR_LEN_32) nLen=STR_LEN_32; StrCpyN(ptszBuff, pDevObjInst->tszName, nLen);
// Set the Output Label!
::SendDlgItemMessage(hDlg, IDC_RAWX, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
#ifdef DEADZONE
// Set text labels!
::SendDlgItemMessage(hDlg, IDC_X_AXIS_LABEL_DEADZONE, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName); ::SendDlgItemMessage(hDlg, IDC_X_AXIS_LABEL_SATURATION, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName); #endif //DEADZONE
// Remove the HAS_X flag
nAxisFlags &= ~HAS_X; }
if( nAxisFlags & HAS_Y ) { if( FAILED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, DIJOFS_Y, DIPH_BYOFFSET)) ) { #ifdef _DEBUG
OutputDebugString(TEXT("GCDEF.DLL: DisplayAvailableAxis: GetObjectInfo Failed to find DIJOFS_Y!\n")); #endif
}
#ifdef DEADZONE
// Set text labels!
::SendDlgItemMessage(hDlg, IDC_Y_AXIS_LABEL_DEADZONE, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName); ::SendDlgItemMessage(hDlg, IDC_Y_AXIS_LABEL_SATURATION, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName); #endif //DEADZONE
// just in case it has Y but not X
if( ptszBuff && lstrlen(ptszBuff) ) { // Whisltler PREFIX 45092
int nLen=STR_LEN_32-lstrlen(ptszBuff); StrNCat(ptszBuff, TEXT(" / "), nLen); }
int nLen=STR_LEN_32-lstrlen(ptszBuff); StrNCat(ptszBuff, pDevObjInst->tszName, nLen);
// Set the Output Label!
::SendDlgItemMessage(hDlg, IDC_RAWY, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName);
// Remove the HAS_Y flag
nAxisFlags &= ~HAS_Y; }
if( pDevObjInst ) delete (pDevObjInst);
::SendDlgItemMessage(hDlg, IDC_JOYLIST1_LABEL, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)ptszBuff);
// if (ptszBuff)
// delete[] (ptszBuff);
} } //*** end of UpdateXYLabel
//*******************************************************************************
//
// FUNCTION: UpdateProgressLabel(HWND hDlg)
//
// PURPOSE: Updates Axis specific labels based on the current Calibration stage.
//
// COMMENTS:
//
//*******************************************************************************
BOOL UpdateProgressLabel(const HWND hDlg) { // Array of supported axis!
const DWORD dwOffsetArray[] = {DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1)}; BOOL bRet = FALSE;
LPDIDEVICEOBJECTINSTANCE_DX3 pDevObjInst = (LPDIDEVICEOBJECTINSTANCE_DX3)_alloca(sizeof(DIDEVICEOBJECTINSTANCE_DX3)); assert (pDevObjInst);
ZeroMemory(pDevObjInst, sizeof(DIDEVICEOBJECTINSTANCE_DX3));
pDevObjInst->dwSize = sizeof(DIDEVICEOBJECTINSTANCE_DX3);
// Get it's text
if( SUCCEEDED(pdiDevice2->GetObjectInfo((LPDIDEVICEOBJECTINSTANCE)pDevObjInst, dwOffsetArray[nCalState-3], DIPH_BYOFFSET)) ) { // Set it's text
::SendDlgItemMessage(hDlg, IDC_JOYLIST2_LABEL, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName); ::SendDlgItemMessage(hDlg, IDC_RAWX, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDevObjInst->tszName); bRet = TRUE; }
return(bRet); }
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: myitoa(long n, LPTSTR lpStr)
//
// PARAMETERS: BYTE n - Number to be translated
// LPTSTR lpStr - Buffer to recieve translated value
//
// PURPOSE: Convert BYTE values < 20 to strings.
///////////////////////////////////////////////////////////////////////////////
void myitoa(long n, LPTSTR lpStr) { long sign = n;
if( n < 0 ) n = - n;
LPTSTR pchStart = lpStr;
do { *lpStr++ = (TCHAR)(n % 10 + '0'); } while( (n /= 10) > 0 );
if( sign < 0 ) *lpStr++ = '-'; *lpStr = '\0'; reverse(pchStart); }
void reverse(LPTSTR string) { TCHAR c; short i, j;
for( i = 0, j = lstrlen(string) - 1; i < j; i++, j-- ) { c = string[j]; string[j] = string[i]; string[i] = c; } }
//*******************************************************************************
//
// FUNCTION: RawDataSelected( HWND hWnd, BOOL bEnable )
//
// PURPOSE: Shows/Hides Raw data associated windows.
//
// COMMENTS:
//
//*******************************************************************************
void RawDataSelected( const HWND hWnd, BOOL bEnable ) { const USHORT nCtrlArray[] = {IDC_RAWX, IDC_RAWY, IDC_RAWXOUTPUT, IDC_RAWYOUTPUT}; BYTE nCtrls = sizeof(nCtrlArray)/sizeof(short);
do { SetWindowPos( GetDlgItem( hWnd, nCtrlArray[--nCtrls]), NULL, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | ((bEnable) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); } while( nCtrls ); }
//*******************************************************************************
//
// FUNCTION: TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
//
// PURPOSE: TimerProc for the Calibration Wizard.
// Searches for button presses, then moves to next stage/finish.
//
// COMMENTS:
//
//*******************************************************************************
VOID CALLBACK TimerProc(const HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime) { if( SUCCEEDED(DIUtilPollJoystick(pdiDevice2, lpDIJoyState)) ) { CollectCalInfo(hWnd, lpDIJoyState);
// Don't bother checking for key presses if the user is in the POV stage!
if( nCalState <= JCS_S1_MOVE ) { // Catch button presses...
static BYTE nDownButton = 0xff; BYTE i = 0;
int nButtons = pdiCpl->GetStateFlags()->nButtons;
// only attempt to check buttons we KNOW we have!!!
while( nButtons ) { // check for a button press
if( lpDIJoyState->rgbButtons[i] & 0x80 ) { if( nDownButton != 0xff ) break;
// Let the Next button handle the processing
::PostMessage(GetParent(hWnd), PSM_PRESSBUTTON, (WPARAM)(int)(nCalState > JCS_S1_MOVE) ? PSBTN_FINISH : PSBTN_NEXT, 0);
// Store the button that went down!
nDownButton = i;
// mission accomplished!
return; } // reset the nDownButton flag
else if( i == nDownButton ) nDownButton = 0xff;
nButtons &= ~(HAS_BUTTON1<<i++); } // end of catch for button presses!
} } }
// This is because PSN_WIZFINISH is Documented to be sent to every page dlg proc on exit... but it doesn't!
static void WizFinish(const HWND hWnd) { HRESULT hres;
KillTimer(hWnd, ID_CAL_TIMER);
// assign the new ranges
SetMyRanges(pdiDevice2, pRanges, pdiCpl->GetStateFlags()->nAxis);
LPDIRECTINPUTJOYCONFIG pdiJoyConfig; pdiCpl->GetJoyConfig(&pdiJoyConfig);
if( pdiCpl->GetStateFlags()->nPOVs ) { pdiDevice2->Unacquire(); SetCalibrationMode( FALSE ); pdiJoyConfig->Acquire();
CopyRange( &pJoyConfig->hwc.hwv.jrvHardware, pRanges ); memcpy( pJoyConfig->hwc.hwv.dwPOVValues, pRanges->dwPOV, sizeof(DWORD)*4 );
hres = pdiJoyConfig->SetConfig(pdiCpl->GetID(), (LPDIJOYCONFIG)pJoyConfig, DIJC_REGHWCONFIGTYPE); #ifdef WE_SUPPORT_CALIBRATING_POVS
if( SUCCEEDED(hres) ) { CalibratePolledPOV( &pJoyConfig->hwc );
// set POV positions!
if( bPolledPOV ) { SetMyPOVRanges(pdiDevice2); } } #endif
}
pdiJoyConfig->SendNotify(); pdiDevice2->Unacquire(); }
|