Reintegrated wintablemetrics, properly this time (for the most part). It works. Now we can start switching to custom-drawing everything.
This commit is contained in:
parent
59d8e81b85
commit
e52373c59a
|
@ -137,11 +137,72 @@ static COLORREF blend(COLORREF base, double r, double g, double b, double a)
|
||||||
(BYTE) (bb * 255));
|
(BYTE) (bb * 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT fillSubitemDrawParams(HWND hwnd, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
// note that we can't just copy nm->nmcd.rc into p->bounds because that is only defined during prepaint stages
|
||||||
|
|
||||||
|
// TODO this corrupts memory
|
||||||
|
if (nm->iSubItem == 0) {return S_OK;
|
||||||
|
ZeroMemory(&r, sizeof (RECT));
|
||||||
|
r.left = LVIR_BOUNDS;
|
||||||
|
if (SendMessageW(hwnd, LVM_GETITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == FALSE) {
|
||||||
|
logLastError(L"LVM_GETITEMRECT LVIR_BOUNDS");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
dp->bounds = r;
|
||||||
|
ZeroMemory(&r, sizeof (RECT));
|
||||||
|
r.left = LVIR_ICON;
|
||||||
|
if (SendMessageW(hwnd, LVM_GETITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == FALSE) {
|
||||||
|
logLastError(L"LVM_GETITEMRECT LVIR_ICON");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
dp->icon = r;
|
||||||
|
ZeroMemory(&r, sizeof (RECT));
|
||||||
|
r.left = LVIR_LABEL;
|
||||||
|
if (SendMessageW(hwnd, LVM_GETITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == FALSE) {
|
||||||
|
logLastError(L"LVM_GETITEMRECT LVIR_LABEL");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
dp->label = r;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&r, sizeof (RECT));
|
||||||
|
r.left = LVIR_BOUNDS;
|
||||||
|
r.top = nm->iSubItem;
|
||||||
|
if (SendMessageW(hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == 0) {
|
||||||
|
logLastError(L"LVM_GETSUBITEMRECT LVIR_BOUNDS");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
dp->bounds = r;
|
||||||
|
ZeroMemory(&r, sizeof (RECT));
|
||||||
|
r.left = LVIR_ICON;
|
||||||
|
r.top = nm->iSubItem;
|
||||||
|
if (SendMessageW(hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == 0) {
|
||||||
|
logLastError(L"LVM_GETSUBITEMRECT LVIR_ICON");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
dp->icon = r;
|
||||||
|
// LVIR_LABEL is treated as LVIR_BOUNDS for LVM_GETSUBITEMRECT, but it doesn't matter because the label rect is uses isn't what we want anyway
|
||||||
|
// there's a hardocded 2-logical unit gap between the icon and text for subitems, AND the text starts being drawn (in the background) one bitmap margin to the right of that
|
||||||
|
// with normal items, there's no gap, and only the 2-logical unit gap after the background starts (TODO confirm this part)
|
||||||
|
// let's copy that to look nicer, even if it's not "accurate"
|
||||||
|
// TODO check against accessibility
|
||||||
|
dp->label = dp->bounds;
|
||||||
|
// because we want the 2 extra logical units to be included with the background, we don't include them here
|
||||||
|
dp->label.left = dp->icon.right;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static LRESULT onNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm)
|
static LRESULT onNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm)
|
||||||
{
|
{
|
||||||
uiprivTableColumnParams *p;
|
uiprivTableColumnParams *p;
|
||||||
uiTableData *data;
|
uiTableData *data;
|
||||||
double r, g, b, a;
|
double r, g, b, a;
|
||||||
|
uiprivSubitemDrawParams dp;
|
||||||
LRESULT ret;
|
LRESULT ret;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -193,7 +254,13 @@ DrawTextW(nm->nmcd.hdc, L"Part", -1,
|
||||||
ret = CDRF_DODEFAULT;
|
ret = CDRF_DODEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = uiprivNM_CUSTOMDRAWImagesCheckboxes(t, nm, &ret);
|
if ((nm->nmcd.dwDrawStage & CDDS_SUBITEM) == 0)return ret;
|
||||||
|
ZeroMemory(&dp, sizeof (uiprivSubitemDrawParams));
|
||||||
|
hr = fillSubitemDrawParams(t->hwnd, nm, &dp);
|
||||||
|
if (hr != S_OK) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
hr = uiprivNM_CUSTOMDRAWImagesCheckboxes(t, nm, &dp, &ret);
|
||||||
if (hr != S_OK) {
|
if (hr != S_OK) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,14 @@ struct uiTable {
|
||||||
// custom draw state
|
// custom draw state
|
||||||
COLORREF clrItemText;
|
COLORREF clrItemText;
|
||||||
};
|
};
|
||||||
|
typedef struct uiprivSubitemDrawParams uiprivSubitemDrawParams;
|
||||||
|
struct uiprivSubitemDrawParams {
|
||||||
|
RECT bounds;
|
||||||
|
RECT icon;
|
||||||
|
RECT label;
|
||||||
|
};
|
||||||
|
|
||||||
// tableimages.cpp
|
// tableimages.cpp
|
||||||
extern HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
extern HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
||||||
extern HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult);
|
extern HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp, LRESULT *lResult);
|
||||||
extern HRESULT uiprivTableSetupImagesCheckboxes(uiTable *t);
|
extern HRESULT uiprivTableSetupImagesCheckboxes(uiTable *t);
|
||||||
|
|
|
@ -139,7 +139,7 @@ HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uip
|
||||||
// however, there seems to be no way to do this natively, so we have to draw over ourselves (TODO?)
|
// however, there seems to be no way to do this natively, so we have to draw over ourselves (TODO?)
|
||||||
// hopefully the performance won't be too bad
|
// hopefully the performance won't be too bad
|
||||||
// see also https://www.codeproject.com/Articles/79/Neat-Stuff-to-Do-in-List-Controls-Using-Custom-Dra
|
// see also https://www.codeproject.com/Articles/79/Neat-Stuff-to-Do-in-List-Controls-Using-Custom-Dra
|
||||||
HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult)
|
HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp, LRESULT *lResult)
|
||||||
{
|
{
|
||||||
uiprivTableColumnParams *p;
|
uiprivTableColumnParams *p;
|
||||||
int index;
|
int index;
|
||||||
|
@ -161,13 +161,7 @@ HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, LRES
|
||||||
|
|
||||||
index = checkboxIndex(t->model, nm->nmcd.dwItemSpec,
|
index = checkboxIndex(t->model, nm->nmcd.dwItemSpec,
|
||||||
p->checkboxModelColumn, p->checkboxEditableColumn);
|
p->checkboxModelColumn, p->checkboxEditableColumn);
|
||||||
ZeroMemory(&r, sizeof (RECT));
|
r = dp->icon;
|
||||||
r.left = LVIR_ICON;
|
|
||||||
r.top = nm->iSubItem;
|
|
||||||
if (SendMessageW(t->hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == 0) {
|
|
||||||
logLastError(L"LVM_GETSUBITEMRECT");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
// the real listview also does this :|
|
// the real listview also does this :|
|
||||||
if (ImageList_GetIconSize(t->smallImages, &cxIcon, &cyIcon) == 0) {
|
if (ImageList_GetIconSize(t->smallImages, &cxIcon, &cyIcon) == 0) {
|
||||||
logLastError(L"LVM_GETSUBITEMRECT cell");
|
logLastError(L"LVM_GETSUBITEMRECT cell");
|
||||||
|
|
153
wintablemetrics
153
wintablemetrics
|
@ -1,153 +0,0 @@
|
||||||
diff --git a/windows/table.cpp b/windows/table.cpp
|
|
||||||
index 32c60244..d33cb22f 100644
|
|
||||||
--- a/windows/table.cpp
|
|
||||||
+++ b/windows/table.cpp
|
|
||||||
@@ -137,11 +137,71 @@ static COLORREF blend(COLORREF base, double r, double g, double b, double a)
|
|
||||||
(BYTE) (bb * 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
+static HRESULT fillSubitemDrawParams(HWND hwnd, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp)
|
|
||||||
+{
|
|
||||||
+ RECT r;
|
|
||||||
+ HRESULT hr;
|
|
||||||
+
|
|
||||||
+ // note that we can't just copy nm->nmcd.rc into p->bounds because that is only defined during prepaint stages
|
|
||||||
+
|
|
||||||
+ if (nm->iSubItem == 0) {return S_OK;
|
|
||||||
+ ZeroMemory(&r, sizeof (RECT));
|
|
||||||
+ r.left = LVIR_BOUNDS;
|
|
||||||
+ if (SendMessageW(hwnd, LVM_GETITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == FALSE) {
|
|
||||||
+ logLastError(L"LVM_GETITEMRECT LVIR_BOUNDS");
|
|
||||||
+ return E_FAIL;
|
|
||||||
+ }
|
|
||||||
+ dp->bounds = r;
|
|
||||||
+ ZeroMemory(&r, sizeof (RECT));
|
|
||||||
+ r.left = LVIR_ICON;
|
|
||||||
+ if (SendMessageW(hwnd, LVM_GETITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == FALSE) {
|
|
||||||
+ logLastError(L"LVM_GETITEMRECT LVIR_ICON");
|
|
||||||
+ return E_FAIL;
|
|
||||||
+ }
|
|
||||||
+ dp->icon = r;
|
|
||||||
+ ZeroMemory(&r, sizeof (RECT));
|
|
||||||
+ r.left = LVIR_LABEL;
|
|
||||||
+ if (SendMessageW(hwnd, LVM_GETITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == FALSE) {
|
|
||||||
+ logLastError(L"LVM_GETITEMRECT LVIR_LABEL");
|
|
||||||
+ return E_FAIL;
|
|
||||||
+ }
|
|
||||||
+ dp->label = r;
|
|
||||||
+ return S_OK;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ZeroMemory(&r, sizeof (RECT));
|
|
||||||
+ r.left = LVIR_BOUNDS;
|
|
||||||
+ r.top = nm->iSubItem;
|
|
||||||
+ if (SendMessageW(hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == 0) {
|
|
||||||
+ logLastError(L"LVM_GETSUBITEMRECT LVIR_BOUNDS");
|
|
||||||
+ return E_FAIL;
|
|
||||||
+ }
|
|
||||||
+ dp->bounds = r;
|
|
||||||
+ ZeroMemory(&r, sizeof (RECT));
|
|
||||||
+ r.left = LVIR_ICON;
|
|
||||||
+ r.top = nm->iSubItem;
|
|
||||||
+ if (SendMessageW(hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == 0) {
|
|
||||||
+ logLastError(L"LVM_GETSUBITEMRECT LVIR_ICON");
|
|
||||||
+ return E_FAIL;
|
|
||||||
+ }
|
|
||||||
+ dp->icon = r;
|
|
||||||
+ // LVIR_LABEL is treated as LVIR_BOUNDS for LVM_GETSUBITEMRECT, but it doesn't matter because the label rect is uses isn't what we want anyway
|
|
||||||
+ // there's a hardocded 2-logical unit gap between the icon and text for subitems, AND the text starts being drawn (in the background) one bitmap margin to the right of that
|
|
||||||
+ // with normal items, there's no gap, and only the 2-logical unit gap after the background starts (TODO confirm this part)
|
|
||||||
+ // let's copy that to look nicer, even if it's not "accurate"
|
|
||||||
+ // TODO check against accessibility
|
|
||||||
+ dp->label = dp->bounds;
|
|
||||||
+ // because we want the 2 extra logical units to be included with the background, we don't include them here
|
|
||||||
+ dp->label.left = dp->icon.right;
|
|
||||||
+ return S_OK;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static LRESULT onNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm)
|
|
||||||
{
|
|
||||||
uiprivTableColumnParams *p;
|
|
||||||
uiTableData *data;
|
|
||||||
double r, g, b, a;
|
|
||||||
+ uiprivSubitemDrawParams dp;
|
|
||||||
LRESULT ret;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
@@ -193,7 +253,12 @@ DrawTextW(nm->nmcd.hdc, L"Part", -1,
|
|
||||||
ret = CDRF_DODEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
- hr = uiprivNM_CUSTOMDRAWImagesCheckboxes(t, nm, &ret);
|
|
||||||
+ ZeroMemory(&dp, sizeof (uiprivSubitemDrawParams));
|
|
||||||
+ hr = fillSubitemDrawParams(t->hwnd, nm, &dp);
|
|
||||||
+ if (hr != S_OK) {
|
|
||||||
+ // TODO
|
|
||||||
+ }
|
|
||||||
+ hr = uiprivNM_CUSTOMDRAWImagesCheckboxes(t, nm, &dp, &ret);
|
|
||||||
if (hr != S_OK) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
diff --git a/windows/table.hpp b/windows/table.hpp
|
|
||||||
index 0be01d8f..2f4f6936 100644
|
|
||||||
--- a/windows/table.hpp
|
|
||||||
+++ b/windows/table.hpp
|
|
||||||
@@ -43,8 +43,14 @@ struct uiTable {
|
|
||||||
// custom draw state
|
|
||||||
COLORREF clrItemText;
|
|
||||||
};
|
|
||||||
+typedef struct uiprivSubitemDrawParams uiprivSubitemDrawParams;
|
|
||||||
+struct uiprivSubitemDrawParams {
|
|
||||||
+ RECT bounds;
|
|
||||||
+ RECT icon;
|
|
||||||
+ RECT label;
|
|
||||||
+};
|
|
||||||
|
|
||||||
// tableimages.cpp
|
|
||||||
extern HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uiprivTableColumnParams *p);
|
|
||||||
-extern HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult);
|
|
||||||
+extern HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp, LRESULT *lResult);
|
|
||||||
extern HRESULT uiprivTableSetupImagesCheckboxes(uiTable *t);
|
|
||||||
diff --git a/windows/tableimages.cpp b/windows/tableimages.cpp
|
|
||||||
index a42307b1..14bae8c8 100644
|
|
||||||
--- a/windows/tableimages.cpp
|
|
||||||
+++ b/windows/tableimages.cpp
|
|
||||||
@@ -139,12 +139,11 @@ HRESULT uiprivLVN_GETDISPINFOImagesCheckboxes(uiTable *t, NMLVDISPINFOW *nm, uip
|
|
||||||
// however, there seems to be no way to do this natively, so we have to draw over ourselves (TODO?)
|
|
||||||
// hopefully the performance won't be too bad
|
|
||||||
// see also https://www.codeproject.com/Articles/79/Neat-Stuff-to-Do-in-List-Controls-Using-Custom-Dra
|
|
||||||
-HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *lResult)
|
|
||||||
+HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, uiprivSubitemDrawParams *dp, LRESULT *lResult)
|
|
||||||
{
|
|
||||||
uiprivTableColumnParams *p;
|
|
||||||
int index;
|
|
||||||
RECT r;
|
|
||||||
- RECT cellRect;
|
|
||||||
LONG yoff;
|
|
||||||
|
|
||||||
if (nm->nmcd.dwDrawStage == (CDDS_SUBITEM | CDDS_ITEMPREPAINT)) {
|
|
||||||
@@ -161,22 +160,9 @@ HRESULT uiprivNM_CUSTOMDRAWImagesCheckboxes(uiTable *t, NMLVCUSTOMDRAW *nm, LRES
|
|
||||||
|
|
||||||
index = checkboxIndex(t->model, nm->nmcd.dwItemSpec,
|
|
||||||
p->checkboxModelColumn, p->checkboxEditableColumn);
|
|
||||||
- ZeroMemory(&r, sizeof (RECT));
|
|
||||||
- r.left = LVIR_ICON;
|
|
||||||
- r.top = nm->iSubItem;
|
|
||||||
- if (SendMessageW(t->hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&r)) == 0) {
|
|
||||||
- logLastError(L"LVM_GETSUBITEMRECT");
|
|
||||||
- return E_FAIL;
|
|
||||||
- }
|
|
||||||
+ r = dp->icon;
|
|
||||||
// the real listview also does this :|
|
|
||||||
- ZeroMemory(&cellRect, sizeof (RECT));
|
|
||||||
- r.left = LVIR_BOUNDS;
|
|
||||||
- r.top = nm->iSubItem;
|
|
||||||
- if (SendMessageW(t->hwnd, LVM_GETSUBITEMRECT, nm->nmcd.dwItemSpec, (LPARAM) (&cellRect)) == 0) {
|
|
||||||
- logLastError(L"LVM_GETSUBITEMRECT cell");
|
|
||||||
- return E_FAIL;
|
|
||||||
- }
|
|
||||||
- yoff = ((cellRect.bottom - cellRect.top) - (r.bottom - r.top)) / 2;
|
|
||||||
+ yoff = ((dp->bounds.bottom - dp->bounds.top) - (r.bottom - r.top)) / 2;
|
|
||||||
r.top += yoff;
|
|
||||||
r.bottom += yoff;
|
|
||||||
if ((nm->nmcd.dwItemSpec%2)==0)
|
|
Loading…
Reference in New Issue