Fix large item label calculation when not focused.

Fancy focus rectangle handling.
This commit is contained in:
Dimitrie O. Paun 2002-10-10 03:04:34 +00:00 committed by Alexandre Julliard
parent b2056c22b5
commit 764607d931

View File

@ -262,6 +262,7 @@ DEFINE_COMMON_NOTIFICATIONS(LISTVIEW_INFO, hwndSelf);
*/ */
static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL); static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL);
static INT LISTVIEW_SuperHitTestItem(LISTVIEW_INFO *, LPLVHITTESTINFO, BOOL, BOOL); static INT LISTVIEW_SuperHitTestItem(LISTVIEW_INFO *, LPLVHITTESTINFO, BOOL, BOOL);
static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *, INT, LPRECT, LPRECT, LPRECT, LPRECT);
static void LISTVIEW_AlignLeft(LISTVIEW_INFO *); static void LISTVIEW_AlignLeft(LISTVIEW_INFO *);
static void LISTVIEW_AlignTop(LISTVIEW_INFO *); static void LISTVIEW_AlignTop(LISTVIEW_INFO *);
static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *, INT); static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *, INT);
@ -1142,67 +1143,57 @@ static void LISTVIEW_UpdateScroll(LISTVIEW_INFO *infoPtr)
*/ */
static void LISTVIEW_ShowFocusRect(LISTVIEW_INFO *infoPtr, BOOL fShow) static void LISTVIEW_ShowFocusRect(LISTVIEW_INFO *infoPtr, BOOL fShow)
{ {
RECT rcItem; HDC hdc;
INT nItem = infoPtr->nFocusedItem;
TRACE("fShow=%d, nItem=%d\n", fShow, nItem); TRACE("fShow=%d, nItem=%d\n", fShow, infoPtr->nFocusedItem);
if (nItem < 0 || nItem >= infoPtr->nItemCount) return; if (infoPtr->nFocusedItem < 0) return;
rcItem.left = LVIR_BOUNDS; /* we need some gymnastics in ICON mode to handle large items */
rcItem.top = 0; if ( (infoPtr->dwStyle & LVS_TYPEMASK) == LVS_ICON )
if ( (infoPtr->dwStyle & LVS_TYPEMASK) == LVS_REPORT &&
!(infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) &&
!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED))
{ {
/* this little optimization eliminates some nasty flicker */ RECT rcBox;
if (!LISTVIEW_GetSubItemRect(infoPtr, nItem, &rcItem)) return;
} if (!LISTVIEW_GetItemMeasures(infoPtr, infoPtr->nFocusedItem, &rcBox, 0, 0, 0))
else return;
{ if ((rcBox.bottom - rcBox.top) > infoPtr->nItemHeight)
if (!LISTVIEW_GetItemRect(infoPtr, nItem, &rcItem)) return; {
LISTVIEW_InvalidateRect(infoPtr, &rcBox);
return;
}
} }
if (!(hdc = GetDC(infoPtr->hwndSelf))) return;
if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED) if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)
{ {
DRAWITEMSTRUCT dis; DRAWITEMSTRUCT dis;
LVITEMW item; LVITEMW item;
HDC hdc;
item.iItem = nItem; item.iItem = infoPtr->nFocusedItem;
item.iSubItem = 0; item.iSubItem = 0;
item.mask = LVIF_PARAM; item.mask = LVIF_PARAM;
if (!LISTVIEW_GetItemW(infoPtr, &item)) goto invalidate; if (!LISTVIEW_GetItemW(infoPtr, &item)) goto done;
if (!(hdc = GetDC(infoPtr->hwndSelf))) goto invalidate;
ZeroMemory(&dis, sizeof(dis)); ZeroMemory(&dis, sizeof(dis));
dis.CtlType = ODT_LISTVIEW; dis.CtlType = ODT_LISTVIEW;
dis.CtlID = GetWindowLongW(infoPtr->hwndSelf, GWL_ID); dis.CtlID = GetWindowLongW(infoPtr->hwndSelf, GWL_ID);
dis.itemID = nItem; dis.itemID = item.iItem;
dis.itemAction = ODA_FOCUS; dis.itemAction = ODA_FOCUS;
if (fShow) dis.itemState |= ODS_FOCUS; if (fShow) dis.itemState |= ODS_FOCUS;
dis.hwndItem = infoPtr->hwndSelf; dis.hwndItem = infoPtr->hwndSelf;
dis.hDC = hdc; dis.hDC = hdc;
dis.rcItem = rcItem; if (!LISTVIEW_GetItemMeasures(infoPtr, dis.itemID, &dis.rcItem, 0, 0, 0)) goto done;
dis.itemData = item.lParam; dis.itemData = item.lParam;
SendMessageW(GetParent(infoPtr->hwndSelf), WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); SendMessageW(GetParent(infoPtr->hwndSelf), WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
ReleaseDC(infoPtr->hwndSelf, hdc);
return;
} }
else else
{ {
/* Here we are inneficient. We could, in theory, simply DrawFocusRect DrawFocusRect(hdc, &infoPtr->rcFocus);
* to erase/show the focus, without all this heavy duty redraw.
* Note that there are cases where we can not do that: when the list
* is in ICON mode, and the item is large, we must to invalidate it.
* Moreover, in the vast majority of cases, the selection status of
* the item changes anyway, and so the item is invalidated already,
* so not too much harm is done. If we do notice any flicker, we should
* refine this method. */
invalidate:
LISTVIEW_InvalidateRect(infoPtr, &rcItem);
} }
done:
ReleaseDC(infoPtr->hwndSelf, hdc);
} }
/*** /***
@ -1451,8 +1442,6 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
if (uView == LVS_ICON) if (uView == LVS_ICON)
{ {
if (!oversizedBox && labelSize.cy > infoPtr->ntmHeight)
labelSize.cy = (labelSize.cy / infoPtr->ntmHeight) * infoPtr->ntmHeight;
Label.left = Box.left + (infoPtr->iconSpacing.cx - labelSize.cx) / 2; Label.left = Box.left + (infoPtr->iconSpacing.cx - labelSize.cx) / 2;
Label.top = Box.top + ICON_TOP_PADDING_HITABLE + Label.top = Box.top + ICON_TOP_PADDING_HITABLE +
infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; infoPtr->iconSize.cy + ICON_BOTTOM_PADDING;
@ -1460,7 +1449,16 @@ static BOOL LISTVIEW_GetItemMeasures(LISTVIEW_INFO *infoPtr, INT nItem,
if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED) if (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)
Label.bottom = Label.top + infoPtr->nItemHeight; Label.bottom = Label.top + infoPtr->nItemHeight;
else else
{
if (!oversizedBox && labelSize.cy > infoPtr->ntmHeight)
{
labelSize.cy = min(Box.bottom - Label.top, labelSize.cy);
labelSize.cy /= infoPtr->ntmHeight;
labelSize.cy = max(labelSize.cy, 1);
labelSize.cy *= infoPtr->ntmHeight;
}
Label.bottom = Label.top + labelSize.cy + HEIGHT_PADDING; Label.bottom = Label.top + labelSize.cy + HEIGHT_PADDING;
}
} }
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */ else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
{ {