//**************************************************************************** // // File: joycal.c // Content: Joystick calibration dialog // History: // Date By Reason // ==== == ====== // 11-dec-94 craige split out of joycpl.c; some tweaks // 15-dec-94 craige allow N joysticks // 17-dec-94 craige new UI as requested by ChrisB // 18-dec-94 craige process UV // 05-jan-95 craige new centering confirmation messages // 04-mar-95 craige bug 10761 - separate strings for pluralization // bug 12036 - now works when "Back" clicked off of // custom 4-axis with POV hat // // Copyright (c) Microsoft Corporation 1994-1995 // //**************************************************************************** #pragma pack (8) #include "stdafx.h" #include "joycpl.h" #include "resource.h" #include "pov.h" #include "assert.h" #include "baseids.h" #include "comstr.h" #undef NewLoadString #define NewLoadString(a, b, c, d) \ pszCommonString->LoadString(b); \ lstrcpy( c, (LPCTSTR)*pszCommonString ) // Context sensitive help stuff! static void OnContextMenu(WPARAM wParam); static void OnHelp (LPARAM); static const DWORD CalibrateHelpIDs[] = { IDC_JOYLIST1, IDC_JOYLIST1, IDC_JOYLIST2, IDC_JOYLIST2, IDC_JOYLIST3, IDC_JOYLIST3, IDC_JOYLIST4, IDC_JOYLIST4, 0, 0 }; /* * This has the look and feel of a wizard, but isn't This leads to the * obvious... * * Q: Why isn't this a "real" wizard? * * A: - it doesn't have multiple pages, it has a single page. the user * sees different joystick items activate and de-activate on the dialog * as he/she calibrates each axis. fussing with multiple sheets for each * axis would be confusing and unnecessary. */ /* * calibration states */ // %%% debug %%% alpha days extern "C" { typedef enum { JCS_INIT=-1, JCS_XY_CENTER1, JCS_XY_MOVE, JCS_XY_CENTER2, JCS_Z_MOVE, JCS_Z_PLACEHOLDER, JCS_R_MOVE, JCS_R_PLACEHOLDER, JCS_U_MOVE, JCS_U_PLACEHOLDER, JCS_V_MOVE, JCS_V_PLACEHOLDER, JCS_POV_MOVEUP, JCS_POV_MOVERIGHT, JCS_POV_MOVEDOWN, JCS_POV_MOVELEFT, JCS_FINI } cal_states; typedef enum { JC_XY=0, JC_Z, JC_POV_UP, JC_POV_RIGHT, JC_POV_DOWN, JC_POV_LEFT, JC_R, JC_U, JC_V, JC_FINI } cal_wins; // variables used in calibration typedef struct { LPGLOBALVARS pgv; cal_states cState; BOOL bHasTimer; BOOL bUseTimer; HINSTANCE hinst; JOYINFOEX ji; JOYRANGE jr; DWORD pov[JOY_POV_NUMDIRS]; int iAxisCount; BOOL bPOVdone; } CALVARS, *LPCALVARS; extern "C" WINMMAPI MMRESULT WINAPI joyConfigChanged(DWORD); #define JOY_CALIB_FLAGS JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | \ JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | \ JOY_RETURNBUTTONS | JOY_RETURNRAWDATA /* * we use raw data during calibration; RAW_SHIFT allows us to convert to * a reasonable "real" value */ #define RAW_SHIFT 100 } // extern "C" // setDefaultButton - make a button the default window static void setDefaultButton( HWND hwnd, HWND hwdb ) { // Optimized New Method SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwdb, (LPARAM)TRUE); /* Optimized Old Method DWORD style; HWND hCtrl; int idList[] = { IDC_JOYCALDONE, IDC_JOYCALNEXT, IDC_JOYCALBACK, IDC_JOYPICKPOV }; #define SIZEOF_LIST 4 // turn off the current default push button for (short i=0; i < SIZEOF_LIST; i++ ) { hCtrl = GetDlgItem( hwnd, idList[i] ); if (hCtrl) { style = GetWindowLong( hCtrl, GWL_STYLE ); if ( style & BS_DEFPUSHBUTTON ) { style &= ~BS_DEFPUSHBUTTON; style |= BS_PUSHBUTTON; SetWindowLong( hCtrl, GWL_STYLE, style ); break; } } } // make the specified button the default style = GetWindowLong( hwdb, GWL_STYLE ); style &= ~(BS_PUSHBUTTON|BS_DEFPUSHBUTTON); style |= BS_DEFPUSHBUTTON; SetWindowLong( hwdb, GWL_STYLE, style ); */ } // setDefaultButton /* * setLabel * * set the label for an axis based on current calibration state */ static void setLabel( LPGLOBALVARS pgv, HWND hwnd, UINT id, LPJOYREGHWCONFIG pcfg, DWORD bit ) { char str[MAX_STR]; int type; HINSTANCE hinst; HWND hwtext; hinst = GetResourceInstance( ); assert(hinst); // get text for this axis label... if( pcfg->dwUsageSettings & JOY_US_ISOEM ) { type = pcfg->dwType - JOY_HW_LASTENTRY; if( type < 0 || type >= pgv->pjd->oemCount ) { type = -1; } } else { type = -1; } switch( id ) { case IDC_JOYLIST1_LABEL: if( (type == -1) || (pgv->pjd->oemList[type].xy_label[0] == 0) ) { NewLoadString( hinst, IDS_XYAXIS_LABEL, str, sizeof( str ) ); if( !lstrlen(str) ) return; } else lstrcpy( str, pgv->pjd->oemList[type].xy_label ); break; case IDC_JOYLIST2_LABEL: if( (type == -1) || (pgv->pjd->oemList[type].z_label[0] == 0 ) ) { NewLoadString( hinst, IDS_ZAXIS_LABEL, str, sizeof( str ) ); if( !lstrlen(str) ) return; } else lstrcpy( str, pgv->pjd->oemList[type].z_label ); break; case IDC_JOYLIST3_LABEL: if( (type == -1) || (pgv->pjd->oemList[type].r_label[0] == 0) ) { NewLoadString( hinst, IDS_RAXIS_LABEL, str, sizeof( str ) ); if( !lstrlen(str) ) return; } else lstrcpy( str, pgv->pjd->oemList[type].r_label ); break; case IDC_JOYLIST4_LABEL: if( (type == -1) || (pgv->pjd->oemList[type].u_label[0] == 0) ) { NewLoadString( hinst, IDS_UAXIS_LABEL, str, sizeof( str ) ); if( !lstrlen(str) ) return; } else lstrcpy( str, pgv->pjd->oemList[type].u_label ); break; case IDC_JOYLIST5_LABEL: if( (type == -1) || (pgv->pjd->oemList[type].v_label[0] == 0) ) { NewLoadString( hinst, IDS_VAXIS_LABEL, str, sizeof( str ) ); if( !lstrlen(str) ) return; } else lstrcpy( str, pgv->pjd->oemList[type].v_label ); break; case IDC_JOYPOV_LABEL: if( (type == -1) || (pgv->pjd->oemList[type].pov_label[0] == 0) ) { NewLoadString( hinst, IDS_POVAXIS_LABEL, str, sizeof( str ) ); if( !lstrlen(str) ) return; } else lstrcpy( str, pgv->pjd->oemList[type].pov_label ); break; } hwtext = GetDlgItem( hwnd, id ); ASSERT (::IsWindow(hwtext)); if( hwtext != NULL ) SetWindowText( hwtext, str ); } /* setLabel */ // enableCalWindows - enable or disable specific calibration windows static void enableCalWindows( LPGLOBALVARS pgv, LPJOYREGHWCONFIG pcfg, HWND hwnd, cal_wins id ) { BOOL on; HWND hwlb; HWND hwb; int iid; // set up the buttons hwb = GetDlgItem( hwnd,IDC_JOYCALDONE ); ASSERT (hwb); if( id == JC_FINI ) { hwlb = GetDlgItem( hwnd, IDC_JOYCALNEXT ); ASSERT (::IsWindow(hwlb)); ShowWindow(hwlb, SW_HIDE ); EnableWindow( hwb, TRUE ); ShowWindow( hwb, SW_NORMAL ); SetFocus( hwb ); setDefaultButton( hwnd, hwb ); } else { hwlb = GetDlgItem( hwnd, IDC_JOYCALNEXT ); ASSERT (::IsWindow(hwlb)); ShowWindow( hwlb, SW_NORMAL ); EnableWindow( hwb, FALSE ); ShowWindow( hwb, SW_HIDE ); } setLabel( pgv, hwnd, IDC_JOYLIST1_LABEL, pcfg, JOY_ISCAL_XY ); // set up the XY window on = FALSE; if( id == JC_XY ) on = TRUE; hwlb = GetDlgItem( hwnd, IDC_JOYLIST1 ); ASSERT (::IsWindow(hwlb)); if( !on ) InvalidateRect( hwlb, NULL, TRUE ); EnableWindow( hwlb, on ); EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST1_LABEL ), on ); /* * set up the Z window */ on = FALSE; if( id == JC_Z ) on = TRUE; hwlb = GetDlgItem( hwnd, IDC_JOYLIST2 ); if( !on ) { InvalidateRect( hwlb, NULL, TRUE ); } EnableWindow( hwlb, on ); EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST2_LABEL ), on ); /* * set up the R window */ on = FALSE; if( id == JC_R ) { on = TRUE; } hwlb = GetDlgItem( hwnd, IDC_JOYLIST3 ); if( !on ) { InvalidateRect( hwlb, NULL, TRUE ); } EnableWindow( hwlb, on ); EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST3_LABEL ), on ); /* * set up the U window */ on = FALSE; if( id == JC_U ) { on = TRUE; } hwlb = GetDlgItem( hwnd, IDC_JOYLIST4 ); if( hwlb != NULL ) { if( !on ) { InvalidateRect( hwlb, NULL, TRUE ); } EnableWindow( hwlb, on ); EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST4_LABEL ), on ); } /* * set up the V window */ on = FALSE; if( id == JC_V ) { on = TRUE; } hwlb = GetDlgItem( hwnd, IDC_JOYLIST5 ); if( hwlb != NULL ) { if( !on ) { InvalidateRect( hwlb, NULL, TRUE ); } EnableWindow( hwlb, on ); EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST5_LABEL ), on ); } /* * set up the POV icon */ on = FALSE; if( id >= JC_POV_UP && id <= JC_POV_LEFT ) { on = TRUE; } EnableWindow( GetDlgItem( hwnd, IDC_JOYPOV_LABEL ), on ); hwb = GetDlgItem( hwnd, IDC_JOYPICKPOV ); EnableWindow( hwb, on ); if( on ) { ShowWindow( hwb, SW_NORMAL ); SetFocus( hwb ); setDefaultButton( hwnd, hwb ); switch( id ) { case JC_POV_UP: iid = IDI_JOYPOV_UP; break; case JC_POV_RIGHT: iid = IDI_JOYPOV_RIGHT; break; case JC_POV_LEFT: iid = IDI_JOYPOV_LEFT; break; case JC_POV_DOWN: iid = IDI_JOYPOV_DOWN; break; } } else { ShowWindow( hwb, SW_HIDE ); UpdateWindow( hwb ); iid = IDI_JOYPOV_GRAYED; } ChangeIcon( hwnd, iid, IDC_JOYPOV ); } /* enableCalWindows */ /* * getJoyName - get the name of a joystick */ static int getJoyName( LPJOYREGHWCONFIG pcfg, BOOL plural ) { int str2id; if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) { str2id = ( plural ) ? IDS_JOYCAL_YOKES : IDS_JOYCAL_YOKE; } else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) { str2id = ( plural ) ? IDS_JOYCAL_CARS : IDS_JOYCAL_CAR; } else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) { str2id = ( plural ) ? IDS_JOYCAL_GAMEPADS : IDS_JOYCAL_GAMEPAD; } else { str2id = ( plural ) ? IDS_JOY2S : IDS_JOY2; } return(str2id); } /* getJoyName */ /* * joyCalStateChange - calibration state change */ static BOOL joyCalStateChange( LPCALVARS pcv, HWND hwnd, BOOL back ) { HINSTANCE hinst; HWND hwtext; int strid; int stridx = 0; // BUG FIX: CML 6/21/96 (FLASH RAID 270) int str2id; int str3id; int str4id; char str[2*MAX_STR]; char buff[2*MAX_STR]; char str2[64]; char str3[64]; char str4[64]; BOOL done; LPJOYREGHWCONFIG pcfg; BOOL rc; int type; LPGLOBALVARS pgv; BOOL isdone; assert(pcv); assert(hwnd); /* * move to the next state: get the appropriate string * to display, and enable the correct controls */ pgv = pcv->pgv; assert(pgv); rc = TRUE; done = FALSE; pcfg = &pgv->joyHWCurr; str2id = -1; str3id = -1; str4id = -1; (pcv->cState) = (cal_states) (pcv->cState + ((cal_states) 1)); EnableWindow( GetDlgItem( hwnd, IDC_JOYCALBACK ), back ); while( !done ) { done = TRUE; switch( pcv->cState ) { case JCS_XY_CENTER1: /* * init. range variables */ pcv->jr.jpMin.dwX = (DWORD) -1; pcv->jr.jpMin.dwY = (DWORD) -1; pcv->jr.jpMin.dwZ = (DWORD) -1; pcv->jr.jpMin.dwR = (DWORD) -1; pcv->jr.jpMin.dwU = (DWORD) -1; pcv->jr.jpMin.dwV = (DWORD) -1; pcv->jr.jpMax.dwX = 0; pcv->jr.jpMax.dwY = 0; pcv->jr.jpMax.dwZ = 0; pcv->jr.jpMax.dwR = 0; pcv->jr.jpMax.dwU = 0; pcv->jr.jpMax.dwV = 0; // set strings to display stridx = CALSTR1; if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) { strid = IDS_JOYCALXY_CENTERYOKE; } else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) { strid = IDS_JOYCALXY_CENTERCAR; } else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) { strid = IDS_JOYCALXY_CENTERGAMEPAD; } else { strid = IDS_JOYCALXY_CENTER; } enableCalWindows( pgv, pcfg, hwnd, JC_XY ); break; case JCS_XY_MOVE: stridx = CALSTR2; if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) { strid = IDS_JOYCALXY_MOVEYOKE; } else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) { strid = IDS_JOYCALXY_MOVECAR; } else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) { strid = IDS_JOYCALXY_MOVEGAMEPAD; } else { strid = IDS_JOYCALXY_MOVE; } break; case JCS_XY_CENTER2: stridx = CALSTR3; if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) { strid = IDS_JOYCALXY_CENTERYOKE2; } else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) { strid = IDS_JOYCALXY_CENTERCAR2; } else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) { strid = IDS_JOYCALXY_CENTERGAMEPAD2; } else { strid = IDS_JOYCALXY_CENTER2; } break; case JCS_Z_MOVE: stridx = CALSTR4; if( !(pcfg->hws.dwFlags & JOY_HWS_HASZ) ) { pcv->cState = JCS_R_MOVE; done = FALSE; } else { enableCalWindows( pgv, pcfg, hwnd, JC_Z ); strid = IDS_JOYCALZ_MOVE; str2id = getJoyName( pcfg, TRUE ); } break; case JCS_Z_PLACEHOLDER: pcv->cState = JCS_R_MOVE; done = FALSE; break; case JCS_R_MOVE: stridx = CALSTR5; if( !(pcfg->hws.dwFlags & JOY_HWS_HASR) && !(pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) { pcv->cState = JCS_U_MOVE; done = FALSE; } else { enableCalWindows( pgv, pcfg, hwnd, JC_R ); strid = IDS_JOYCALRUDDER_MOVE; str2id = getJoyName( pcfg, TRUE ); } break; case JCS_R_PLACEHOLDER: pcv->cState = JCS_U_MOVE; done = FALSE; break; case JCS_U_MOVE: stridx = CALSTR6; if( !(pcfg->hws.dwFlags & JOY_HWS_HASU) ) { pcv->cState = JCS_V_MOVE; done = FALSE; } else { enableCalWindows( pgv, pcfg, hwnd, JC_U ); strid = IDS_JOYCALU_MOVE; str2id = getJoyName( pcfg, TRUE ); } break; case JCS_U_PLACEHOLDER: pcv->cState = JCS_V_MOVE; done = FALSE; break; case JCS_V_MOVE: stridx = CALSTR7; if( !(pcfg->hws.dwFlags & JOY_HWS_HASV) ) { pcv->cState = JCS_POV_MOVEUP; done = FALSE; } else { enableCalWindows( pgv, pcfg, hwnd, JC_V ); strid = IDS_JOYCALV_MOVE; str2id = getJoyName( pcfg, TRUE ); } break; case JCS_V_PLACEHOLDER: pcv->cState = JCS_POV_MOVEUP; done = FALSE; break; case JCS_POV_MOVEUP: stridx = CALSTR8; if( !(pcfg->hws.dwFlags & JOY_HWS_HASPOV) ) { pcv->cState = JCS_FINI; done = FALSE; } else { enableCalWindows( pgv, pcfg, hwnd, JC_POV_UP ); strid = IDS_JOYCALPOV_MOVE; str2id = IDS_JOYCAL_UP; str3id = getJoyName( pcfg, TRUE ); str4id = IDS_JOYCAL_UP; } break; case JCS_POV_MOVERIGHT: stridx = CALSTR9; enableCalWindows( pgv, pcfg, hwnd, JC_POV_RIGHT ); strid = IDS_JOYCALPOV_MOVE; str2id = IDS_JOYCAL_RIGHT; str3id = getJoyName( pcfg, TRUE ); str4id = IDS_JOYCAL_RIGHT; break; case JCS_POV_MOVEDOWN: stridx = CALSTR10; enableCalWindows( pgv, pcfg, hwnd, JC_POV_DOWN ); strid = IDS_JOYCALPOV_MOVE; str2id = IDS_JOYCAL_DOWN; str3id = getJoyName( pcfg, TRUE ); str4id = IDS_JOYCAL_DOWN; break; case JCS_POV_MOVELEFT: stridx = CALSTR11; enableCalWindows( pgv, pcfg, hwnd, JC_POV_LEFT ); strid = IDS_JOYCALPOV_MOVE; str2id = IDS_JOYCAL_LEFT; str3id = getJoyName( pcfg, TRUE ); str4id = IDS_JOYCAL_LEFT; break; case JCS_FINI: /* * see if everything that needs to be calibrated * was actually calibrated */ if( !(pcfg->hwv.dwCalFlags & JOY_ISCAL_XY) ) { isdone = FALSE; } else if( (pcfg->hws.dwFlags & JOY_HWS_HASZ) && !(pcfg->hwv.dwCalFlags & JOY_ISCAL_Z) ) { isdone = FALSE; } else if( ((pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER)) && !(pcfg->hwv.dwCalFlags & JOY_ISCAL_R) ) { isdone = FALSE; } else if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) && !(pcfg->hwv.dwCalFlags & JOY_ISCAL_POV) ) { isdone = FALSE; } else if( (pcfg->hws.dwFlags & JOY_HWS_HASU) && !(pcfg->hwv.dwCalFlags & JOY_ISCAL_U) ) { isdone = FALSE; } else if( (pcfg->hws.dwFlags & JOY_HWS_HASV) && !(pcfg->hwv.dwCalFlags & JOY_ISCAL_V) ) { isdone = FALSE; } else { isdone = TRUE; } strid = ( isdone ) ? IDS_JOYCAL_DONE : IDS_JOYCAL_NOTDONE; str2id = getJoyName( pcfg, FALSE ); str3id = getJoyName( pcfg, TRUE ); stridx = CALSTR12; enableCalWindows( pgv, pcfg, hwnd, JC_FINI ); rc = FALSE; break; } // END OF SWITCH } // END OF WHILE // see if there is any OEM text specified hinst = GetResourceInstance( ); assert(hinst); hwtext = GetDlgItem( hwnd, IDC_JOYCALMSG ); if( pcfg->dwUsageSettings & JOY_US_ISOEM ) { LPJOYDATA pjd; pjd = pgv->pjd; assert(pjd); type = pcfg->dwType - JOY_HW_LASTENTRY; if( pjd->oemList[type].cal_strs[ stridx ][0] != 0 ) { SetWindowText( hwtext, pjd->oemList[type].cal_strs[ stridx] ); return(rc); } } // no OEM text, use the defaults LoadString( hinst, strid, str, sizeof(str)); if( lstrlen(str) ) { if( str2id != -1 ) { NewLoadString( hinst, str2id, str2, sizeof( str2 ) ); if( str2 ) { if( str3id != -1 ) { NewLoadString( hinst, str3id, str3, sizeof( str3 ) ); if( lstrlen(str3) ) { if( str4id != -1 ) { NewLoadString( hinst, str4id, str4, sizeof( str4 ) ); if( lstrlen(str4) ) { // wsprintf( buff, str, str2, str3, str4 ); assert(str2); assert(str3); assert(str4); LPSTR lpargs[] = {str2, str3, str4}; FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, (LPSTR) str, 0, 0, buff, sizeof(buff), lpargs); SetWindowText( hwtext, buff ); } } else { wsprintf( buff, str, str2, str3 ); SetWindowText( hwtext, buff ); } } } else { wsprintf( buff, str, str2, str2 ); SetWindowText( hwtext, buff ); } } } else { SetWindowText( hwtext, str ); } } return(rc); } /* joyCalStateChange */ /* * joyCalStateSkip - skip the current state, move to the next one */ static void joyCalStateSkip( LPCALVARS pcv, HWND hwnd ) { assert(pcv); assert(hwnd); #if 0 /* * if we're calibrating XY, skip to Z */ if( pcv->cState <= JCS_XY_CENTER2 ) { pcv->cState = JCS_XY_CENTER2; /* * if we're calibrating Z, skip to R */ } else if( pcv->cState < JCS_Z_PLACEHOLDER ) { pcv->cState = JCS_Z_PLACEHOLDER; /* * if we're calibrating R, skip to U */ } else if( pcv->cState < JCS_R_PLACEHOLDER ) { pcv->cState = JCS_R_PLACEHOLDER; /* * if we're calibrating U, skip to V */ } else if( pcv->cState < JCS_U_PLACEHOLDER ) { pcv->cState = JCS_U_PLACEHOLDER; /* * if we're calibrating V, skip to POV */ } else if( pcv->cState < JCS_V_PLACEHOLDER ) { pcv->cState = JCS_V_PLACEHOLDER; /* * we must be calibration POV, skip to the end */ } else { pcv->cState = JCS_POV_MOVELEFT; } #endif /* * state changed, reset to the new one */ CauseRedraw( &pcv->ji, FALSE ); joyCalStateChange( pcv, hwnd, TRUE ); } /* joyCalStateSkip */ /* * resetCustomPOVFlags - set POV flags based on original values for custom joystick */ static void resetCustomPOVFlags( LPGLOBALVARS pgv, LPJOYREGHWCONFIG pcfg ) { assert(pgv); assert(pcfg); if( pcfg->dwType == JOY_HW_CUSTOM ) { pcfg->hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS); if( pgv->bOrigPOVIsPoll ) pcfg->hws.dwFlags |= JOY_HWS_POVISPOLL; if( pgv->bOrigPOVIsButtonCombos ) pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS; } } /* resetCustomPOVFlags */ /* * joyCalStateBack - move back to start the previous state */ static void joyCalStateBack( LPCALVARS pcv, HWND hwnd ) { assert(pcv); assert(hwnd); BOOL back; LPJOYREGHWCONFIG pcfg; LPGLOBALVARS pgv; pgv = pcv->pgv; assert(pgv); back = TRUE; pcfg = &pgv->joyHWCurr; assert(pcfg); /* * at the end, backup */ if( pcv->cState == JCS_FINI ) { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALBACK)); // END ADD /* * if there is POV, back up to it */ if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) { pcv->cState = JCS_V_PLACEHOLDER; resetCustomPOVFlags( pgv, pcfg ); /* * if there is V, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASV ) { pcv->cState = JCS_U_PLACEHOLDER; /* * if there is U, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASU ) { pcv->cState = JCS_R_PLACEHOLDER; /* * if there is R, back up to it */ } else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) { pcv->cState = JCS_Z_PLACEHOLDER; /* * if there is Z, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) { pcv->cState = JCS_XY_CENTER2; /* * no where else to go, back up to XY */ } else { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT)); // END ADD // pcv->cState = JCS_INIT; pcv->cState = JCS_XY_MOVE; // back = FALSE; } /* * doing POV, so restart it */ } else if( pcv->cState > JCS_POV_MOVEUP ) { pcv->cState = JCS_V_PLACEHOLDER; // pcfg->hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS); resetCustomPOVFlags( pgv, pcfg ); /* * just starting POV, back up */ } else if( pcv->cState == JCS_POV_MOVEUP ) { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALBACK)); // END ADD /* * if there is V, back up to it */ if( pcfg->hws.dwFlags & JOY_HWS_HASV ) { pcv->cState = JCS_U_PLACEHOLDER; /* * if there is U, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASU ) { pcv->cState = JCS_R_PLACEHOLDER; /* * if there is R, back up to it */ } else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) { pcv->cState = JCS_Z_PLACEHOLDER; /* * if there is Z, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) { pcv->cState = JCS_XY_CENTER2; /* * no where else to go, back up to XY */ } else { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT)); // END ADD // pcv->cState = JCS_INIT; pcv->cState = JCS_XY_MOVE; // back = FALSE; } /* * doing V, backup */ } else if( pcv->cState == JCS_V_MOVE ) { /* * if there is U, back up to it */ if( pcfg->hws.dwFlags & JOY_HWS_HASU ) { pcv->cState = JCS_R_PLACEHOLDER; /* * if there is R, back up to it */ } else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) { pcv->cState = JCS_Z_PLACEHOLDER; /* * if there is Z, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) { pcv->cState = JCS_XY_CENTER2; /* * no where else to go, back up to XY */ } else { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT)); // END ADD // pcv->cState = JCS_INIT; pcv->cState = JCS_XY_MOVE; // back = FALSE; } /* * doing U, backup */ } else if( pcv->cState == JCS_U_MOVE ) { /* * if there is R, back up to it */ if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) { pcv->cState = JCS_Z_PLACEHOLDER; /* * if there is Z, back up to it */ } else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) { pcv->cState = JCS_XY_CENTER2; /* * no where else to go, back up to XY */ } else { // pcv->cState = JCS_INIT; pcv->cState = JCS_XY_MOVE; // back = FALSE; } /* * doing R, backup */ } else if( pcv->cState == JCS_R_MOVE ) { /* * if there is Z, back up to it */ if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) { pcv->cState = JCS_XY_CENTER2; /* * no where else to go, back up to XY */ } else { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT)); // END ADD // pcv->cState = JCS_INIT; pcv->cState = JCS_XY_MOVE; // back = FALSE; } /* * if we're doing Z or in the middle of XY, backup to XY */ } else if( pcv->cState == JCS_XY_MOVE ) { SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT)); pcv->cState = JCS_INIT; back = FALSE; } else { // ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167) SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT)); // END ADD pcv->cState = (cal_states)(pcv->cState - 2); // pcv->cState = JCS_INIT; // back = FALSE; } /* * state changed, reset to the new one */ CauseRedraw( &pcv->ji, FALSE ); joyCalStateChange( pcv, hwnd, back ); } /* joyCalStateBack */ // macro to get new max/min data for an axis #define NEWMINMAX( a ) \ if( pji->dw##a##pos > pcv->jr.jpMax.dw##a ) { \ pcv->jr.jpMax.dw##a = pji->dw##a##pos; \ } \ if( pji->dw##a##pos < pcv->jr.jpMin.dw##a ) { \ pcv->jr.jpMin.dw##a = pji->dw##a##pos; \ } \ pji->dw##a##pos *= RAW_SHIFT; // joyCollectCalInfo - record calibration info static BOOL joyCollectCalInfo( LPCALVARS pcv, HWND hwnd, LPJOYINFOEX pji ) { assert(pcv); assert(hwnd); assert(pji); LPGLOBALVARS pgv; LPJOYREGHWCONFIG pcfg; pgv = pcv->pgv; assert(pgv); switch( pcv->cState ) { // remember XY center case JCS_XY_CENTER1: case JCS_XY_CENTER2: #ifdef _DEBUG TRACE("%s: %d: dwXpos is %d dwYpos is %d\n", __FILE__, __LINE__, pji->dwXpos, pji->dwYpos); #endif // _DEBUG if( !pcv->jr.jpCenter.dwY ) { pgv->joyRange.jpMax.dwY = pji->dwYpos << 1; pcv->jr.jpCenter.dwY = pji->dwYpos; } if( !pcv->jr.jpCenter.dwX ) { pgv->joyRange.jpMax.dwX = pji->dwXpos << 1; pcv->jr.jpCenter.dwX = pji->dwXpos; } pgv->joyRange.jpMin.dwX = 0; pgv->joyRange.jpMin.dwY = 0; DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWXY ); break; // remember max/min XY values case JCS_XY_MOVE: if( pji->dwXpos > pcv->jr.jpMax.dwX ) { pcv->jr.jpMax.dwX = pji->dwXpos; } if( pji->dwXpos < pcv->jr.jpMin.dwX ) { pcv->jr.jpMin.dwX = pji->dwXpos; } if( pji->dwYpos > pcv->jr.jpMax.dwY ) { pcv->jr.jpMax.dwY = pji->dwYpos; } if( pji->dwYpos < pcv->jr.jpMin.dwY ) { pcv->jr.jpMin.dwY = pji->dwYpos; } DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWXY ); break; // remember max/min Z value case JCS_Z_MOVE: NEWMINMAX( Z ); DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWZ ); break; // remember max/min R value case JCS_R_MOVE: NEWMINMAX( R ); DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWR ); break; // remember max/min U value case JCS_U_MOVE: NEWMINMAX( U ); DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWU ); break; // remember max/min V value case JCS_V_MOVE: NEWMINMAX( V ); DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWV ); break; } // if a button was pressed, move to the next state if( ((pcv->ji.dwButtons & ALL_BUTTONS) != (pji->dwButtons & ALL_BUTTONS)) && ((pji->dwButtons & JOY_BUTTON1) || (pji->dwButtons & JOY_BUTTON2) || (pji->dwButtons & JOY_BUTTON3) || (pji->dwButtons & JOY_BUTTON4) || (pji->dwButtons & JOY_BUTTON5) || (pji->dwButtons & JOY_BUTTON6) || (pji->dwButtons & JOY_BUTTON7) || (pji->dwButtons & JOY_BUTTON8) || (pji->dwButtons & JOY_BUTTON9) || (pji->dwButtons & JOY_BUTTON10) || (pji->dwButtons & JOY_BUTTON11) || (pji->dwButtons & JOY_BUTTON12) || (pji->dwButtons & JOY_BUTTON13) || (pji->dwButtons & JOY_BUTTON14) || (pji->dwButtons & JOY_BUTTON15) || (pji->dwButtons & JOY_BUTTON16) || (pji->dwButtons & JOY_BUTTON17) || (pji->dwButtons & JOY_BUTTON18) || (pji->dwButtons & JOY_BUTTON19) || (pji->dwButtons & JOY_BUTTON20) || (pji->dwButtons & JOY_BUTTON21) || (pji->dwButtons & JOY_BUTTON22) || (pji->dwButtons & JOY_BUTTON23) || (pji->dwButtons & JOY_BUTTON24) || (pji->dwButtons & JOY_BUTTON25) || (pji->dwButtons & JOY_BUTTON26) || (pji->dwButtons & JOY_BUTTON27) || (pji->dwButtons & JOY_BUTTON28) || (pji->dwButtons & JOY_BUTTON29) || (pji->dwButtons & JOY_BUTTON30) || (pji->dwButtons & JOY_BUTTON31) || (pji->dwButtons & JOY_BUTTON32) ) ) { // check and see if we are leaving one calibration to the next; // if yes, take time to stop and remember what the user just did pcfg = &pgv->joyHWCurr; assert(pcfg); switch( pcv->cState ) { case JCS_XY_CENTER1: pcv->jr.jpCenter.dwX = pji->dwXpos; pcv->jr.jpCenter.dwY = pji->dwYpos; DPF( "Center 1: %d,%d\r\n", pji->dwXpos, pji->dwYpos ); break; case JCS_XY_CENTER2: DPF( "Center 2: %d,%d\r\n", pji->dwXpos, pji->dwYpos ); pcv->jr.jpCenter.dwX += pji->dwXpos; pcv->jr.jpCenter.dwY += pji->dwYpos; pcv->jr.jpCenter.dwX /= 2; pcv->jr.jpCenter.dwY /= 2; DPF( "Center Avg: %d,%d\r\n", pcv->jr.jpCenter.dwX, pcv->jr.jpCenter.dwY ); pcfg->hwv.jrvHardware.jpMin.dwX = pcv->jr.jpMin.dwX; pcfg->hwv.jrvHardware.jpMin.dwY = pcv->jr.jpMin.dwY; pcfg->hwv.jrvHardware.jpMax.dwX = pcv->jr.jpMax.dwX; pcfg->hwv.jrvHardware.jpMax.dwY = pcv->jr.jpMax.dwY; pcfg->hwv.jrvHardware.jpCenter.dwX = pcv->jr.jpCenter.dwX; pcfg->hwv.jrvHardware.jpCenter.dwY = pcv->jr.jpCenter.dwY; pcfg->hwv.dwCalFlags |= JOY_ISCAL_XY; break; case JCS_Z_MOVE: pcfg->hwv.jrvHardware.jpMin.dwZ = pcv->jr.jpMin.dwZ; pcfg->hwv.jrvHardware.jpMax.dwZ = pcv->jr.jpMax.dwZ; pcfg->hwv.dwCalFlags |= JOY_ISCAL_Z; break; case JCS_R_MOVE: pcfg->hwv.jrvHardware.jpMin.dwR = pcv->jr.jpMin.dwR; pcfg->hwv.jrvHardware.jpMax.dwR = pcv->jr.jpMax.dwR; pcfg->hwv.dwCalFlags |= JOY_ISCAL_R; break; case JCS_U_MOVE: pcfg->hwv.jrvHardware.jpMin.dwU = pcv->jr.jpMin.dwU; pcfg->hwv.jrvHardware.jpMax.dwU = pcv->jr.jpMax.dwU; pcfg->hwv.dwCalFlags |= JOY_ISCAL_U; break; case JCS_V_MOVE: pcfg->hwv.jrvHardware.jpMin.dwV = pcv->jr.jpMin.dwV; pcfg->hwv.jrvHardware.jpMax.dwV = pcv->jr.jpMax.dwV; pcfg->hwv.dwCalFlags |= JOY_ISCAL_V; break; } pcv->ji.dwButtons = pji->dwButtons; return(joyCalStateChange( pcv, hwnd, TRUE )); } pcv->ji.dwButtons = pji->dwButtons; return(TRUE); } /* joyCollectCalInfo */ /* * joyCalibrateInitDialog - init the calibration dialog */ static BOOL joyCalibrateInitDialog( HWND hwnd, LPARAM lParam ) { LPJOYREGHWCONFIG pcfg; LPCALVARS pcv = NULL; LPGLOBALVARS pgv = NULL; ASSERT (::IsWindow(hwnd)); // set up calibration variables pcv = (CALVARS *) DoAlloc( sizeof( CALVARS ) ); ASSERT(pcv); if( pcv == NULL ) return(FALSE); SetWindowLong( hwnd, DWL_USER, (LONG) pcv ); assert(pcv); pgv = (LPGLOBALVARS) lParam; assert(pgv); pcv->pgv = pgv; // // set labels // LPSTR psz1 = new char[MAX_STR_LEN]; ASSERT (psz1); LPSTR psz2 = new char[MAX_STR_LEN]; ASSERT (psz2); if( !LoadString(GetResourceInstance(), IDS_JOYCALCAPN, psz1, MAX_STR_LEN) ) { TRACE( "%s: %s - LoadString Failure!\n", __FILE__, __LINE__); } wsprintf(psz2, psz1, pgv->iJoyId+1); SetWindowText(hwnd, psz2); if( psz1 ) delete[] (psz1); if( psz2 ) delete[] (psz2); // init state info pcv->cState = JCS_INIT; // set dialog text based on OEM strings SetOEMText( pgv, hwnd, FALSE ); // customize dialog based on Z axis, R axis, and POV hat pcfg = &pgv->joyHWCurr; assert(pcfg); pcv->iAxisCount = 2; if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) pcv->iAxisCount++; if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) pcv->iAxisCount++; if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) && (pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) ) pcv->iAxisCount++; if( pcfg->hws.dwFlags & JOY_HWS_HASU ) pcv->iAxisCount++; if( pcfg->hws.dwFlags & JOY_HWS_HASV ) pcv->iAxisCount++; ShowControls( pcfg, hwnd ); HWND hCtrl = GetDlgItem( hwnd, IDC_JOYPOV_LABEL ); ASSERT (::IsWindow(hCtrl)); ShowWindow(hCtrl, pcfg->hws.dwFlags & JOY_HWS_HASPOV ? SW_SHOW : SW_HIDE); // if all axes are used and we have POV then it MUST be buttons if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) { if( pgv->dwMaxAxes == 4 && pcv->iAxisCount == 4 ) pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS; } // other misc setup pcv->bPOVdone = FALSE; pcv->bHasTimer = SetTimer( hwnd, TIMER_ID, JOYPOLLTIME, NULL ); pcv->bUseTimer = TRUE; if( !pcv->bHasTimer ) { DPF( "No timer for joystick calibration!\r\n" ); return(FALSE); } if( !joyCalStateChange( pcv, hwnd, FALSE ) ) { DPF( "Could not initialize joystick calibration\r\n" ); return(FALSE); } return(TRUE); } /* joyCalibrateInitDialog */ /* * setJIFlagsForPOV - get joyinfo flags to allow a raw POV poll */ static void setJIFlagsForPOV( LPCALVARS pcv, LPJOYREGHWCONFIG pcfg, DWORD *pflags ) { /* * for polled POV, we need to specifiy JOY_CAL_READ(3|4) to make * the driver give us position values back instead of trying to * give us a POV value back */ // if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) { if( pcfg->hws.dwFlags & JOY_HWS_POVISPOLL ) { switch( pcv->iAxisCount ) { case 6: (*pflags) |= JOY_CAL_READ6; break; case 5: (*pflags) |= JOY_CAL_READ5; break; case 4: (*pflags) |= JOY_CAL_READ4; break; case 3: (*pflags) |= JOY_CAL_READ3; break; } // If we don't have a 3rd or 4th axis on this joystick, try reading // another axis anyway to see if the POV hat is on it } else if( !(pcfg->hws.dwFlags & (JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS)) ) { switch( pcv->iAxisCount ) { case 5: (*pflags) |= JOY_CAL_READ6; break; case 4: (*pflags) |= JOY_CAL_READ5; break; case 3: (*pflags) |= JOY_CAL_READ4; break; case 2: (*pflags) |= JOY_CAL_READ3; break; } } } } /* setJIFlagsForPOV */ // tryPOV - try for a POV access static BOOL tryPOV( LPCALVARS pcv, HWND hwnd ) { assert(pcv); assert(hwnd); int rc; BOOL ispoll; BOOL isb; BOOL nowaypoll; JOYINFOEX ji; DWORD val; LPJOYREGHWCONFIG pcfg; LPGLOBALVARS pgv; int i; pgv = pcv->pgv; assert(pgv); // reject call if not in a POV state if( !(pcv->cState == JCS_POV_MOVEUP || pcv->cState == JCS_POV_MOVEDOWN || pcv->cState == JCS_POV_MOVELEFT || pcv->cState == JCS_POV_MOVERIGHT) ) return(FALSE); // take a snapshot of the current joystick state pcfg = &pgv->joyHWCurr; assert(pcfg); nowaypoll = FALSE; ji.dwSize = sizeof( ji ); while( 1 ) { // get joystick info ji.dwFlags = JOY_CALIB_FLAGS; // if you have a POV, set the flags for it! if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) setJIFlagsForPOV( pcv, pcfg, &ji.dwFlags ); rc = joyGetPosEx( pgv->iJoyId, &ji ); if( rc == JOYERR_NOERROR ) break; if( !(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) && (ji.dwFlags & (JOY_CAL_READ3|JOY_CAL_READ4|JOY_CAL_READ5|JOY_CAL_READ6)) ) { // try again, but don't ask for extra axis ji.dwFlags &= ~(JOY_CAL_READ6 | JOY_CAL_READ5 | JOY_CAL_READ4 | JOY_CAL_READ3); rc = joyGetPosEx( pgv->iJoyId, &ji ); if( rc == JOYERR_NOERROR ) { nowaypoll = TRUE; // pov can't possibly be polled break; } else return(JoyError( hwnd )) ? TRUE : FALSE; // have to wait for next "Select POV" to retry } else return(JoyError( hwnd )) ? TRUE : FALSE; // have to wait for next "Select POV" to retry } /* * here is where we determine if POV is polled or is button combos. * * See if we already know the answer (bits in joyHWCurr): * if yes: * we're done. * if no: * We see if there are currently multiple buttons down. * if yes: * POV is assumed to be button combos. * if no: * POV is assumed to be done with polling */ ispoll = FALSE; isb = FALSE; if( pcfg->hws.dwFlags & JOY_HWS_POVISPOLL ) { ispoll = TRUE; } else if( pcfg->hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS ) { isb = TRUE; } if( !isb && !ispoll ) { // the type is indeterminate, so we identify it if( nowaypoll ||((ji.dwButtons != 0) && (ji.dwButtons != JOY_BUTTON1) && (ji.dwButtons != JOY_BUTTON2) && (ji.dwButtons != JOY_BUTTON3) && (ji.dwButtons != JOY_BUTTON4) && (ji.dwButtons != JOY_BUTTON5) && (ji.dwButtons != JOY_BUTTON6) && (ji.dwButtons != JOY_BUTTON7) && (ji.dwButtons != JOY_BUTTON8) && (ji.dwButtons != JOY_BUTTON9) && (ji.dwButtons != JOY_BUTTON10) && (ji.dwButtons != JOY_BUTTON11) && (ji.dwButtons != JOY_BUTTON12) && (ji.dwButtons != JOY_BUTTON13) && (ji.dwButtons != JOY_BUTTON14) && (ji.dwButtons != JOY_BUTTON15) && (ji.dwButtons != JOY_BUTTON16) && (ji.dwButtons != JOY_BUTTON17) && (ji.dwButtons != JOY_BUTTON18) && (ji.dwButtons != JOY_BUTTON19) && (ji.dwButtons != JOY_BUTTON20) && (ji.dwButtons != JOY_BUTTON21) && (ji.dwButtons != JOY_BUTTON22) && (ji.dwButtons != JOY_BUTTON23) && (ji.dwButtons != JOY_BUTTON24) && (ji.dwButtons != JOY_BUTTON25) && (ji.dwButtons != JOY_BUTTON26) && (ji.dwButtons != JOY_BUTTON27) && (ji.dwButtons != JOY_BUTTON28) && (ji.dwButtons != JOY_BUTTON29) && (ji.dwButtons != JOY_BUTTON30) && (ji.dwButtons != JOY_BUTTON31) && (ji.dwButtons != JOY_BUTTON32) ) ) { isb = TRUE; pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS; } else { // we always assume J2 Y for a polling POV if unspecified ispoll = TRUE; pcfg->hws.dwFlags |= JOY_HWS_POVISPOLL; } // the driver needs to notified that we've made this decision RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv ); } // record the data value for this POV reading if( isb ) val = ji.dwButtons; else val = (pcfg->hws.dwFlags & JOY_HWS_HASZ) ? ji.dwRpos : ji.dwZpos; switch( pcv->cState ) { case JCS_POV_MOVEUP: pcv->pov[JOY_POVVAL_FORWARD] = val; break; case JCS_POV_MOVERIGHT: pcv->pov[JOY_POVVAL_RIGHT] = val; break; case JCS_POV_MOVEDOWN: pcv->pov[JOY_POVVAL_BACKWARD] = val; break; case JCS_POV_MOVELEFT: pcv->pov[JOY_POVVAL_LEFT] = val; // since this was the last POV thing to calibrate, we need to save the calibration info for( i=0;ihwv.dwPOVValues[i] = pcv->pov[i]; pcfg->hwv.dwCalFlags |= JOY_ISCAL_POV; pcv->bPOVdone = TRUE; break; } return(joyCalStateChange( pcv, hwnd, TRUE )); } /* tryPOV */ #ifdef DEAD_CODE // FixCustomPOVType - fix custom POV type info if POV wasn't calibrated; called by test dlg to update config void FixCustomPOVType( LPCALVARS pcv ) { assert(pcv); if( !pcv->bPOVdone ) resetCustomPOVFlags( pcv->pgv, &pcv->pgv->joyHWCurr ); } /* FixCustomPOVType */ #endif // DEAD_CODE // CalibrateProc - calibrate a joystick BOOL CALLBACK CalibrateProc( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) { switch( umsg ) { case WM_CONTEXTMENU: OnContextMenu(wParam); return(1); case WM_HELP: OnHelp(lParam); return(1); case WM_TIMER: { LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER ); assert(pcv); if( pcv->bUseTimer ) { JOYINFOEX *ji = new JOYINFOEX; ASSERT (ji); MMRESULT rc; LPJOYREGHWCONFIG pcfg; LPGLOBALVARS pgv; pgv = pcv->pgv; assert(pgv); pcv->bUseTimer = FALSE; ji->dwSize = sizeof( JOYINFOEX ); while( 1 ) { // get current joystick info ji->dwFlags = JOY_CALIB_FLAGS; pcfg = &pgv->joyHWCurr; ASSERT(pcfg); // if there is a POV, set the flags for it! if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) setJIFlagsForPOV( pcv, pcfg, &ji->dwFlags ); rc = joyGetPosEx( pgv->iJoyId, ji ); if( rc == JOYERR_NOERROR ) break; // didn't work, try without extra POV axis if( !(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) && (ji->dwFlags & (JOY_CAL_READ3|JOY_CAL_READ4|JOY_CAL_READ5|JOY_CAL_READ6)) ) { ji->dwFlags &= ~(JOY_CAL_READ6 | JOY_CAL_READ5 | JOY_CAL_READ4 | JOY_CAL_READ3); rc = joyGetPosEx( pgv->iJoyId, ji ); if( rc == JOYERR_NOERROR ) break; } if( !JoyError( hwnd ) ) { // return now if cancel selected; don't turn back on the timer PostMessage(hwnd, WM_COMMAND, IDCANCEL, 0); // ADDED CML 7/05/96 return(FALSE); } continue; } // how could you get here and rc != JOYERR_NOERROR? if( rc == JOYERR_NOERROR ) joyCollectCalInfo( pcv, hwnd, ji ); if( ji ) delete (ji); /* * If we've started POV calibration, we need to look at the * keyboard and ignore joystick, so don't turn the timer * back on if we've started the POV calibration */ if( pcv->cState < JCS_POV_MOVEUP ) pcv->bUseTimer = TRUE; } break; } case WM_DESTROY: { LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER ); assert(pcv); DoFree( pcv ); break; } case WM_INITDIALOG: if( !joyCalibrateInitDialog( hwnd, lParam ) ) { LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER ); assert(pcv); if( pcv != NULL && pcv->bHasTimer ) { KillTimer( hwnd, TIMER_ID ); pcv->bHasTimer = FALSE; } EndDialog( hwnd, 0 ); } return(FALSE); case WM_PAINT: { LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER ); assert(pcv); CauseRedraw( &pcv->ji, FALSE ); return(FALSE); } case WM_COMMAND: { LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER ); assert(pcv); int id = GET_WM_COMMAND_ID(wParam, lParam); switch( id ) { #ifdef DEAD_CODE case IDC_JOYTEST: { BOOL timeon; timeon = pcv->bUseTimer; pcv->bUseTimer = FALSE; DoTest( pcv->pgv, hwnd, (void (__cdecl *)(void *)) FixCustomPOVType, pcv ); pcv->bUseTimer = timeon; break; } #endif //DEAD_CODE case IDCANCEL: // fall through case IDC_JOYCALDONE: if( pcv->bHasTimer ) { KillTimer( hwnd, TIMER_ID ); pcv->bHasTimer = FALSE; } // { // LPJOYREGHWCONFIG pcfg = &pcv->pgv->joyHWCurr; // assert(pcfg); // } EndDialog( hwnd, (id == IDC_JOYCALDONE) ); break; case IDC_JOYPICKPOV: if( !tryPOV( pcv, hwnd ) ) { ASSERT (::IsWindow(hwnd)); HWND hwb = GetDlgItem( hwnd, IDC_JOYPICKPOV ); ASSERT (::IsWindow(hwb)); ShowWindow( hwb, SW_HIDE ); EnableWindow( hwb, FALSE ); } break; case IDC_JOYCALNEXT: pcv->bUseTimer = TRUE; joyCalStateSkip( pcv, hwnd ); break; case IDC_JOYCALBACK: pcv->bUseTimer = TRUE; joyCalStateBack( pcv, hwnd ); break; default: break; } break; } default: break; } return(FALSE); } // CalibrateProc // DoCalibrate - do the calibration dialog void DoCalibrate( LPGLOBALVARS pgv, HWND hwnd ) { assert(pgv); JOYREGHWCONFIG save_joycfg; int rc; int id; // save the current config, and then add the rudder if it is present save_joycfg = pgv->joyHWCurr; // if this is a custom joystick, then don't assume anything // about how the POV is set up if( pgv->joyHWCurr.dwType == JOY_HW_CUSTOM ) { pgv->bOrigPOVIsPoll = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_POVISPOLL); pgv->bOrigPOVIsButtonCombos = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS); pgv->joyHWCurr.hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS); } // update the registry with our new joystick info RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv ); // Fix for 8738, missing IDD_JOYCALIBRATE1 in resource table! id = ( pgv->joyHWCurr.hws.dwFlags & (JOY_HWS_HASU|JOY_HWS_HASV)) ? IDD_JOYCALIBRATE1 : IDD_CAL; rc = DialogBoxParam(GetResourceInstance(), MAKEINTRESOURCE( id ), hwnd, (int (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)) CalibrateProc, (LONG) pgv ); // update the registry with the new info or the old info if( rc ) PropSheet_Changed( GetParent(hwnd), hwnd ); else pgv->joyHWCurr = save_joycfg; RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv ); } /* DoCalibrate */ //////////////////////////////////////////////////////////////////////////////////////// // OnContextMenu(WPARAM wParam) //////////////////////////////////////////////////////////////////////////////////////// void OnContextMenu(WPARAM wParam) { short nSize = STR_LEN_32; // point to help file char *pszHelpFileName = new char[nSize]; ASSERT (pszHelpFileName); // returns help file name and size of string GetHelpFileName(pszHelpFileName, &nSize); WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (DWORD)CalibrateHelpIDs); if( pszHelpFileName ) delete[] (pszHelpFileName); } //////////////////////////////////////////////////////////////////////////////////////// // OnHelp(LPARAM lParam) //////////////////////////////////////////////////////////////////////////////////////// void OnHelp(LPARAM lParam) { short nSize = STR_LEN_32; // point to help file char *pszHelpFileName = new char[nSize]; ASSERT (pszHelpFileName); // returns help file name and size of string GetHelpFileName(pszHelpFileName, &nSize); LPHELPINFO lphi = (LPHELPINFO)lParam; if( lphi->iContextType==HELPINFO_WINDOW ) WinHelp((HWND)lphi->hItemHandle, pszHelpFileName, HELP_WM_HELP, (DWORD)CalibrateHelpIDs); if( pszHelpFileName ) delete[] (pszHelpFileName); }