ChangeLog Fix silly redraw bug introduced in previous patch Tidy up, and simplify large item drawing. --- dlls/comctl32/listview.c.N2 Thu Oct 10 10:38:50 2002 +++ dlls/comctl32/listview.c Thu Oct 10 12:31:32 2002 @@ -27,6 +27,7 @@ * TODO: * -- Drawing optimizations. * -- Hot item handling. + * -- Expand large item in ICON mode when the cursor is flying over the icon or text. * * Notifications: * LISTVIEW_Notify : most notifications from children (editbox and header) @@ -3205,153 +3206,87 @@ * [I] infoPtr : valid pointer to the listview structure * [I] hdc : device context handle * [I] nItem : item index - * [I] rcItem : clipping rectangle * * RETURN: * TRUE: if item is focused * FALSE: otherwise */ -static BOOL LISTVIEW_DrawLargeItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, RECT rcItem) +static void LISTVIEW_DrawLargeItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem) { - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - LVITEMW lvItem; - UINT uFormat; - RECT rcIcon, rcFocus, rcLabel, *lprcFocus; - - TRACE("(hdc=%x, nItem=%d, rcItem=%s)\n", hdc, nItem, debugrect(&rcItem)); - - /* get information needed for drawing the item */ - lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK; - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - lvItem.cchTextMax = DISP_TEXT_SIZE; - lvItem.pszText = szDispText; - *lvItem.pszText = '\0'; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE; - TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE)); + WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; + RECT rcIcon, rcLabel, *lprcFocus; + LVITEMW lvItem; + UINT uFormat; + TEXTATTR ta; - /* now check if we need to update the focus rectangle */ - lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0; - - if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, &rcIcon, &rcLabel)) return FALSE; + TRACE("(hdc=%x, nItem=%d)\n", hdc, nItem); - /* Set the item to the boundary box for now */ - TRACE("rcIcon=%s, rcLabel=%s\n", debugrect(&rcIcon), debugrect(&rcLabel)); + /* get information needed for drawing the item */ + lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK; + lvItem.iItem = nItem; + lvItem.iSubItem = 0; + lvItem.pszText = szDispText; + lvItem.cchTextMax = DISP_TEXT_SIZE; + if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return; + TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE)); - /* Figure out text colours etc. depending on state - * At least the following states exist; there may be more. - * Many items may be selected - * At most one item may have the focus - * The application may not actually be active currently - * 1. The item is not selected in any way - * 2. The cursor is flying over the icon or text and the text is being - * expanded because it is not fully displayed currently. - * 3. The item is selected and is focussed, i.e. the user has not clicked - * in the blank area of the window, and the window (or application?) - * still has the focus. - * 4. As 3 except that a different window has the focus - * 5. The item is the selected item of all the items, but the user has - * clicked somewhere else on the window. - * Only a few of these are handled currently. In particular 2 is not yet - * handled since we do not support the functionality currently (or at least - * we didn't when I wrote this) - */ + /* now check if we need to update the focus rectangle */ + lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0; + + if (!LISTVIEW_GetItemMeasures(infoPtr, nItem, NULL, NULL, &rcIcon, &rcLabel)) return; - if (lvItem.state & LVIS_SELECTED) - { - /* set item colors */ - SetBkColor(hdc, comctl32_color.clrHighlight); - SetTextColor(hdc, comctl32_color.clrHighlightText); - SetBkMode (hdc, OPAQUE); - /* set raster mode */ - SetROP2(hdc, R2_XORPEN); - /* When exactly is it in XOR? while being dragged? */ - } - else - { - /* set item colors */ - if ( (infoPtr->clrTextBk == CLR_DEFAULT) || (infoPtr->clrTextBk == CLR_NONE) ) - { - SetBkMode(hdc, TRANSPARENT); - } - else + /* Set the item to the boundary box for now */ + TRACE("rcIcon=%s, rcLabel=%s\n", debugrect(&rcIcon), debugrect(&rcLabel)); + + /* state icons */ + if (infoPtr->himlState) { - SetBkMode(hdc, OPAQUE); - SetBkColor(hdc, infoPtr->clrTextBk); + UINT uStateImage = (lvItem.state & LVIS_STATEIMAGEMASK) >> 12; + INT x = rcIcon.left - infoPtr->iconStateSize.cx + 10; + INT y = rcIcon.top + infoPtr->iconSize.cy - infoPtr->iconStateSize.cy + 4; + if (uStateImage > 0) + ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, x, y, ILD_NORMAL); } - SetTextColor(hdc, infoPtr->clrText); - /* set raster mode */ - SetROP2(hdc, R2_COPYPEN); - } - - /* In cases 2,3 and 5 (see above) the full text is displayed, with word - * wrapping and long words split. - * In cases 1 and 4 only a portion of the text is displayed with word - * wrapping and both word and end ellipsis. (I don't yet know about path - * ellipsis) - */ - uFormat = lprcFocus ? LV_FL_DT_FLAGS : LV_ML_DT_FLAGS; + /* draw the icon */ + if (infoPtr->himlNormal && lvItem.iImage >=0) + ImageList_Draw (infoPtr->himlNormal, lvItem.iImage, hdc, + rcIcon.left + ICON_LR_HALF, rcIcon.top + ICON_TOP_PADDING, + (lvItem.state & LVIS_SELECTED) ? ILD_SELECTED : ILD_NORMAL); - /* state icons */ - if (infoPtr->himlState != NULL) - { - UINT uStateImage = (lvItem.state & LVIS_STATEIMAGEMASK) >> 12; - INT x, y; + /* Draw the text below the icon */ - x = rcIcon.left - infoPtr->iconStateSize.cx + 10; - y = rcIcon.top + infoPtr->iconSize.cy - infoPtr->iconStateSize.cy + 4; - if (uStateImage > 0) - ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, x, y, ILD_NORMAL); - } - - /* draw the icon */ - if (infoPtr->himlNormal != NULL) - { - if (lvItem.iImage >= 0) - ImageList_Draw (infoPtr->himlNormal, lvItem.iImage, hdc, - rcIcon.left + ICON_LR_HALF, rcIcon.top + ICON_TOP_PADDING, - (lvItem.state & LVIS_SELECTED) ? ILD_SELECTED : ILD_NORMAL); - } + /* Don't bother painting item being edited */ + if ((infoPtr->bEditing && lprcFocus) || !lvItem.pszText || !lstrlenW(lvItem.pszText)) + { + if(lprcFocus) SetRectEmpty(lprcFocus); + return; + } - /* Draw the text below the icon */ + select_text_attr(infoPtr, hdc, lvItem.state & LVIS_SELECTED, &ta); - /* Don't bother painting item being edited */ - if ((infoPtr->bEditing && lprcFocus) || !lvItem.pszText || !lstrlenW(lvItem.pszText)) - { - if(lprcFocus) SetRectEmpty(lprcFocus); - return FALSE; - } + uFormat = lprcFocus ? LV_FL_DT_FLAGS : LV_ML_DT_FLAGS; - /* draw label */ + /* draw label */ - /* I am sure of most of the uFormat values. However I am not sure about - * whether we need or do not need the following: - * DT_EXTERNALLEADING, DT_INTERNAL, DT_CALCRECT, DT_NOFULLWIDTHCHARBREAK, - * DT_PATH_ELLIPSIS, DT_RTLREADING, - * We certainly do not need - * DT_BOTTOM, DT_VCENTER, DT_MODIFYSTRING, DT_LEFT, DT_RIGHT, DT_PREFIXONLY, - * DT_SINGLELINE, DT_TABSTOP, DT_EXPANDTABS - */ + /* I am sure of most of the uFormat values. However I am not sure about + * whether we need or do not need the following: + * DT_EXTERNALLEADING, DT_INTERNAL, DT_CALCRECT, DT_NOFULLWIDTHCHARBREAK, + * DT_PATH_ELLIPSIS, DT_RTLREADING, + * We certainly do not need + * DT_BOTTOM, DT_VCENTER, DT_MODIFYSTRING, DT_LEFT, DT_RIGHT, DT_PREFIXONLY, + * DT_SINGLELINE, DT_TABSTOP, DT_EXPANDTABS + */ - /* If the text is being drawn without clipping (i.e. the full text) then we - * need to jump through a few hoops to ensure that it all gets displayed and - * that the background is complete - */ - rcFocus = rcLabel; /* save for focus */ - if (lvItem.state & LVIS_SELECTED) - ExtTextOutW(hdc, rcLabel.left, rcLabel.top, ETO_OPAQUE, &rcLabel, 0, 0, 0); - /* else ? What if we are losing the focus? will we not get a complete - * background? - */ + if (lvItem.state & LVIS_SELECTED) + ExtTextOutW(hdc, rcLabel.left, rcLabel.top, ETO_OPAQUE, &rcLabel, 0, 0, 0); - DrawTextW (hdc, lvItem.pszText, -1, &rcLabel, uFormat); - TRACE("text at rcLabel=%s is %s\n", debugrect(&rcLabel), debugstr_w(lvItem.pszText)); + DrawTextW (hdc, lvItem.pszText, -1, &rcLabel, uFormat); - if(lprcFocus) CopyRect(lprcFocus, &rcFocus); + if(lprcFocus) *lprcFocus = rcLabel; - return lprcFocus != NULL; + set_text_attr(hdc, &ta); } /*** @@ -3643,18 +3578,12 @@ if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_FOCUSED)) continue; - if (!LISTVIEW_GetItemListOrigin(infoPtr, i.nItem, &Position)) continue; - rcItem.left = Position.x; - rcItem.top = Position.y; - rcItem.bottom = rcItem.top + infoPtr->nItemHeight; - rcItem.right = rcItem.left + infoPtr->nItemWidth; - OffsetRect(&rcItem, Origin.x, Origin.y); - if (cdmode & CDRF_NOTIFYITEMDRAW) cditemmode = notify_customdrawitem (infoPtr, hdc, i.nItem, 0, CDDS_ITEMPREPAINT); if (cditemmode & CDRF_SKIPDEFAULT) continue; - LISTVIEW_DrawLargeItem(infoPtr, hdc, i.nItem, rcItem); + if (!LISTVIEW_GetItemListOrigin(infoPtr, i.nItem, &Position)) continue; + LISTVIEW_DrawLargeItem(infoPtr, hdc, i.nItem); if (cditemmode & CDRF_NOTIFYPOSTPAINT) notify_customdrawitem(infoPtr, hdc, i.nItem, 0, CDDS_ITEMPOSTPAINT); @@ -3670,7 +3599,7 @@ if (cditemmode & CDRF_SKIPDEFAULT) return; - LISTVIEW_DrawLargeItem(infoPtr, hdc, infoPtr->nFocusedItem, rcItem); + LISTVIEW_DrawLargeItem(infoPtr, hdc, infoPtr->nFocusedItem); if (cditemmode & CDRF_NOTIFYPOSTPAINT) notify_customdrawitem(infoPtr, hdc, i.nItem, 0, CDDS_ITEMPOSTPAINT); @@ -7063,6 +6992,7 @@ infoPtr->nFocusedItem = -1; infoPtr->nSelectionMark = -1; infoPtr->nHotItem = -1; + infoPtr->bRedraw = TRUE; infoPtr->iconSpacing.cx = GetSystemMetrics(SM_CXICONSPACING); infoPtr->iconSpacing.cy = GetSystemMetrics(SM_CYICONSPACING); infoPtr->nEditLabelItem = -1;