/***************************************************************************** * * diqmain.c * * The main dialog box. * *****************************************************************************/ #include "diquick.h" GUID GUID_Uninit = { 1 }; DWORD g_dwEnumType; DWORD g_dwEnumFlags; /***************************************************************************** * * Dialog instance data * * Instance data for main dialog box. * *****************************************************************************/ typedef struct MAINDLGINFO { HWND hwndDevices; /* Devices combo box */ UINT cBusy; /* Number of threads starting */ UINT cDevs; /* Number of devices created */ IDirectInput *pdi; /* Cached interface */ BOOL fW; /* Is pdi a pdiW? (else, pdiA) */ DARY daryDevs; /* Device info lives here */ } MAINDLGINFO, *PMAINDLGINFO; /***************************************************************************** * * Diq_DeviceEnumProc * * Device enumeration procedure which is called one for each device. * * Add the item to our dialog instance data and to the combo box. * *****************************************************************************/ BOOL INTERNAL Diq_DeviceEnumProc(PCV pvDi, LPVOID pv) { PMAINDLGINFO pmdi = pv; DIDEVICEINSTANCE didi; TCHAR tsz[1024]; int ich; if (pmdi->fW) { LPCDIDEVICEINSTANCEW pdiW = pvDi; didi.guidInstance = pdiW->guidInstance; didi.guidProduct = pdiW->guidProduct; didi.dwDevType = pdiW->dwDevType; ConvertString(pmdi->fW, pdiW->tszProductName, didi.tszProductName, cA(didi.tszProductName)); ConvertString(pmdi->fW, pdiW->tszInstanceName, didi.tszInstanceName, cA(didi.tszInstanceName)); } else { LPCDIDEVICEINSTANCEA pdiA = pvDi; didi.guidInstance = pdiA->guidInstance; didi.guidProduct = pdiA->guidProduct; didi.dwDevType = pdiA->dwDevType; ConvertString(pmdi->fW, pdiA->tszProductName, didi.tszProductName, cA(didi.tszProductName)); ConvertString(pmdi->fW, pdiA->tszInstanceName, didi.tszInstanceName, cA(didi.tszInstanceName)); } ich = wsprintf(tsz, TEXT("%s (%s)"), didi.tszInstanceName, didi.tszProductName); if (didi.dwDevType & DIDEVTYPE_HID) { LoadString(g_hinst, IDS_SPACEPARENHID, &tsz[ich], 10); } ComboBox_AddString(pmdi->hwndDevices, tsz); Dary_Append(&pmdi->daryDevs, &didi); return DIENUM_CONTINUE; } /***************************************************************************** * * Diq_EnumDevices * * Rebuild the list of enumerated devices. Try to preserve the * current selection index. * *****************************************************************************/ void INTERNAL Diq_EnumDevices(PMAINDLGINFO pmdi) { HRESULT hres; int iSel = ComboBox_GetCurSel(pmdi->hwndDevices); HCURSOR hcurPrev = GetCursor(); SetCursor(LoadCursor(NULL, IDC_WAIT)); Dary_Term(&pmdi->daryDevs); ZeroX(pmdi->daryDevs); ComboBox_ResetContent(pmdi->hwndDevices); #if defined(_DEBUG) || defined(DEBUG) { /* * Create the intentionally invalid device. */ DIDEVICEINSTANCE didi; ComboBox_AddString(pmdi->hwndDevices, g_tszInvalid); ZeroX(didi); Dary_Append(&pmdi->daryDevs, &didi); ComboBox_AddString(pmdi->hwndDevices, ""); ZeroX(didi); didi.guidInstance = GUID_Uninit; lstrcpyn(didi.tszInstanceName, "", cA(didi.tszInstanceName)); Dary_Append(&pmdi->daryDevs, &didi); } #endif pmdi->fW = 1; hres = DirectInput8Create(g_hinst, g_dwDIVer, &IID_IDirectInput8W, (PVOID)&pmdi->pdi, 0); /* For each object, add it to the menu */ if (SUCCEEDED(hres)) { IDirectInput_EnumDevices(pmdi->pdi, g_dwEnumType, Diq_DeviceEnumProc, pmdi, g_dwEnumFlags); IDirectInput_Release(pmdi->pdi); pmdi->pdi = 0; } ComboBox_SetCurSel(pmdi->hwndDevices, max(iSel, 0)); SetCursor(hcurPrev); } /***************************************************************************** * * Diq_OnInitDialog * * Populate the combo box with the list of devices. * *****************************************************************************/ BOOL INTERNAL Diq_OnInitDialog(HWND hdlg) { PMAINDLGINFO pmdi; Diq_HackPropertySheets(hdlg); pmdi = LocalAlloc(LPTR, cbX(MAINDLGINFO)); if ( !pmdi ) { return 0; } SetDialogPtr(hdlg, pmdi); pmdi->hwndDevices = GetDlgItem(hdlg, IDC_MAIN_DEVICES); Diq_EnumDevices(pmdi); CheckRadioButton(hdlg, IDC_MAIN_OLE, IDC_MAIN_DI, IDC_MAIN_DI); CheckRadioButton(hdlg, IDC_MAIN_DIA, IDC_MAIN_DIW, IDC_MAIN_DIW); CheckRadioButton(hdlg, IDC_MAIN_DIDA, IDC_MAIN_ITFMAC, IDC_MAIN_DIDW); if (g_dwDIVer <= 0x0300) { //EnableWindow(GetDlgItem(hdlg, IDC_MAIN_DID2A), FALSE); //EnableWindow(GetDlgItem(hdlg, IDC_MAIN_DID2W), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MAIN_DIDJC), FALSE); } return 1; } /***************************************************************************** * * Diq_OnDestroy * * Clean up. * *****************************************************************************/ BOOL INTERNAL Diq_OnDestroy(PMAINDLGINFO pmdi, HWND hdlg) { if (pmdi) { Dary_Term(&pmdi->daryDevs); LocalFree(pmdi); } return 1; } /***************************************************************************** * * Diq_RecalcClose * * Enable or disable the SC_CLOSE option accordingly. * *****************************************************************************/ void INTERNAL Diq_RecalcClose(PMAINDLGINFO pmdi, HWND hdlg) { EnableMenuItem(GetSystemMenu(hdlg, 0), SC_CLOSE, MF_BYCOMMAND | (pmdi->cDevs ? MF_DISABLED | MF_GRAYED : MF_ENABLED)); } /***************************************************************************** * * Diq_OnGetStatus * * Somebody asked for the status of the device. * *****************************************************************************/ BOOL INTERNAL Diq_OnGetStatus(HWND hdlg) { PMAINDLGINFO pmdi = GetDialogPtr(hdlg); int iSel = ComboBox_GetCurSel(pmdi->hwndDevices); if ((UINT)iSel < (UINT)pmdi->daryDevs.cx) { LPDIRECTINPUTA pdia; HRESULT hres; UINT didc; int ids; didc = GetCheckedRadioButton(hdlg, IDC_MAIN_ITF, IDC_MAIN_ITFMAC) - IDC_MAIN_ITF; hres = CreateDI(IsDlgButtonChecked(hdlg, IDC_MAIN_OLE), IsUnicodeDidc(didc), (PPV)&pdia); if (SUCCEEDED(hres)) { LPDIDEVICEINSTANCE pdidi; pdidi = Dary_GetPtr(&pmdi->daryDevs, iSel, DIDEVICEINSTANCE); hres = IDirectInput_GetDeviceStatus(pdia, &pdidi->guidInstance); switch (hres) { case DI_OK: ids = IDS_GETSTAT_OK; break; case DI_NOTATTACHED: ids = IDS_GETSTAT_NOTATTACHED; break; default: ids = IDS_GETSTAT_ERROR; break; } } else { ids = IDS_GETSTAT_ERROR; } MessageBoxV(hdlg, ids, hres); } return 1; } /***************************************************************************** * * Diq_OnCreateObject * * Somebody asked us to create an object. Party! * *****************************************************************************/ BOOL INTERNAL Diq_OnCreateObject(HWND hdlg) { PMAINDLGINFO pmdi = GetDialogPtr(hdlg); int iSel = ComboBox_GetCurSel(pmdi->hwndDevices); //#ifdef DEBUG if (IsDlgButtonChecked(hdlg, IDC_MAIN_DIDJC)) { if (Cpl_Create(hdlg, IsDlgButtonChecked(hdlg, IDC_MAIN_OLE), IsDlgButtonChecked(hdlg, IDC_MAIN_DIW))) { pmdi->cBusy++; pmdi->cDevs++; RecalcCursor(hdlg); Diq_RecalcClose(pmdi, hdlg); } } else //#endif if ((UINT)iSel < (UINT)pmdi->daryDevs.cx) { UINT didc; LPDIDEVICEINSTANCE pdidi; didc = GetCheckedRadioButton(hdlg, IDC_MAIN_ITF, IDC_MAIN_ITFMAC) - IDC_MAIN_ITF; pdidi = Dary_GetPtr(&pmdi->daryDevs, iSel, DIDEVICEINSTANCE); if (Dev_Create(hdlg, IsDlgButtonChecked(hdlg, IDC_MAIN_OLE), IsUnicodeDidc(didc), &pdidi->guidInstance, pdidi->tszInstanceName, didc)) { pmdi->cBusy++; pmdi->cDevs++; RecalcCursor(hdlg); Diq_RecalcClose(pmdi, hdlg); } } return 1; } /***************************************************************************** * * Diq_OnFindDevice * * Display the "FindDevice" dialog. * *****************************************************************************/ BOOL INTERNAL Diq_OnFindDevice(HWND hdlg) { PMAINDLGINFO pmdi = GetDialogPtr(hdlg); UINT didc; didc = GetCheckedRadioButton(hdlg, IDC_MAIN_ITF, IDC_MAIN_ITFMAC) - IDC_MAIN_ITF; if (Find_Create(hdlg, IsDlgButtonChecked(hdlg, IDC_MAIN_OLE), IsDlgButtonChecked(hdlg, IDC_MAIN_DIW))) { pmdi->cBusy++; pmdi->cDevs++; RecalcCursor(hdlg); Diq_RecalcClose(pmdi, hdlg); } return 1; } /***************************************************************************** * * Diq_OnControlPanel * * Run the DirectInput control panel using the indicated interface. * *****************************************************************************/ BOOL INTERNAL Diq_OnControlPanel(HWND hdlg) { HRESULT hres; LPDIRECTINPUTA pdia; hres = CreateDI(IsDlgButtonChecked(hdlg, IDC_MAIN_OLE), IsDlgButtonChecked(hdlg, IDC_MAIN_DIW), (PPV)&pdia); if (SUCCEEDED(hres)) { hres = pdia->lpVtbl->RunControlPanel(pdia, hdlg, 0); if (SUCCEEDED(hres)) { } else { MessageBoxV(hdlg, IDS_ERR_RUNCPL, hres); } pdia->lpVtbl->Release(pdia); } else { MessageBoxV(hdlg, IDS_ERR_CREATEOBJ, hres); } return 1; } /***************************************************************************** * * Diq_OnRefresh * * Refresh the device list. * *****************************************************************************/ BOOL INTERNAL Diq_OnRefresh(HWND hdlg) { if (DialogBox(g_hinst, MAKEINTRESOURCE(IDD_ENUMDEV), hdlg, DEnum_DlgProc) > 0) { PMAINDLGINFO pmdi = GetDialogPtr(hdlg); Diq_EnumDevices(pmdi); } return TRUE; } /***************************************************************************** * * Diq_OnCommand * *****************************************************************************/ BOOL INLINE Diq_OnCommand(HWND hdlg, int id, UINT cmd) { switch (id) { case IDC_MAIN_GETSTAT:return Diq_OnGetStatus(hdlg); case IDC_MAIN_CREATE: return Diq_OnCreateObject(hdlg); case IDC_MAIN_CPL: return Diq_OnControlPanel(hdlg); case IDC_MAIN_FIND: return Diq_OnFindDevice(hdlg); case IDC_MAIN_REFRESH:return Diq_OnRefresh(hdlg); } return 0; } /***************************************************************************** * * Diq_OnChildExit * * A client device has exited. Decrement the dev count. * *****************************************************************************/ BOOL INTERNAL Diq_OnChildExit(PMAINDLGINFO pmdi, HWND hdlg) { if (pmdi) { pmdi->cDevs--; if (pmdi->cDevs == 0) { Diq_RecalcClose(pmdi, hdlg); } } return 1; } /***************************************************************************** * * Diq_OnThreadStarted * * A worker thread has finished starting. Decrement our busy count. * *****************************************************************************/ BOOL INTERNAL Diq_OnThreadStarted(PMAINDLGINFO pmdi, HWND hdlg) { if (pmdi) { pmdi->cBusy--; if (pmdi->cBusy == 0) { /* Set the cursor back if it's us */ RecalcCursor(hdlg); } } return 1; } /***************************************************************************** * * Diq_OnSetCursor * * Set the cursor to match our pending thread create count. * *****************************************************************************/ BOOL INTERNAL Diq_OnSetCursor(PMAINDLGINFO pmdi, HWND hdlg, WPARAM wp, LPARAM lp) { if (LOWORD(lp) == HTCLIENT && pmdi->cBusy) { SetCursor(g_hcurStarting); return SetDlgMsgResult(hdlg, WM_SETCURSOR, 1); } else { return 0; } } /***************************************************************************** * * Diq_DlgProc * *****************************************************************************/ INT_PTR CALLBACK Diq_DlgProc(HWND hdlg, UINT wm, WPARAM wp, LPARAM lp) { PMAINDLGINFO pmdi = GetDialogPtr(hdlg); switch (wm) { case WM_INITDIALOG: return Diq_OnInitDialog(hdlg); case WM_DESTROY: return Diq_OnDestroy(pmdi, hdlg); case WM_CLOSE: EndDialog(hdlg, 0); break; case WM_COMMAND: return Diq_OnCommand(hdlg, (int)GET_WM_COMMAND_ID(wp, lp), (UINT)GET_WM_COMMAND_CMD(wp, lp)); case WM_SETCURSOR: return Diq_OnSetCursor(pmdi, hdlg, wp, lp); case WM_THREADSTARTED: return Diq_OnThreadStarted(pmdi, hdlg); case WM_CHILDEXIT: return Diq_OnChildExit(pmdi, hdlg); } return 0; }