windows-nt/Source/XPSP1/NT/multimedia/directx/gamectrl/default/cal.cpp
2020-09-26 16:20:57 +08:00

2025 lines
67 KiB
C++

//===========================================================================
// 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();
}