/***************************************************************************** * * diqvbool.c * * VList plug-in that does BOOLs. * *****************************************************************************/ #include "diquick.h" #pragma BEGIN_CONST_DATA /***************************************************************************** * * VLISTBOOL * * BOOL-specific goo. * * When we PreDisplay a control, we stash the VLISTBOOL into the * DWL_USER. We can't use the GWLP_USERDATA, because the vlist * manager uses that. * *****************************************************************************/ typedef struct VLISTBOOL { VLISTITEM item; DIPROPDWORD dipdw; /* * If non-NULL, then this is a read/write control. */ PROPUPDATEPROC Update; PV pvRef1; PV pvRef2; } VLISTBOOL, *PVLISTBOOL; /***************************************************************************** * * VBool_PreDisplay * * Check the Yes or No, accordingly. * * Note that there is no such thing as a read-only radio button. * We have to disable it. * *****************************************************************************/ void INTERNAL VBool_PreDisplay(HWND hdlg, PV pv) { PVLISTBOOL pvbool = pv; /* * Need to do this early so our subclass procedure knows who * we're talking about. */ SetDialogPtr(hdlg, pvbool); CheckRadioButton(hdlg, IDC_VBOOL_YES, IDC_VBOOL_NO, pvbool->dipdw.dwData ? IDC_VBOOL_YES : IDC_VBOOL_NO); ShowWindow(GetDlgItem(hdlg, IDC_VBOOL_APPLY), pvbool->Update ? SW_SHOW : SW_HIDE); } /***************************************************************************** * * VBool_Destroy * * Nothing to clean up. * *****************************************************************************/ void INTERNAL VBool_Destroy(PV pv) { PVLISTBOOL pvbool = pv; } /***************************************************************************** * * VBool_Button_SubclassProc * * Procedure we install that subclasses our radio buttons. * * If we are in R/O mode, then we return DLGC_STATIC so the * dialog manager won't include us in the TAB order. * *****************************************************************************/ LRESULT CALLBACK VBool_Button_SubclassProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) { switch (wm) { case WM_GETDLGCODE: { PVLISTBOOL pvbool = GetDialogPtr(GetParent(hwnd)); if (pvbool && !pvbool->Update) { return DLGC_STATIC; } } break; } return CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, wm, wp, lp); } /***************************************************************************** * * VBool_OnInitDialog * * Subclas our buttons so they act "dumb". * *****************************************************************************/ BOOL INTERNAL VBool_OnInitDialog(HWND hdlg) { WNDPROC wp; HWND hwnd; hwnd = GetDlgItem(hdlg, IDC_VBOOL_YES); wp = SubclassWindow(hwnd, VBool_Button_SubclassProc); SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR)wp); hwnd = GetDlgItem(hdlg, IDC_VBOOL_NO); wp = SubclassWindow(hwnd, VBool_Button_SubclassProc); SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR)wp); return TRUE; } /***************************************************************************** * * VBool_OnApply * * Let the owner know. * *****************************************************************************/ void INTERNAL VBool_OnApply(HWND hdlg) { HRESULT hres; PVLISTBOOL pvbool = GetDialogPtr(hdlg); pvbool->dipdw.dwData = IsDlgButtonChecked(hdlg, IDC_VBOOL_YES); hres = pvbool->Update(&pvbool->dipdw.diph, pvbool->pvRef1, pvbool->pvRef2); if (FAILED(hres)) { MessageBoxV(hdlg, IDS_ERR_HRESULT, hres); } } /***************************************************************************** * * VBool_OnCommand * * If they clicked one of the options, change it back if we are R/O. * * If they pressed Apply, then apply it. * *****************************************************************************/ BOOL INLINE VBool_OnCommand(HWND hdlg, int id, UINT codeNotify) { switch (id) { case IDC_VBOOL_APPLY: VBool_OnApply(hdlg); return TRUE; } return FALSE; } /***************************************************************************** * * VBool_DlgProc * * Nothing really happens here. The real work is done externally. * *****************************************************************************/ INT_PTR CALLBACK VBool_DlgProc(HWND hdlg, UINT wm, WPARAM wp, LPARAM lp) { switch (wm) { case WM_INITDIALOG: return VBool_OnInitDialog(hdlg); case WM_COMMAND: return VBool_OnCommand(hdlg, (int)GET_WM_COMMAND_ID(wp, lp), (UINT)GET_WM_COMMAND_CMD(wp, lp)); } return FALSE; } /***************************************************************************** * * c_vvtblBool * * Our vtbl. * *****************************************************************************/ const VLISTVTBL c_vvtblBool = { VBool_PreDisplay, VBool_Destroy, IDD_VAL_BOOL, VBool_DlgProc, }; /***************************************************************************** * * VBool_Create * * Make a vlist item that tracks a BOOL. * *****************************************************************************/ PVLISTITEM EXTERNAL VBool_Create(LPDIPROPDWORD pdipdw, PROPUPDATEPROC Update, PV pvRef1, PV pvRef2) { PVLISTBOOL pvbool = LocalAlloc(LPTR, cbX(VLISTBOOL)); if (pvbool) { pvbool->item.pvtbl = &c_vvtblBool; pvbool->dipdw = *pdipdw; pvbool->Update = Update; pvbool->pvRef1 = pvRef1; pvbool->pvRef2 = pvRef2; } return (PV)pvbool; }