445 lines
12 KiB
C
445 lines
12 KiB
C
/*****************************************************************************
|
|
*
|
|
* diqvlist.c
|
|
*
|
|
* Wrappers that turn a listbox/edit control pair into
|
|
* a value-listbox.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "diquick.h"
|
|
|
|
#pragma BEGIN_CONST_DATA
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* VLISTINFO
|
|
*
|
|
* Stuff that tracks the vlist itself.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
typedef struct VLISTINFO {
|
|
|
|
/*
|
|
* The current visible dialog.
|
|
*/
|
|
HWND hdlgVis;
|
|
|
|
/*
|
|
* The coordinates of the child dialog area.
|
|
*/
|
|
POINT pt;
|
|
|
|
} VLISTINFO, *PVLISTINFO;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_OnInitDialog
|
|
*
|
|
* Initialize a single Vlist control. The value control is assumed
|
|
* to follow the listbox in the Z-order.
|
|
*
|
|
* All our goofy sub-dialogs are inserted into the Z-order between
|
|
* the main vlist control and the value control.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_OnInitDialog(HWND hwndList)
|
|
{
|
|
PVLISTINFO pvi = LocalAlloc(LPTR, cbX(VLISTINFO));
|
|
if (pvi) {
|
|
RECT rc;
|
|
HWND hwnd;
|
|
|
|
SetWindowLongPtr(hwndList, GWLP_USERDATA, (INT_PTR)pvi);
|
|
|
|
/*
|
|
* Get the invisible static that we use to signal the end of the
|
|
* list. pull out its coordinates.
|
|
*/
|
|
hwnd = GetWindow(hwndList, GW_HWNDNEXT);
|
|
GetWindowRect(hwnd, &rc);
|
|
pvi->pt.x = rc.left;
|
|
pvi->pt.y = rc.top;
|
|
MapWindowPoints(HWND_DESKTOP, GetParent(hwndList), &pvi->pt, 1);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* VlistItem_Destroy
|
|
*
|
|
* Destroy a VLISTITEM and its associated goo.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void INTERNAL
|
|
VlistItem_Destroy(PVLISTITEM pitem)
|
|
{
|
|
pitem->pvtbl->Destroy(pitem);
|
|
LocalFree(pitem);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddItem
|
|
*
|
|
* Add an item with a string id.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddItem(HWND hwnd, UINT ids, PVLISTITEM pitem)
|
|
{
|
|
int iItem;
|
|
TCHAR tsz[256];
|
|
|
|
LoadString(g_hinst, ids, tsz, cA(tsz));
|
|
iItem = ListBox_AddString(hwnd, tsz);
|
|
if (iItem >= 0) {
|
|
ListBox_SetItemData(hwnd, iItem, pitem);
|
|
} else {
|
|
VlistItem_Destroy(pitem);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddValueRW
|
|
*
|
|
* Add a mutable string with corresponding value.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddValueRW(HWND hwnd, UINT ids, LPCTSTR ptszValue,
|
|
EDITUPDATEPROC Update, PV pvRef1, PV pvRef2)
|
|
{
|
|
PVLISTITEM pitem;
|
|
pitem = VEdit_Create(ptszValue, Update, pvRef1, pvRef2);
|
|
|
|
if (pitem) {
|
|
Vlist_AddItem(hwnd, ids, pitem);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddValue
|
|
*
|
|
* Add a string with corresponding value.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddValue(HWND hwnd, UINT ids, LPCTSTR ptszValue)
|
|
{
|
|
Vlist_AddValueRW(hwnd, ids, ptszValue, NULL, 0, 0);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddNumValueRW
|
|
*
|
|
* Add an integer that can be edited.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddNumValueRW(HWND hwnd, UINT ids,
|
|
LPDIPROPDWORD pdipdw, int iMin, int iMax, int iRadix,
|
|
PROPUPDATEPROC Update, PV pvRef1, PV pvRef2)
|
|
{
|
|
PVLISTITEM pitem;
|
|
pitem = VInt_Create(pdipdw, iMin, iMax, iRadix, Update, pvRef1, pvRef2);
|
|
|
|
if (pitem) {
|
|
Vlist_AddItem(hwnd, ids, pitem);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddRadixValue
|
|
*
|
|
* Add an integer with the appropriate default radix.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void INTERNAL
|
|
Vlist_AddRadixValue(HWND hwnd, UINT ids, DWORD dw, int iRadix)
|
|
{
|
|
DIPROPDWORD dipdw;
|
|
dipdw.dwData = dw;
|
|
|
|
Vlist_AddNumValueRW(hwnd, ids, &dipdw, (int)dw, (int)dw, iRadix,
|
|
NULL, 0, 0);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddHexValue
|
|
*
|
|
* Add a string with corresponding value.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddHexValue(HWND hwnd, UINT ids, DWORD dw)
|
|
{
|
|
Vlist_AddRadixValue(hwnd, ids, dw, 16);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddIntValue
|
|
*
|
|
* Add a string with corresponding value.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddIntValue(HWND hwnd, UINT ids, DWORD dw)
|
|
{
|
|
Vlist_AddRadixValue(hwnd, ids, dw, 10);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddRangeValueRW
|
|
*
|
|
* Add a pair of integers that can be edited.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddRangeValueRW(HWND hwnd, UINT ids,
|
|
LPDIPROPRANGE pdiprg, int iRadix,
|
|
PROPUPDATEPROC Update, PV pvRef1, PV pvRef2)
|
|
{
|
|
PVLISTITEM pitem;
|
|
pitem = VRange_Create(pdiprg, iRadix, Update, pvRef1, pvRef2);
|
|
|
|
if (pitem) {
|
|
Vlist_AddItem(hwnd, ids, pitem);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddCalValueRW
|
|
*
|
|
* Add a pair of integers that can be edited.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddCalValueRW(HWND hwnd, UINT ids,
|
|
LPDIPROPCAL pdipcal, int iRadix,
|
|
PROPUPDATEPROC Update, PV pvRef1, PV pvRef2)
|
|
{
|
|
PVLISTITEM pitem;
|
|
pitem = VCal_Create(pdipcal, iRadix, Update, pvRef1, pvRef2);
|
|
|
|
if (pitem) {
|
|
Vlist_AddItem(hwnd, ids, pitem);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddBoolValueRW
|
|
*
|
|
* Add a boolean.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddBoolValueRW(HWND hwnd, UINT ids, LPDIPROPDWORD pdipdw,
|
|
PROPUPDATEPROC Update, PV pvRef1, PV pvRef2)
|
|
{
|
|
PVLISTITEM pitem;
|
|
pitem = VBool_Create(pdipdw, Update, pvRef1, pvRef2);
|
|
|
|
if (pitem) {
|
|
Vlist_AddItem(hwnd, ids, pitem);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddBoolValue
|
|
*
|
|
* Add a boolean.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddBoolValue(HWND hwnd, UINT ids, DWORD dw)
|
|
{
|
|
DIPROPDWORD dipdw;
|
|
dipdw.dwData = dw;
|
|
|
|
Vlist_AddBoolValueRW(hwnd, ids, &dipdw, NULL, 0, 0);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_AddFlags
|
|
*
|
|
* Add a bunch of strings corresponding to flag bits.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_AddFlags(HWND hwnd, DWORD fl, PCHECKLISTFLAG rgclf, UINT cclf)
|
|
{
|
|
UINT iclf;
|
|
|
|
for (iclf = 0; iclf < cclf; iclf++) {
|
|
Vlist_AddBoolValue(hwnd, rgclf[iclf].ids,
|
|
fl & rgclf[iclf].flMask);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_FindChild
|
|
*
|
|
* Find the dialog box (creating it if necessary) that manages
|
|
* the vlist in question. We know who it is because we stash
|
|
* the vtbl pointer into the GWLP_USERDATA so we know who it is.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HWND INTERNAL
|
|
Vlist_FindChild(HWND hwndList, PVLISTVTBL pvtbl)
|
|
{
|
|
HWND hwnd = hwndList;
|
|
PVLISTINFO pvi;
|
|
|
|
while ((hwnd = GetWindow(hwnd, GW_HWNDNEXT))) {
|
|
PVLISTVTBL pvtblT = (PVLISTVTBL)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (!pvtblT) {
|
|
break;
|
|
}
|
|
|
|
if (pvtbl == pvtblT) {
|
|
return hwnd;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Not found. Gotta make it.
|
|
*/
|
|
hwnd = CreateDialog(g_hinst, (PV)(UINT_PTR)pvtbl->idd, GetParent(hwndList),
|
|
pvtbl->dp);
|
|
|
|
if( hwnd ) {
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR)pvtbl);
|
|
|
|
/*
|
|
* Now put it in the right place.
|
|
*/
|
|
pvi = (PVLISTINFO)GetWindowLongPtr(hwndList, GWLP_USERDATA);
|
|
SetWindowPos(hwnd, hwndList, pvi->pt.x, pvi->pt.y, 0, 0, SWP_NOSIZE);
|
|
}
|
|
|
|
return hwnd;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_OnSelChange
|
|
*
|
|
* Update the edit control to match the current gizmo in the
|
|
* list box.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_OnSelChange(HWND hwnd)
|
|
{
|
|
PVLISTINFO pvi = (PVLISTINFO)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (pvi) {
|
|
int iItem;
|
|
|
|
iItem = ListBox_GetCurSel(hwnd);
|
|
if (iItem >= 0) {
|
|
PVLISTITEM pitem = (PV)ListBox_GetItemData(hwnd, iItem);
|
|
if (pitem) {
|
|
HWND hdlg = Vlist_FindChild(hwnd, pitem->pvtbl);
|
|
|
|
if( hdlg ) {
|
|
pitem->pvtbl->PreDisplay(hdlg, pitem);
|
|
|
|
/*
|
|
* Out with the old, in with the new.
|
|
*/
|
|
if (pvi->hdlgVis != hdlg) {
|
|
if (pvi->hdlgVis) {
|
|
ShowWindow(pvi->hdlgVis, FALSE);
|
|
}
|
|
pvi->hdlgVis = hdlg;
|
|
ShowWindow(pvi->hdlgVis, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Vlist_OnDestroy
|
|
*
|
|
* Clean up a Vlist.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
Vlist_OnDestroy(HWND hwndList)
|
|
{
|
|
PVLISTINFO pvi;
|
|
HWND hwnd;
|
|
int iItem, cItem;
|
|
|
|
/*
|
|
* Empty the listbox.
|
|
*/
|
|
cItem = ListBox_GetCount(hwndList);
|
|
for (iItem = 0; iItem < cItem; iItem++) {
|
|
PVLISTITEM pitem = (PV)ListBox_GetItemData(hwndList, iItem);
|
|
if (pitem) {
|
|
VlistItem_Destroy(pitem);
|
|
}
|
|
}
|
|
ListBox_ResetContent(hwndList);
|
|
|
|
/*
|
|
* Toss our instance data.
|
|
*/
|
|
pvi = (PVLISTINFO)GetWindowLongPtr(hwndList, GWLP_USERDATA);
|
|
if (pvi) {
|
|
LocalFree(pvi);
|
|
SetWindowLongPtr(hwndList, GWLP_USERDATA, 0);
|
|
}
|
|
|
|
/*
|
|
* Kill the child dialogs we created.
|
|
*/
|
|
|
|
while ((hwnd = GetWindow(hwndList, GW_HWNDNEXT)) &&
|
|
GetWindowLongPtr(hwnd, GWLP_USERDATA)) {
|
|
DestroyWindow(hwnd);
|
|
}
|
|
|
|
}
|