Integrated tablemetrics.cpp with tabledraw.cpp.
This commit is contained in:
parent
ec07b12295
commit
5ae45a1fcb
|
@ -54,6 +54,7 @@ list(APPEND _LIBUI_SOURCES
|
||||||
windows/tabledispinfo.cpp
|
windows/tabledispinfo.cpp
|
||||||
windows/tabledraw.cpp
|
windows/tabledraw.cpp
|
||||||
windows/tableediting.cpp
|
windows/tableediting.cpp
|
||||||
|
windows/tablemetrics.cpp
|
||||||
windows/tabpage.cpp
|
windows/tabpage.cpp
|
||||||
windows/text.cpp
|
windows/text.cpp
|
||||||
windows/utf16.cpp
|
windows/utf16.cpp
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct uiTable {
|
||||||
// TODO document all this
|
// TODO document all this
|
||||||
std::map<std::pair<int, int>, LONG> *indeterminatePositions;
|
std::map<std::pair<int, int>, LONG> *indeterminatePositions;
|
||||||
BOOL inLButtonDown;
|
BOOL inLButtonDown;
|
||||||
|
// TODO is this even necessary? it seems NM_CLICK is not sent if NM_DBLCLICK or LVN_ITEMACTIVATE (one of the two) happens...
|
||||||
BOOL inDoubleClickTimer;
|
BOOL inDoubleClickTimer;
|
||||||
HWND edit;
|
HWND edit;
|
||||||
int editedItem;
|
int editedItem;
|
||||||
|
@ -52,3 +53,27 @@ extern HRESULT uiprivUpdateImageListSize(uiTable *t);
|
||||||
extern HRESULT uiprivTableHandleNM_CLICK(uiTable *t, NMITEMACTIVATE *nm, LRESULT *lResult);
|
extern HRESULT uiprivTableHandleNM_CLICK(uiTable *t, NMITEMACTIVATE *nm, LRESULT *lResult);
|
||||||
extern HRESULT uiprivTableFinishEditingText(uiTable *t);
|
extern HRESULT uiprivTableFinishEditingText(uiTable *t);
|
||||||
extern HRESULT uiprivTableAbortEditingText(uiTable *t);
|
extern HRESULT uiprivTableAbortEditingText(uiTable *t);
|
||||||
|
|
||||||
|
// tablemetrics.cpp
|
||||||
|
typedef struct uiprivTableMetrics uiprivTableMetrics;
|
||||||
|
struct uiprivTableMetrics {
|
||||||
|
BOOL hasText;
|
||||||
|
BOOL hasImage;
|
||||||
|
BOOL focused;
|
||||||
|
BOOL selected;
|
||||||
|
|
||||||
|
RECT itemBounds;
|
||||||
|
RECT itemIcon;
|
||||||
|
RECT itemLabel;
|
||||||
|
RECT subitemBounds;
|
||||||
|
RECT subitemIcon;
|
||||||
|
RECT subitemLabel;
|
||||||
|
|
||||||
|
LRESULT bitmapMargin;
|
||||||
|
int cxIcon;
|
||||||
|
int cyIcon;
|
||||||
|
|
||||||
|
RECT realTextBackground;
|
||||||
|
RECT realTextRect;
|
||||||
|
};
|
||||||
|
extern HRESULT uiprivTableGetMetrics(uiTable *t, int iItem, int iSubItem, uiprivTableMetrics **mout);
|
||||||
|
|
|
@ -2,25 +2,19 @@
|
||||||
#include "uipriv_windows.hpp"
|
#include "uipriv_windows.hpp"
|
||||||
#include "table.hpp"
|
#include "table.hpp"
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
#define cellValue(model, row, column) ((*((model)->mh->CellValue))((model)->mh, (model), (row), (column)))
|
||||||
|
|
||||||
struct drawState {
|
struct drawState {
|
||||||
uiTable *t;
|
uiTable *t;
|
||||||
uiTableModel *m;
|
uiTableModel *model;
|
||||||
uiprivTableColumnParams *p;
|
uiprivTableColumnParams *p;
|
||||||
|
|
||||||
HDC dc;
|
HDC dc;
|
||||||
int iItem;
|
int iItem;
|
||||||
int iSubItem;
|
int iSubItem;
|
||||||
BOOL hasText;
|
|
||||||
BOOL hasImage;
|
|
||||||
BOOL selected;
|
|
||||||
BOOL focused;
|
|
||||||
|
|
||||||
RECT itemBounds;
|
uiprivTableMetrics *m;
|
||||||
RECT itemIcon;
|
|
||||||
RECT itemLabel;
|
|
||||||
RECT subitemBounds;
|
|
||||||
RECT subitemIcon;
|
|
||||||
RECT subitemLabel;
|
|
||||||
|
|
||||||
COLORREF bgColor;
|
COLORREF bgColor;
|
||||||
HBRUSH bgBrush;
|
HBRUSH bgBrush;
|
||||||
|
@ -28,52 +22,19 @@ struct drawState {
|
||||||
COLORREF textColor;
|
COLORREF textColor;
|
||||||
HBRUSH textBrush;
|
HBRUSH textBrush;
|
||||||
BOOL freeTextBrush;
|
BOOL freeTextBrush;
|
||||||
|
|
||||||
LRESULT bitmapMargin;
|
|
||||||
int cxIcon;
|
|
||||||
int cyIcon;
|
|
||||||
|
|
||||||
RECT realTextRect;
|
|
||||||
RECT focusRect;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static HRESULT computeOtherRectsAndDrawBackgrounds(struct drawState *s)
|
static HRESULT drawBackgrounds(struct drawState *s)
|
||||||
{
|
{
|
||||||
RECT r;
|
if (s->m->hasImage)
|
||||||
|
if (FillRect(s->dc, &(s->m->subitemIcon), GetSysColorBrush(COLOR_WINDOW)) == 0) {
|
||||||
r = s->subitemLabel;
|
|
||||||
if (!s->hasText && !s->hasImage)
|
|
||||||
r = s->subitemBounds;
|
|
||||||
else if (!s->hasImage && s->iSubItem != 0)
|
|
||||||
// By default, this will include images; we're not drawing
|
|
||||||
// images, so we will manually draw over the image area.
|
|
||||||
// There's a second part to this; see below.
|
|
||||||
r.left = s->subitemBounds.left;
|
|
||||||
|
|
||||||
if (s->hasImage)
|
|
||||||
if (FillRect(s->dc, &(s->subitemIcon), GetSysColorBrush(COLOR_WINDOW)) == 0) {
|
|
||||||
logLastError(L"FillRect() icon");
|
logLastError(L"FillRect() icon");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
if (FillRect(s->dc, &r, s->bgBrush) == 0) {
|
if (FillRect(s->dc, &(s->m->realTextBackground), s->bgBrush) == 0) {
|
||||||
logLastError(L"FillRect()");
|
logLastError(L"FillRect()");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
UnionRect(&(s->focusRect), &(s->focusRect), &r);
|
|
||||||
|
|
||||||
s->realTextRect = r;
|
|
||||||
// TODO confirm whether this really happens on column 0 as well
|
|
||||||
if (s->hasImage && s->iSubItem != 0)
|
|
||||||
// Normally there's this many hard-coded logical units
|
|
||||||
// of blank space, followed by the background, followed
|
|
||||||
// by a bitmap margin's worth of space. This looks bad,
|
|
||||||
// so we overrule that to start the background immediately
|
|
||||||
// and the text after the hard-coded amount.
|
|
||||||
s->realTextRect.left += 2;
|
|
||||||
else if (s->iSubItem != 0)
|
|
||||||
// In the case of subitem text without an image, we draw
|
|
||||||
// text one bitmap margin away from the left edge.
|
|
||||||
s->realTextRect.left += s->bitmapMargin;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,11 +71,11 @@ static HRESULT drawImagePart(struct drawState *s)
|
||||||
if (s->p->imageModelColumn == -1)
|
if (s->p->imageModelColumn == -1)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->imageModelColumn);
|
data = cellValue(s->model, s->iItem, s->p->imageModelColumn);
|
||||||
wb = uiprivImageAppropriateForDC(uiTableDataImage(data), s->dc);
|
wb = uiprivImageAppropriateForDC(uiTableDataImage(data), s->dc);
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
|
|
||||||
hr = uiprivWICToGDI(wb, s->dc, s->cxIcon, s->cyIcon, &b);
|
hr = uiprivWICToGDI(wb, s->dc, s->m->cxIcon, s->m->cyIcon, &b);
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
return hr;
|
return hr;
|
||||||
// TODO rewrite this condition to make more sense; possibly swap the if and else blocks too
|
// TODO rewrite this condition to make more sense; possibly swap the if and else blocks too
|
||||||
|
@ -132,12 +93,12 @@ static HRESULT drawImagePart(struct drawState *s)
|
||||||
// TODO error check
|
// TODO error check
|
||||||
DeleteObject(b);
|
DeleteObject(b);
|
||||||
|
|
||||||
r = s->subitemIcon;
|
r = s->m->subitemIcon;
|
||||||
r.right = r.left + s->cxIcon;
|
r.right = r.left + s->m->cxIcon;
|
||||||
r.bottom = r.top + s->cyIcon;
|
r.bottom = r.top + s->m->cyIcon;
|
||||||
centerImageRect(&r, &(s->subitemIcon));
|
centerImageRect(&r, &(s->m->subitemIcon));
|
||||||
fStyle = ILD_NORMAL;
|
fStyle = ILD_NORMAL;
|
||||||
if (s->selected)
|
if (s->m->selected)
|
||||||
fStyle = ILD_SELECTED;
|
fStyle = ILD_SELECTED;
|
||||||
if (ImageList_Draw(s->t->imagelist, 0,
|
if (ImageList_Draw(s->t->imagelist, 0,
|
||||||
s->dc, r.left, r.top, fStyle) == 0) {
|
s->dc, r.left, r.top, fStyle) == 0) {
|
||||||
|
@ -156,7 +117,7 @@ static HRESULT drawUnthemedCheckbox(struct drawState *s, int checked, int enable
|
||||||
RECT r;
|
RECT r;
|
||||||
UINT state;
|
UINT state;
|
||||||
|
|
||||||
r = s->subitemIcon;
|
r = s->m->subitemIcon;
|
||||||
// this is what the actual list view LVS_EX_CHECKBOXES code does to size the checkboxes
|
// this is what the actual list view LVS_EX_CHECKBOXES code does to size the checkboxes
|
||||||
// TODO reverify the initial size
|
// TODO reverify the initial size
|
||||||
r.right = r.left + GetSystemMetrics(SM_CXSMICON);
|
r.right = r.left + GetSystemMetrics(SM_CXSMICON);
|
||||||
|
@ -168,7 +129,7 @@ static HRESULT drawUnthemedCheckbox(struct drawState *s, int checked, int enable
|
||||||
r.right++;
|
r.right++;
|
||||||
r.bottom++;
|
r.bottom++;
|
||||||
|
|
||||||
centerImageRect(&r, &(s->subitemIcon));
|
centerImageRect(&r, &(s->m->subitemIcon));
|
||||||
state = DFCS_BUTTONCHECK | DFCS_FLAT;
|
state = DFCS_BUTTONCHECK | DFCS_FLAT;
|
||||||
if (checked)
|
if (checked)
|
||||||
state |= DFCS_CHECKED;
|
state |= DFCS_CHECKED;
|
||||||
|
@ -195,11 +156,11 @@ static HRESULT drawThemedCheckbox(struct drawState *s, HTHEME theme, int checked
|
||||||
logHRESULT(L"GetThemePartSize()", hr);
|
logHRESULT(L"GetThemePartSize()", hr);
|
||||||
return hr; // TODO fall back?
|
return hr; // TODO fall back?
|
||||||
}
|
}
|
||||||
r = s->subitemIcon;
|
r = s->m->subitemIcon;
|
||||||
r.right = r.left + size.cx;
|
r.right = r.left + size.cx;
|
||||||
r.bottom = r.top + size.cy;
|
r.bottom = r.top + size.cy;
|
||||||
|
|
||||||
centerImageRect(&r, &(s->subitemIcon));
|
centerImageRect(&r, &(s->m->subitemIcon));
|
||||||
if (!checked && enabled)
|
if (!checked && enabled)
|
||||||
state = CBS_UNCHECKEDNORMAL;
|
state = CBS_UNCHECKEDNORMAL;
|
||||||
else if (checked && enabled)
|
else if (checked && enabled)
|
||||||
|
@ -228,7 +189,7 @@ static HRESULT drawCheckboxPart(struct drawState *s)
|
||||||
if (s->p->checkboxModelColumn == -1)
|
if (s->p->checkboxModelColumn == -1)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->checkboxModelColumn);
|
data = cellValue(s->model, s->iItem, s->p->checkboxModelColumn);
|
||||||
checked = uiTableDataInt(data);
|
checked = uiTableDataInt(data);
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
switch (s->p->checkboxEditableColumn) {
|
switch (s->p->checkboxEditableColumn) {
|
||||||
|
@ -239,7 +200,7 @@ static HRESULT drawCheckboxPart(struct drawState *s)
|
||||||
enabled = 1;
|
enabled = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->checkboxEditableColumn);
|
data = cellValue(s->model, s->iItem, s->p->checkboxEditableColumn);
|
||||||
enabled = uiTableDataInt(data);
|
enabled = uiTableDataInt(data);
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +231,7 @@ static HRESULT drawTextPart(struct drawState *s)
|
||||||
uiTableData *data;
|
uiTableData *data;
|
||||||
WCHAR *wstr;
|
WCHAR *wstr;
|
||||||
|
|
||||||
if (!s->hasText)
|
if (!s->m->hasText)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
prevText = SetTextColor(s->dc, s->textColor);
|
prevText = SetTextColor(s->dc, s->textColor);
|
||||||
|
@ -284,14 +245,14 @@ static HRESULT drawTextPart(struct drawState *s)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->textModelColumn);
|
data = cellValue(s->model, s->iItem, s->p->textModelColumn);
|
||||||
wstr = toUTF16(uiTableDataString(data));
|
wstr = toUTF16(uiTableDataString(data));
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
// These flags are a menagerie of flags from various sources:
|
// These flags are a menagerie of flags from various sources:
|
||||||
// guessing, the Windows 2000 source leak, various custom
|
// guessing, the Windows 2000 source leak, various custom
|
||||||
// draw examples on the web, etc.
|
// draw examples on the web, etc.
|
||||||
// TODO find the real correct flags
|
// TODO find the real correct flags
|
||||||
if (DrawTextW(s->dc, wstr, -1, &(s->realTextRect), DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE | DT_NOPREFIX | DT_EDITCONTROL) == 0) {
|
if (DrawTextW(s->dc, wstr, -1, &(s->m->realTextRect), DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE | DT_NOPREFIX | DT_EDITCONTROL) == 0) {
|
||||||
uiprivFree(wstr);
|
uiprivFree(wstr);
|
||||||
logLastError(L"DrawTextW()");
|
logLastError(L"DrawTextW()");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
@ -337,7 +298,7 @@ static HRESULT drawProgressBarPart(struct drawState *s)
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
r = s->subitemBounds;
|
r = s->m->subitemBounds;
|
||||||
// this sets the height of the progressbar and vertically centers it in one fell swoop
|
// this sets the height of the progressbar and vertically centers it in one fell swoop
|
||||||
r.top += (r.bottom - tm.tmHeight - r.top) / 2;
|
r.top += (r.bottom - tm.tmHeight - r.top) / 2;
|
||||||
r.bottom = r.top + tm.tmHeight;
|
r.bottom = r.top + tm.tmHeight;
|
||||||
|
@ -367,7 +328,7 @@ static HRESULT drawProgressBarPart(struct drawState *s)
|
||||||
HBRUSH brush, prevBrush;
|
HBRUSH brush, prevBrush;
|
||||||
|
|
||||||
sysColor = COLOR_HIGHLIGHT;
|
sysColor = COLOR_HIGHLIGHT;
|
||||||
if (s->selected)
|
if (s->m->selected)
|
||||||
sysColor = COLOR_HIGHLIGHTTEXT;
|
sysColor = COLOR_HIGHLIGHTTEXT;
|
||||||
|
|
||||||
// TODO check errors everywhere
|
// TODO check errors everywhere
|
||||||
|
@ -438,7 +399,7 @@ static HRESULT drawButtonPart(struct drawState *s)
|
||||||
if (s->p->buttonModelColumn == -1)
|
if (s->p->buttonModelColumn == -1)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->buttonModelColumn);
|
data = cellValue(s->model, s->iItem, s->p->buttonModelColumn);
|
||||||
wstr = toUTF16(uiTableDataString(data));
|
wstr = toUTF16(uiTableDataString(data));
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
switch (s->p->buttonClickableModelColumn) {
|
switch (s->p->buttonClickableModelColumn) {
|
||||||
|
@ -449,7 +410,7 @@ static HRESULT drawButtonPart(struct drawState *s)
|
||||||
enabled = 1;
|
enabled = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, s->p->checkboxEditableColumn);
|
data = cellValue(s->model, s->iItem, s->p->checkboxEditableColumn);
|
||||||
enabled = uiTableDataInt(data);
|
enabled = uiTableDataInt(data);
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
}
|
}
|
||||||
|
@ -461,7 +422,7 @@ static HRESULT drawButtonPart(struct drawState *s)
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
r = s->subitemBounds;
|
r = s->m->subitemBounds;
|
||||||
|
|
||||||
if (theme != NULL) {
|
if (theme != NULL) {
|
||||||
int state;
|
int state;
|
||||||
|
@ -534,6 +495,10 @@ static HRESULT freeDrawState(struct drawState *s)
|
||||||
HRESULT hr, hrret;
|
HRESULT hr, hrret;
|
||||||
|
|
||||||
hrret = S_OK;
|
hrret = S_OK;
|
||||||
|
if (s->m != NULL) {
|
||||||
|
uiprivFree(s->m);
|
||||||
|
s->m = NULL;
|
||||||
|
}
|
||||||
if (s->freeTextBrush) {
|
if (s->freeTextBrush) {
|
||||||
if (DeleteObject(s->textBrush) == 0) {
|
if (DeleteObject(s->textBrush) == 0) {
|
||||||
logLastError(L"DeleteObject()");
|
logLastError(L"DeleteObject()");
|
||||||
|
@ -553,20 +518,6 @@ static HRESULT freeDrawState(struct drawState *s)
|
||||||
return hrret;
|
return hrret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT itemRect(HRESULT hr, uiTable *t, UINT uMsg, WPARAM wParam, LONG left, LONG top, LRESULT bad, RECT *r)
|
|
||||||
{
|
|
||||||
if (hr != S_OK)
|
|
||||||
return hr;
|
|
||||||
ZeroMemory(r, sizeof (RECT));
|
|
||||||
r->left = left;
|
|
||||||
r->top = top;
|
|
||||||
if (SendMessageW(t->hwnd, uMsg, wParam, (LPARAM) r) == bad) {
|
|
||||||
logLastError(L"itemRect() message");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static COLORREF blend(COLORREF base, double r, double g, double b, double a)
|
static COLORREF blend(COLORREF base, double r, double g, double b, double a)
|
||||||
{
|
{
|
||||||
double br, bg, bb;
|
double br, bg, bb;
|
||||||
|
@ -591,48 +542,18 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
||||||
|
|
||||||
ZeroMemory(s, sizeof (struct drawState));
|
ZeroMemory(s, sizeof (struct drawState));
|
||||||
s->t = t;
|
s->t = t;
|
||||||
s->m = t->model;
|
s->model = t->model;
|
||||||
s->p = p;
|
s->p = p;
|
||||||
|
|
||||||
s->dc = nm->nmcd.hdc;
|
s->dc = nm->nmcd.hdc;
|
||||||
s->iItem = nm->nmcd.dwItemSpec;
|
s->iItem = nm->nmcd.dwItemSpec;
|
||||||
s->iSubItem = nm->iSubItem;
|
s->iSubItem = nm->iSubItem;
|
||||||
s->hasText = p->textModelColumn != -1;
|
|
||||||
s->hasImage = (p->imageModelColumn != -1) || (p->checkboxModelColumn != -1);
|
|
||||||
// nm->nmcd.uItemState CDIS_SELECTED is unreliable for the
|
|
||||||
// listview configuration we have, so we must do this.
|
|
||||||
state = SendMessageW(t->hwnd, LVM_GETITEMSTATE, nm->nmcd.dwItemSpec, LVIS_SELECTED);
|
|
||||||
s->selected = (state & LVIS_SELECTED) != 0;
|
|
||||||
s->focused = (nm->nmcd.uItemState & CDIS_FOCUS) != 0;
|
|
||||||
|
|
||||||
// TODO check LRESULT bad parameters here
|
hr = uiprivTableGetMetrics(t, s->iItem, s->iSubItem, &(s->m));
|
||||||
hr = itemRect(S_OK, t, LVM_GETITEMRECT, s->iItem,
|
|
||||||
LVIR_BOUNDS, 0, FALSE, &(s->itemBounds));
|
|
||||||
hr = itemRect(hr, t, LVM_GETITEMRECT, s->iItem,
|
|
||||||
LVIR_ICON, 0, FALSE, &(s->itemIcon));
|
|
||||||
hr = itemRect(hr, t, LVM_GETITEMRECT, s->iItem,
|
|
||||||
LVIR_LABEL, 0, FALSE, &(s->itemLabel));
|
|
||||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, s->iItem,
|
|
||||||
LVIR_BOUNDS, s->iSubItem, 0, &(s->subitemBounds));
|
|
||||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, s->iItem,
|
|
||||||
LVIR_ICON, s->iSubItem, 0, &(s->subitemIcon));
|
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
goto fail;
|
goto fail;
|
||||||
// LVM_GETSUBITEMRECT treats LVIR_LABEL as the same as
|
|
||||||
// LVIR_BOUNDS, so we can't use that directly. Instead, let's
|
|
||||||
// assume the text is immediately after the icon. The correct
|
|
||||||
// rect will be determined by
|
|
||||||
// computeOtherRectsAndDrawBackgrounds() above.
|
|
||||||
s->subitemLabel = s->subitemBounds;
|
|
||||||
s->subitemLabel.left = s->subitemIcon.right;
|
|
||||||
// And on iSubItem == 0, LVIF_GETSUBITEMRECT still includes
|
|
||||||
// all the subitems, which we don't want.
|
|
||||||
if (s->iSubItem == 0) {
|
|
||||||
s->subitemBounds.right = s->itemLabel.right;
|
|
||||||
s->subitemLabel.right = s->itemLabel.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->selected) {
|
if (s->m->selected) {
|
||||||
s->bgColor = GetSysColor(COLOR_HIGHLIGHT);
|
s->bgColor = GetSysColor(COLOR_HIGHLIGHT);
|
||||||
s->bgBrush = GetSysColorBrush(COLOR_HIGHLIGHT);
|
s->bgBrush = GetSysColorBrush(COLOR_HIGHLIGHT);
|
||||||
s->textColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
s->textColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
||||||
|
@ -644,7 +565,7 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
||||||
s->bgColor = GetSysColor(COLOR_WINDOW);
|
s->bgColor = GetSysColor(COLOR_WINDOW);
|
||||||
s->bgBrush = GetSysColorBrush(COLOR_WINDOW);
|
s->bgBrush = GetSysColorBrush(COLOR_WINDOW);
|
||||||
if (t->backgroundColumn != -1) {
|
if (t->backgroundColumn != -1) {
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, t->backgroundColumn);
|
data = cellValue(s->model, s->iItem, t->backgroundColumn);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
uiTableDataColor(data, &r, &g, &b, &a);
|
uiTableDataColor(data, &r, &g, &b, &a);
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
|
@ -661,7 +582,7 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
||||||
s->textColor = GetSysColor(COLOR_WINDOWTEXT);
|
s->textColor = GetSysColor(COLOR_WINDOWTEXT);
|
||||||
s->textBrush = GetSysColorBrush(COLOR_WINDOWTEXT);
|
s->textBrush = GetSysColorBrush(COLOR_WINDOWTEXT);
|
||||||
if (p->textParams.ColorModelColumn != -1) {
|
if (p->textParams.ColorModelColumn != -1) {
|
||||||
data = (*(s->m->mh->CellValue))(s->m->mh, s->m, s->iItem, p->textParams.ColorModelColumn);
|
data = cellValue(s->model, s->iItem, p->textParams.ColorModelColumn);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
uiTableDataColor(data, &r, &g, &b, &a);
|
uiTableDataColor(data, &r, &g, &b, &a);
|
||||||
uiFreeTableData(data);
|
uiFreeTableData(data);
|
||||||
|
@ -677,14 +598,6 @@ static HRESULT fillDrawState(struct drawState *s, uiTable *t, NMLVCUSTOMDRAW *nm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header = (HWND) SendMessageW(t->hwnd, LVM_GETHEADER, 0, 0);
|
|
||||||
s->bitmapMargin = SendMessageW(header, HDM_GETBITMAPMARGIN, 0, 0);
|
|
||||||
if (ImageList_GetIconSize(t->imagelist, &(s->cxIcon), &(s->cyIcon)) == 0) {
|
|
||||||
logLastError(L"ImageList_GetIconSize()");
|
|
||||||
hr = E_FAIL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
fail:
|
fail:
|
||||||
// ignore the error; we need to return the one we got above
|
// ignore the error; we need to return the one we got above
|
||||||
|
@ -716,7 +629,7 @@ HRESULT uiprivTableHandleNM_CUSTOMDRAW(uiTable *t, NMLVCUSTOMDRAW *nm, LRESULT *
|
||||||
hr = fillDrawState(&s, t, nm, p);
|
hr = fillDrawState(&s, t, nm, p);
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
return hr;
|
return hr;
|
||||||
hr = computeOtherRectsAndDrawBackgrounds(&s);
|
hr = drawBackgrounds(&s);
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
goto fail;
|
goto fail;
|
||||||
hr = drawImagePart(&s);
|
hr = drawImagePart(&s);
|
||||||
|
|
|
@ -2,33 +2,6 @@
|
||||||
#include "uipriv_windows.hpp"
|
#include "uipriv_windows.hpp"
|
||||||
#include "table.hpp"
|
#include "table.hpp"
|
||||||
|
|
||||||
struct uiprivTableMetrics {
|
|
||||||
uiTable *t;
|
|
||||||
uiTableModel *m;
|
|
||||||
uiprivTableColumnParams *p;
|
|
||||||
|
|
||||||
int iItem;
|
|
||||||
int iSubItem;
|
|
||||||
BOOL hasText;
|
|
||||||
BOOL hasImage;
|
|
||||||
BOOL focused;
|
|
||||||
BOOL selected;
|
|
||||||
|
|
||||||
RECT itemBounds;
|
|
||||||
RECT itemIcon;
|
|
||||||
RECT itemLabel;
|
|
||||||
RECT subitemBounds;
|
|
||||||
RECT subitemIcon;
|
|
||||||
RECT subitemLabel;
|
|
||||||
|
|
||||||
LRESULT bitmapMargin;
|
|
||||||
int cxIcon;
|
|
||||||
int cyIcon;
|
|
||||||
|
|
||||||
RECT realTextBackground;
|
|
||||||
RECT realTextRect;
|
|
||||||
};
|
|
||||||
|
|
||||||
static HRESULT itemRect(HRESULT hr, uiTable *t, UINT uMsg, WPARAM wParam, LONG left, LONG top, LRESULT bad, RECT *r)
|
static HRESULT itemRect(HRESULT hr, uiTable *t, UINT uMsg, WPARAM wParam, LONG left, LONG top, LRESULT bad, RECT *r)
|
||||||
{
|
{
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
|
@ -46,6 +19,7 @@ static HRESULT itemRect(HRESULT hr, uiTable *t, UINT uMsg, WPARAM wParam, LONG l
|
||||||
HRESULT uiprivTableGetMetrics(uiTable *t, int iItem, int iSubItem, uiprivTableMetrics **mout)
|
HRESULT uiprivTableGetMetrics(uiTable *t, int iItem, int iSubItem, uiprivTableMetrics **mout)
|
||||||
{
|
{
|
||||||
uiprivTableMetrics *m;
|
uiprivTableMetrics *m;
|
||||||
|
uiprivTableColumnParams *p;
|
||||||
LRESULT state;
|
LRESULT state;
|
||||||
HWND header;
|
HWND header;
|
||||||
RECT r;
|
RECT r;
|
||||||
|
@ -55,29 +29,25 @@ HRESULT uiprivTableGetMetrics(uiTable *t, int iItem, int iSubItem, uiprivTableMe
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
m = uiprivNew(uiprivTableMetrics);
|
m = uiprivNew(uiprivTableMetrics);
|
||||||
m->t = t;
|
|
||||||
m->m = t->model;
|
|
||||||
m->p = (*(t->columns))[iSubItem];
|
|
||||||
|
|
||||||
m->iItem = iItem;
|
p = (*(t->columns))[iSubItem];
|
||||||
m->iSubItem = iSubItem;
|
m->hasText = p->textModelColumn != -1;
|
||||||
m->hasText = m->p->textModelColumn != -1;
|
m->hasImage = (p->imageModelColumn != -1) || (p->checkboxModelColumn != -1);
|
||||||
m->hasImage = (m->p->imageModelColumn != -1) || (m->p->checkboxModelColumn != -1);
|
|
||||||
state = SendMessageW(t->hwnd, LVM_GETITEMSTATE, iItem, LVIS_FOCUSED | LVIS_SELECTED);
|
state = SendMessageW(t->hwnd, LVM_GETITEMSTATE, iItem, LVIS_FOCUSED | LVIS_SELECTED);
|
||||||
m->focused = (state & LVIS_FOCUSED) != 0;
|
m->focused = (state & LVIS_FOCUSED) != 0;
|
||||||
m->selected = (state & LVIS_SELECTED) != 0;
|
m->selected = (state & LVIS_SELECTED) != 0;
|
||||||
|
|
||||||
// TODO check LRESULT bad parameters here
|
// TODO check LRESULT bad parameters here
|
||||||
hr = itemRect(S_OK, t, LVM_GETITEMRECT, s->iItem,
|
hr = itemRect(S_OK, t, LVM_GETITEMRECT, iItem,
|
||||||
LVIR_BOUNDS, 0, FALSE, &(m->itemBounds));
|
LVIR_BOUNDS, 0, FALSE, &(m->itemBounds));
|
||||||
hr = itemRect(hr, t, LVM_GETITEMRECT, s->iItem,
|
hr = itemRect(hr, t, LVM_GETITEMRECT, iItem,
|
||||||
LVIR_ICON, 0, FALSE, &(m->itemIcon));
|
LVIR_ICON, 0, FALSE, &(m->itemIcon));
|
||||||
hr = itemRect(hr, t, LVM_GETITEMRECT, s->iItem,
|
hr = itemRect(hr, t, LVM_GETITEMRECT, iItem,
|
||||||
LVIR_LABEL, 0, FALSE, &(m->itemLabel));
|
LVIR_LABEL, 0, FALSE, &(m->itemLabel));
|
||||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, s->iItem,
|
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, iItem,
|
||||||
LVIR_BOUNDS, s->iSubItem, 0, &(m->subitemBounds));
|
LVIR_BOUNDS, iSubItem, 0, &(m->subitemBounds));
|
||||||
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, s->iItem,
|
hr = itemRect(hr, t, LVM_GETSUBITEMRECT, iItem,
|
||||||
LVIR_ICON, s->iSubItem, 0, &(m->subitemIcon));
|
LVIR_ICON, iSubItem, 0, &(m->subitemIcon));
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
goto fail;
|
goto fail;
|
||||||
// LVM_GETSUBITEMRECT treats LVIR_LABEL as the same as
|
// LVM_GETSUBITEMRECT treats LVIR_LABEL as the same as
|
||||||
|
@ -104,7 +74,7 @@ HRESULT uiprivTableGetMetrics(uiTable *t, int iItem, int iSubItem, uiprivTableMe
|
||||||
|
|
||||||
r = m->subitemLabel;
|
r = m->subitemLabel;
|
||||||
if (!m->hasText && !m->hasImage)
|
if (!m->hasText && !m->hasImage)
|
||||||
r = s->subitemBounds;
|
r = m->subitemBounds;
|
||||||
else if (!m->hasImage && iSubItem != 0)
|
else if (!m->hasImage && iSubItem != 0)
|
||||||
// By default, this will include images; we're not drawing
|
// By default, this will include images; we're not drawing
|
||||||
// images, so we will manually draw over the image area.
|
// images, so we will manually draw over the image area.
|
||||||
|
|
Loading…
Reference in New Issue