Started using normal images for checkboxes in Windows uiTables. It doesn't quite work yet.

This commit is contained in:
Pietro Gagliardi 2018-06-09 23:25:16 -04:00
parent 4c5f0961fe
commit 405a6defd2
1 changed files with 28 additions and 47 deletions

View File

@ -9,6 +9,9 @@ static uiTableTextColumnOptionalParams defaultTextColumnOptionalParams = {
/*TODO.ColorModelColumn = */-1,
};
#define nCheckboxImages 4
#define nLVN_GETDISPINFOSkip 3
struct columnParams {
int textModelColumn;
int textEditableColumn;
@ -159,17 +162,13 @@ nm->item.pszText=L"abcdefg";
b = uiprivWICToGDI(wb, dc);
if (ReleaseDC(t->hwnd, dc) == 0)
logLastError(L"error calling ReleaseDC() in onLVN_GETDISPINFO()");
if (ImageList_GetImageCount(t->smallImages) <= t->smallIndex) {
if (ImageList_Add(t->smallImages, b, NULL) == -1)
logLastError(L"error calling ImageList_Add() in onLVN_GETDISPINFO()");
} else
if (ImageList_Replace(t->smallImages, t->smallIndex, b, NULL) == 0)
logLastError(L"error calling ImageList_Replace() in onLVN_GETDISPINFO()");
if (ImageList_Replace(t->smallImages, t->smallIndex + nCheckboxImages, b, NULL) == 0)
logLastError(L"error calling ImageList_Replace() in onLVN_GETDISPINFO()");
// TODO error check
DeleteObject(b);
nm->item.iImage = t->smallIndex;
nm->item.iImage = t->smallIndex + nCheckboxImages;
t->smallIndex++;
t->smallIndex %= 3; // TODO don't hardcode this
t->smallIndex %= nLVN_GETDISPINFOSkip;
}
// having an image list always leaves space for an image on the main item :|
@ -180,20 +179,16 @@ nm->item.pszText=L"abcdefg";
nm->item.iIndent = -1;
}
if ((nm->item.mask & LVIF_STATE) != 0)
if (p->checkboxModelColumn != -1) {
// TODO handle enabled
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->textModelColumn);
checked = uiTableDataInt(data) != 0;
uiFreeTableData(data);
nm->item.state = INDEXTOSTATEIMAGEMASK(1);
if (checked)
nm->item.state = INDEXTOSTATEIMAGEMASK(2);
nm->item.stateMask = LVIS_STATEIMAGEMASK;
} else {
nm->item.state = INDEXTOSTATEIMAGEMASK(0);
nm->item.stateMask = LVIS_STATEIMAGEMASK;
}
if (p->checkboxModelColumn != -1) {
// TODO handle enabled
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->textModelColumn);
checked = uiTableDataInt(data) != 0;
uiFreeTableData(data);
nm->item.iImage = 0;
if (checked)
nm->item.iImage = 1;
nm->item.mask |= LVIF_IMAGE;
}
// we don't want to pop from an empty queue, so if nothing updated the queue (no info was filled in above), just push NULL
if (!queueUpdated)
@ -448,17 +443,14 @@ static void mkCheckboxesUnthemed(uiTable *t, int cx, int cy)
HDC cdc;
HBITMAP prevBitmap;
RECT r;
int i, n;
// + 1 because we can't actually use image index 0 — that index is used to mean "no state image" in LVITEMW
n = ARRAYSIZE(unthemedStates) + 1;
int i;
dc = GetDC(t->hwnd);
if (dc == NULL)
logLastError(L"error calling GetDC() in mkCheckboxesUnthemed()");
ZeroMemory(&bmi, sizeof (BITMAPINFO));
bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = cx * n;
bmi.bmiHeader.biWidth = cx * nCheckboxImages;
bmi.bmiHeader.biHeight = cy;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
@ -474,12 +466,11 @@ static void mkCheckboxesUnthemed(uiTable *t, int cx, int cy)
// TODO error check
prevBitmap = (HBITMAP) SelectObject(cdc, b);
// note we start at cx to start at index 1
r.left = cx;
r.left = 0;
r.top = 0;
r.right = cx * 2;
r.right = cx;
r.bottom = cy;
for (i = 0; i < ARRAYSIZE(unthemedStates); i++) {
for (i = 0; i < nCheckboxImages; i++) {
if (DrawFrameControl(cdc, &r,
DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | unthemedStates[i]) == 0)
logLastError(L"error calling DrawFrameControl() in mkCheckboxesUnthemed()");
@ -494,14 +485,8 @@ static void mkCheckboxesUnthemed(uiTable *t, int cx, int cy)
if (ReleaseDC(t->hwnd, dc) == 0)
logLastError(L"error calling ReleaseDC() in mkCheckboxesUnthemed()");
t->checkboxImages = ImageList_Create(cx, cy, ILC_COLOR32,
n, n);
if (t->checkboxImages == NULL)
logLastError(L"error calling ImageList_Create() in mkCheckboxesUnthemed()");
if (ImageList_Add(t->checkboxImages, b, NULL) == -1)
logLastError(L"error calling ImageList_Add() in mkCheckboxesUnthemed()");
// TODO will this return NULL here because it's an initial state?
SendMessageW(t->hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM) (t->checkboxImages));
if (ImageList_Replace(t->smallImages, 0, b, NULL) == 0)
logLastError(L"error calling ImageList_Replace() in mkCheckboxesUnthemed()");
// TODO error check
DeleteObject(b);
@ -511,6 +496,7 @@ uiTable *uiNewTable(uiTableModel *model)
{
uiTable *t;
int n;
int i;
uiWindowsNewControl(uiTable, t);
@ -536,26 +522,21 @@ uiTable *uiNewTable(uiTableModel *model)
t->dispinfoStrings = new std::queue<WCHAR *>;
// this encodes the idea that two LVN_GETDISPINFOs must complete before we can free a string: the first real one is for the fourth call to free
t->dispinfoStrings->push(NULL);
t->dispinfoStrings->push(NULL);
t->dispinfoStrings->push(NULL);
for (i = 0; i < nLVN_GETDISPINFOSkip; i++)
t->dispinfoStrings->push(NULL);
// TODO update these when the DPI changes
// TODO handle errors
// TODO try adding a real transparent image
t->smallImages = ImageList_Create(
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
ILC_COLOR32,
0, 3);
nCheckboxImages + nLVN_GETDISPINFOSkip, nCheckboxImages + nLVN_GETDISPINFOSkip);
if (t->smallImages == NULL)
logLastError(L"error calling ImageList_Create() in uiNewTable()");
// TODO will this return NULL here because it's an initial state?
SendMessageW(t->hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM) (t->smallImages));
mkCheckboxesUnthemed(t, 16, 16);
// and we need to enable LVN_GETDISPINFO for states
if (SendMessageW(t->hwnd, LVM_SETCALLBACKMASK, LVIS_STATEIMAGEMASK, 0) == FALSE)
logLastError(L"error calling LVM_SETCALLBACKMASK in uiTableAdd()");
return t;
}