Don't redraw if no information has changed.
Fixed endless redraw loop if app using callback for images and/or text. Keep color changes made by app for the current draw cycle.
This commit is contained in:
parent
a8d8b52d6f
commit
71be094420
|
@ -241,6 +241,39 @@ TREEVIEW_GetItemIndex(TREEVIEW_INFO *infoPtr, HTREEITEM handle)
|
|||
return DPA_GetPtrIndex(infoPtr->items, handle);
|
||||
}
|
||||
|
||||
/* Checks if item has changed and needs to be redrawn */
|
||||
static inline BOOL item_changed (TREEVIEW_ITEM *tiOld, TREEVIEW_ITEM *tiNew, LPTVITEMEXW tvChange)
|
||||
{
|
||||
/* Number of children has changed */
|
||||
if ((tvChange->mask & TVIF_CHILDREN) && (tiOld->cChildren != tiNew->cChildren))
|
||||
return TRUE;
|
||||
|
||||
/* Image has changed and it's not a callback */
|
||||
if ((tvChange->mask & TVIF_IMAGE) && (tiOld->iImage != tiNew->iImage) &&
|
||||
tiNew->iImage != I_IMAGECALLBACK)
|
||||
return TRUE;
|
||||
|
||||
/* Selected image has changed and it's not a callback */
|
||||
if ((tvChange->mask & TVIF_SELECTEDIMAGE) && (tiOld->iSelectedImage != tiNew->iSelectedImage) &&
|
||||
tiNew->iSelectedImage != I_IMAGECALLBACK)
|
||||
return TRUE;
|
||||
|
||||
/* Text has changed and it's not a callback */
|
||||
if ((tvChange->mask & TVIF_TEXT) && (tiOld->pszText != tiNew->pszText) &&
|
||||
tiNew->pszText != LPSTR_TEXTCALLBACKW)
|
||||
return TRUE;
|
||||
|
||||
/* Indent has changed */
|
||||
if ((tvChange->mask & TVIF_INTEGRAL) && (tiOld->iIntegral != tiNew->iIntegral))
|
||||
return TRUE;
|
||||
|
||||
/* Item state has changed */
|
||||
if ((tvChange->mask & TVIF_STATE) && ((tiOld->state ^ tiNew->state) & tvChange->stateMask ))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* This method checks that handle is an item for this tree.
|
||||
*/
|
||||
|
@ -616,10 +649,10 @@ TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr, DWORD dwDrawStage,
|
|||
|
||||
static BOOL
|
||||
TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
|
||||
TREEVIEW_ITEM *wineItem, UINT uItemDrawState)
|
||||
TREEVIEW_ITEM *wineItem, UINT uItemDrawState,
|
||||
NMTVCUSTOMDRAW *nmcdhdr)
|
||||
{
|
||||
HWND hwnd = infoPtr->hwnd;
|
||||
NMTVCUSTOMDRAW nmcdhdr;
|
||||
LPNMCUSTOMDRAW nmcd;
|
||||
DWORD dwDrawStage, dwItemSpec;
|
||||
UINT uItemState;
|
||||
|
@ -635,7 +668,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
|
|||
if (wineItem == infoPtr->hotItem)
|
||||
uItemState |= CDIS_HOT;
|
||||
|
||||
nmcd = &nmcdhdr.nmcd;
|
||||
nmcd = &nmcdhdr->nmcd;
|
||||
nmcd->hdr.hwndFrom = hwnd;
|
||||
nmcd->hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
|
||||
nmcd->hdr.code = NM_CUSTOMDRAW;
|
||||
|
@ -645,9 +678,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
|
|||
nmcd->dwItemSpec = dwItemSpec;
|
||||
nmcd->uItemState = uItemState;
|
||||
nmcd->lItemlParam = wineItem->lParam;
|
||||
nmcdhdr.clrText = infoPtr->clrText;
|
||||
nmcdhdr.clrTextBk = infoPtr->clrBk;
|
||||
nmcdhdr.iLevel = wineItem->iLevel;
|
||||
nmcdhdr->iLevel = wineItem->iLevel;
|
||||
|
||||
TRACE("drawstage:%lx hdc:%p item:%lx, itemstate:%x, lItemlParam:%lx\n",
|
||||
nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
|
||||
|
@ -655,7 +686,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
|
|||
|
||||
retval = TREEVIEW_SendRealNotify(infoPtr,
|
||||
(WPARAM)nmcd->hdr.idFrom,
|
||||
(LPARAM)&nmcdhdr);
|
||||
(LPARAM)nmcdhdr);
|
||||
|
||||
return (BOOL)retval;
|
||||
}
|
||||
|
@ -2114,9 +2145,8 @@ TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW)
|
|||
/* The refresh updates everything, but we can't wait until then. */
|
||||
TREEVIEW_ComputeItemInternalMetrics(infoPtr, wineItem);
|
||||
|
||||
/* if any of the items values changed, redraw the item */
|
||||
if(memcmp(&originalItem, wineItem, sizeof(TREEVIEW_ITEM)) ||
|
||||
(tvItem->stateMask & TVIS_BOLD))
|
||||
/* if any of the item's values changed and it's not a callback, redraw the item */
|
||||
if (item_changed(&originalItem, wineItem, tvItem))
|
||||
{
|
||||
if (tvItem->mask & TVIF_INTEGRAL)
|
||||
{
|
||||
|
@ -2265,10 +2295,14 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
|
|||
BOOL lar = ((infoPtr->dwStyle
|
||||
& (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
|
||||
> TVS_LINESATROOT);
|
||||
HBRUSH hbr, hbrOld;
|
||||
|
||||
if (!lar && item->iLevel == 0)
|
||||
return;
|
||||
|
||||
hbr = CreateSolidBrush(infoPtr->clrBk);
|
||||
hbrOld = SelectObject(hdc, hbr);
|
||||
|
||||
centerx = (item->linesOffset + item->stateOffset) / 2;
|
||||
centery = (item->rect.top + item->rect.bottom) / 2;
|
||||
|
||||
|
@ -2335,15 +2369,10 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
|
|||
|
||||
HPEN hNewPen = CreatePen(PS_SOLID, 0, infoPtr->clrLine);
|
||||
HPEN hOldPen = SelectObject(hdc, hNewPen);
|
||||
HBRUSH hbr = CreateSolidBrush(infoPtr->clrBk);
|
||||
HBRUSH hbrOld = SelectObject(hdc, hbr);
|
||||
|
||||
Rectangle(hdc, centerx - rectsize - 1, centery - rectsize - 1,
|
||||
centerx + rectsize + 2, centery + rectsize + 2);
|
||||
|
||||
SelectObject(hdc, hbrOld);
|
||||
DeleteObject(hbr);
|
||||
|
||||
SelectObject(hdc, hOldPen);
|
||||
DeleteObject(hNewPen);
|
||||
|
||||
|
@ -2373,6 +2402,8 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
|
|||
}
|
||||
}
|
||||
}
|
||||
SelectObject(hdc, hbrOld);
|
||||
DeleteObject(hbr);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2380,12 +2411,50 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
|
|||
{
|
||||
INT cditem;
|
||||
HFONT hOldFont;
|
||||
COLORREF oldTextColor, oldTextBkColor;
|
||||
int centery;
|
||||
|
||||
hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
|
||||
BOOL inFocus = (GetFocus() == infoPtr->hwnd);
|
||||
NMTVCUSTOMDRAW nmcdhdr;
|
||||
|
||||
TREEVIEW_UpdateDispInfo(infoPtr, wineItem, CALLBACK_MASK_ALL);
|
||||
|
||||
/* - If item is drop target or it is selected and window is in focus -
|
||||
* use blue background (COLOR_HIGHLIGHT).
|
||||
* - If item is selected, window is not in focus, but it has style
|
||||
* TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE)
|
||||
* - Otherwise - use background color
|
||||
*/
|
||||
if ((wineItem->state & TVIS_DROPHILITED) || ((wineItem == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) ||
|
||||
((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) &&
|
||||
(inFocus || (infoPtr->dwStyle & TVS_SHOWSELALWAYS))))
|
||||
{
|
||||
if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
|
||||
{
|
||||
nmcdhdr.clrTextBk = GetSysColor(COLOR_HIGHLIGHT);
|
||||
nmcdhdr.clrText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
nmcdhdr.clrTextBk = GetSysColor(COLOR_BTNFACE);
|
||||
if (infoPtr->clrText == -1)
|
||||
nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
|
||||
else
|
||||
nmcdhdr.clrText = infoPtr->clrText;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nmcdhdr.clrTextBk = infoPtr->clrBk;
|
||||
if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem))
|
||||
nmcdhdr.clrText = comctl32_color.clrHighlight;
|
||||
else if (infoPtr->clrText == -1)
|
||||
nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
|
||||
else
|
||||
nmcdhdr.clrText = infoPtr->clrText;
|
||||
}
|
||||
|
||||
hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
|
||||
|
||||
/* The custom draw handler can query the text rectangle,
|
||||
* so get ready. */
|
||||
/* should already be known, set to 0 when changed */
|
||||
|
@ -2397,7 +2466,7 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
|
|||
if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW)
|
||||
{
|
||||
cditem = TREEVIEW_SendCustomDrawItemNotify
|
||||
(infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT);
|
||||
(infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT, &nmcdhdr);
|
||||
TRACE("prepaint:cditem-app returns 0x%x\n", cditem);
|
||||
|
||||
if (cditem & CDRF_SKIPDEFAULT)
|
||||
|
@ -2412,6 +2481,10 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
|
|||
|
||||
TREEVIEW_DrawItemLines(infoPtr, hdc, wineItem);
|
||||
|
||||
/* Set colors. Custom draw handler can change these so we do this after it. */
|
||||
oldTextColor = SetTextColor(hdc, nmcdhdr.clrText);
|
||||
oldTextBkColor = SetBkColor(hdc, nmcdhdr.clrTextBk);
|
||||
|
||||
centery = (wineItem->rect.top + wineItem->rect.bottom) / 2;
|
||||
|
||||
/*
|
||||
|
@ -2469,87 +2542,31 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
|
|||
{
|
||||
if (wineItem->pszText)
|
||||
{
|
||||
COLORREF oldTextColor = 0;
|
||||
INT oldBkMode;
|
||||
HBRUSH hbrBk = 0;
|
||||
BOOL inFocus = (GetFocus() == infoPtr->hwnd);
|
||||
RECT rcText;
|
||||
|
||||
oldBkMode = SetBkMode(hdc, TRANSPARENT);
|
||||
|
||||
/* - If item is drop target or it is selected and window is in focus -
|
||||
* use blue background (COLOR_HIGHLIGHT).
|
||||
* - If item is selected, window is not in focus, but it has style
|
||||
* TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE)
|
||||
* - Otherwise - don't fill background
|
||||
*/
|
||||
if ((wineItem->state & TVIS_DROPHILITED) || ((wineItem == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) ||
|
||||
((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) &&
|
||||
(inFocus || (infoPtr->dwStyle & TVS_SHOWSELALWAYS))))
|
||||
{
|
||||
if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
|
||||
{
|
||||
hbrBk = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
|
||||
oldTextColor =
|
||||
SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
||||
}
|
||||
else
|
||||
{
|
||||
hbrBk = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
||||
|
||||
if (infoPtr->clrText == -1)
|
||||
oldTextColor =
|
||||
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
||||
else
|
||||
oldTextColor = SetTextColor(hdc, infoPtr->clrText);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem))
|
||||
oldTextColor = SetTextColor(hdc, comctl32_color.clrHighlight);
|
||||
else if (infoPtr->clrText == -1)
|
||||
oldTextColor =
|
||||
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
|
||||
else
|
||||
oldTextColor = SetTextColor(hdc, infoPtr->clrText);
|
||||
}
|
||||
|
||||
rcText.top = wineItem->rect.top;
|
||||
rcText.bottom = wineItem->rect.bottom;
|
||||
rcText.left = wineItem->textOffset;
|
||||
rcText.right = rcText.left + wineItem->textWidth + 4;
|
||||
|
||||
if (hbrBk)
|
||||
{
|
||||
FillRect(hdc, &rcText, hbrBk);
|
||||
DeleteObject(hbrBk);
|
||||
}
|
||||
TRACE("drawing text %s at (%ld,%ld)-(%ld,%ld)\n",
|
||||
debugstr_w(wineItem->pszText),
|
||||
rcText.left, rcText.top, rcText.right, rcText.bottom);
|
||||
|
||||
/* Draw it */
|
||||
ExtTextOutW(hdc, rcText.left + 2, rcText.top + 1,
|
||||
ETO_CLIPPED | ETO_OPAQUE,
|
||||
&rcText,
|
||||
wineItem->pszText,
|
||||
lstrlenW(wineItem->pszText),
|
||||
NULL);
|
||||
|
||||
/* Draw the box around the selected item */
|
||||
if ((wineItem == infoPtr->selectedItem) && inFocus)
|
||||
{
|
||||
DrawFocusRect(hdc,&rcText);
|
||||
}
|
||||
|
||||
InflateRect(&rcText, -2, -1); /* allow for the focus rect */
|
||||
|
||||
TRACE("drawing text %s at (%ld,%ld)-(%ld,%ld)\n",
|
||||
debugstr_w(wineItem->pszText),
|
||||
rcText.left, rcText.top, rcText.right, rcText.bottom);
|
||||
|
||||
/* Draw it */
|
||||
DrawTextW(hdc,
|
||||
wineItem->pszText,
|
||||
lstrlenW(wineItem->pszText),
|
||||
&rcText,
|
||||
DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
|
||||
|
||||
/* Restore the hdc state */
|
||||
SetTextColor(hdc, oldTextColor);
|
||||
|
||||
if (oldBkMode != TRANSPARENT)
|
||||
SetBkMode(hdc, oldBkMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2593,10 +2610,13 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
|
|||
if (cditem & CDRF_NOTIFYPOSTPAINT)
|
||||
{
|
||||
cditem = TREEVIEW_SendCustomDrawItemNotify
|
||||
(infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT);
|
||||
(infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT, &nmcdhdr);
|
||||
TRACE("postpaint:cditem-app returns 0x%x\n", cditem);
|
||||
}
|
||||
|
||||
/* Restore the hdc state */
|
||||
SetTextColor(hdc, oldTextColor);
|
||||
SetBkColor(hdc, oldTextBkColor);
|
||||
SelectObject(hdc, hOldFont);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue