Alexandre: Is this format any better. I am worried about line end characters and line wrapping. This is the base for the next patch (soon) that will fix the drawing of the large icons (bugs 676 and #239). This one doesn't really fix any of the drawing issues but does get the LVM_GETITEMRECT correct for the LVIR_BOUNDS, LVIR_ICON, and LVIR_LABEL. This is built on top of CVS of yesterday (9/9/02) but will probably conflict with Dimi's latest patch. Guy License: X11 Changelog: Guy Albertelli <<galberte@neo.lrun.com>> dlls/comctl32/listview.c - Improve LVM_GETITEMRECT values for LVS_ICON style. Now mostly correct (or atleast matches native). - Handle focused and selected large icon text better. - Handle internal erase. - Fix initial WM_NOTIFYFORMAT.- additional debugging code - Base for next patch. Index: dlls/comctl32/listview.c =================================================================== RCS file: /home/wine/wine/dlls/comctl32/listview.c,v retrieving revision 1.139 diff -u -r1.139 listview.c --- dlls/comctl32/listview.c 9 Sep 2002 19:22:19 -0000 1.139 +++ dlls/comctl32/listview.c 11 Sep 2002 01:57:43 -0000 @@ -1,3 +1,5 @@ +#define LISTVIEW_DEBUG 0 + /* * Listview control * @@ -192,13 +194,13 @@ * ICON_TOP_PADDING_HITABLE - spacing between above and icon. * ICON_TOP_PADDING - sum of the two above. * ICON_BOTTOM_PADDING - between bottom of icon and top of text - * LABEL_VERT_OFFSET - between bottom of text and end of box + * LABEL_VERT_PADDING - between bottom of text and end of box */ #define ICON_TOP_PADDING_NOTHITABLE 2 #define ICON_TOP_PADDING_HITABLE 2 -#define ICON_TOP_PADDING ICON_TOP_PADDING_NOTHITABLE + ICON_TOP_PADDING_HITABLE -#define ICON_BOTTOM_PADDING 4 -#define LABEL_VERT_OFFSET 10 +#define ICON_TOP_PADDING (ICON_TOP_PADDING_NOTHITABLE + ICON_TOP_PADDING_HITABLE) +#define ICON_BOTTOM_PADDING 4 +#define LABEL_VERT_PADDING 7 /* default label width for items in list and small icon display modes */ #define DEFAULT_LABEL_WIDTH 40 @@ -217,6 +219,10 @@ /* Border for the icon caption */ #define CAPTION_BORDER 2 + +/* Standard DrawText flags for LISTVIEW_UpdateLargeItemLabelRect and LISTVIEW_DrawLargeItem */ +#define LISTVIEW_DTFLAGS DT_TOP | DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL + /* * macros */ @@ -278,6 +284,7 @@ static VOID LISTVIEW_RemoveSelectionRange(LISTVIEW_INFO *, INT, INT); static void LISTVIEW_FillBackground(LISTVIEW_INFO *, HDC, LPRECT); static void LISTVIEW_UpdateLargeItemLabelRect (LISTVIEW_INFO *, int, RECT*); +static void LISTVIEW_SuperFillBackground(LISTVIEW_INFO *, HDC, LPRECT, COLORREF); static LRESULT LISTVIEW_GetColumnT(LISTVIEW_INFO *, INT, LPLVCOLUMNW, BOOL); static LRESULT LISTVIEW_VScroll(LISTVIEW_INFO *, INT, SHORT, HWND); static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *, INT, SHORT, HWND); @@ -395,6 +402,20 @@ return notify(infoPtr, code, (LPNMHDR)plvnm); } +#if LISTVIEW_DEBUG +static void LISTVIEW_InvRect(int line, HWND hwnd, const RECT* lprc, BOOL bol) +{ + if (lprc) + TRACE("doing InvalidateRect at line %d, rect=(%d,%d)-(%d,%d), bool=%d\n", + line, lprc->left, lprc->top, lprc->right, lprc->bottom, bol); + else + TRACE("doing InvalidateRect at line %d, rect=<null>, bool=%d\n", + line, bol); + InvalidateRect(hwnd, lprc, bol); +} +#define InvalidateRect(a,b,c) LISTVIEW_InvRect(__LINE__, a, b, c) +#endif + static int tabNotification[] = { LVN_BEGINLABELEDITW, LVN_BEGINLABELEDITA, LVN_ENDLABELEDITW, LVN_ENDLABELEDITA, @@ -548,9 +569,13 @@ TRACE("listview %08x at line %d, himlNor=%p, himlSml=%p, himlState=%p, Focused=%d, Hot=%d, exStyle=0x%08lx\n", iP->hwndSelf, line, iP->himlNormal, iP->himlSmall, iP->himlState, iP->nFocusedItem, iP->nHotItem, iP->dwExStyle); - TRACE("listview %08x at line %d, ntmH=%d, icSz.cx=%ld, icSz.cy=%ld, icSp.cx=%ld, icSp.cy=%ld\n", + TRACE("listview %08x at line %d, ntmH=%d, icSz.cx=%ld, icSz.cy=%ld, icSp.cx=%ld, icSp.cy=%ld, notifyFmt=%d\n", iP->hwndSelf, line, iP->ntmHeight, iP->iconSize.cx, iP->iconSize.cy, - iP->iconSpacing.cx, iP->iconSpacing.cy); + iP->iconSpacing.cx, iP->iconSpacing.cy, iP->notifyFormat); + TRACE("listview %08x at line %d, rcList=(%d,%d)-(%d,%d), rcView=(%d,%d)-(%d,%d)\n", + iP->hwndSelf, line, + iP->rcList.left, iP->rcList.top, iP->rcList.right, iP->rcList.bottom, + iP->rcView.left, iP->rcView.top, iP->rcView.right, iP->rcView.bottom); } static BOOL @@ -3300,10 +3325,9 @@ { WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; LVITEMW lvItem; - UINT uFormat = DT_TOP | DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | - DT_EDITCONTROL ; - /* Maintain this format in line with the one in LISTVIEW_UpdateLargeItemLabelRect*/ - RECT rcTemp; + UINT uFormat = LISTVIEW_DTFLAGS; + COLORREF clrFill; + RECT rcFill; TRACE("(hdc=%x, nItem=%d, left=%d, top=%d, right=%d, bottom=%d)\n", hdc, nItem, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom); @@ -3320,18 +3344,19 @@ LISTVIEW_GetItemW(infoPtr, &lvItem, FALSE); TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE)); - /* redraw the background of the item */ - rcTemp = rcItem; - if(infoPtr->nColumnCount == (nItem + 1)) - rcTemp.right = infoPtr->rcList.right; - else - rcTemp.right+=WIDTH_PADDING; - /* The comment doesn't say WIDTH_PADDING applies to large icons */ + rcFill = rcItem; TRACE("background rect (%d,%d)-(%d,%d)\n", - rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom); + rcFill.left, rcFill.top, rcFill.right, rcFill.bottom); - LISTVIEW_FillBackground(infoPtr, hdc, &rcTemp); + /* Paint background of icon and basic text area */ + clrFill = infoPtr->clrBk; +#if LISTVIEW_DEBUG + clrFill = 0x00f01000; + TRACE("background rect (%d,%d)-(%d,%d) special fill\n", + rcFill.left, rcFill.top, rcFill.right, rcFill.bottom); +#endif + LISTVIEW_SuperFillBackground(infoPtr, hdc, &rcFill, clrFill); /* Figure out text colours etc. depending on state @@ -3400,6 +3425,8 @@ ImageList_Draw (infoPtr->himlNormal, lvItem.iImage, hdc, rcItem.left, rcItem.top, (lvItem.state & LVIS_SELECTED) ? ILD_SELECTED : ILD_NORMAL); + TRACE("icon %d at (%d,%d)\n", + lvItem.iImage, rcItem.left, rcItem.top); } } @@ -3420,6 +3447,17 @@ TRACE("bound box for text+icon (%d,%d)-(%d,%d), iS.cx=%ld, nItemWidth=%d\n", rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, infoPtr->iconSize.cx, infoPtr->nItemWidth); + +#if LISTVIEW_DEBUG + { + POINT point[2]; + memcpy(&point, &rcItem, sizeof(RECT)); + MapWindowPoints(hwnd, HWND_DESKTOP, point, 2); + TRACE("bound box in win coord (%ld,%ld)-(%ld,%ld)\n", + point[0].x, point[0].y, point[1].x, point[1].y); + } +#endif + TRACE("rcList (%d,%d)-(%d,%d), rcView (%d,%d)-(%d,%d)\n", infoPtr->rcList.left, infoPtr->rcList.top, infoPtr->rcList.right, infoPtr->rcList.bottom, @@ -3468,6 +3506,9 @@ * background? */ DrawTextW (hdc, lvItem.pszText, -1, &rcItem, uFormat); + TRACE("text at (%d,%d)-(%d,%d) is %s\n", + rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, + debugstr_w(lvItem.pszText)); CopyRect(SuggestedFocus, &rcItem); } @@ -3825,6 +3866,7 @@ RECT rcItem, SuggestedFocus, rcTemp; INT i; DWORD cditemmode = CDRF_DODEFAULT; + COLORREF clrFill; TRACE("\n"); infoPtr->nColumnCount = 1; /* set this to an arbitrary value to prevent */ @@ -3832,7 +3874,14 @@ /* paint the background of the control that doesn't contain any items */ SubtractRect(&rcTemp, &infoPtr->rcList, &infoPtr->rcView); - LISTVIEW_FillBackground(infoPtr, hdc, &rcTemp); + + TRACE("filling viewable area (%d,%d)-(%d,%d)\n", + rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom); + clrFill = infoPtr->clrBk; +#if LISTVIEW_DEBUG + clrFill = 0x000004010; +#endif + LISTVIEW_SuperFillBackground(infoPtr, hdc, &rcTemp, clrFill); /* nothing to draw, return here */ if(GETITEMCOUNT(infoPtr) == 0) @@ -5510,6 +5559,36 @@ } /*** + * Adjust a text rectangle to an integral number of text lines. + */ +static void LISTVIEW_GetIntegralLines( + const LISTVIEW_INFO *infoPtr, + RECT *rcText) +{ + INT i, j, k, l; + + /* + * We need to have the bottom to be an intergal number of + * text lines (ntmHeight) below text top that is less than + * or equal to the nItemHeight. + */ + i = infoPtr->nItemHeight - infoPtr->iconSize.cy - + ICON_TOP_PADDING - ICON_BOTTOM_PADDING; + j = i / infoPtr->ntmHeight; + k = j * infoPtr->ntmHeight; + l = rcText->top + k; + rcText->bottom = min(rcText->bottom, l); + rcText->bottom += 1; + + TRACE("integral lines, nitemH=%d, ntmH=%d, icon.cy=%ld, i=%d, j=%d, k=%d, rect=(%d,%d)-(%d,%d)\n", + infoPtr->nItemHeight, infoPtr->ntmHeight, infoPtr->iconSize.cy, + i, j, k, + rcText->left, rcText->top, rcText->right, rcText->bottom); +} + + +/*** + * DESCRIPTION: [INTERNAL] * Update the bounding rectangle around the text under a large icon. * This depends on whether it has the focus or not. * On entry the rectangle's top, left and right should be set. @@ -5527,8 +5606,23 @@ { HDC hdc = GetDC (infoPtr->hwndSelf); HFONT hOldFont = SelectObject (hdc, infoPtr->hFont); + UINT uFormat = LISTVIEW_DTFLAGS | DT_CALCRECT; + RECT rcText = *rect; + RECT rcBack = *rect; + BOOL focused, selected; + int dx, dy, old_wid, new_wid; + + TRACE("%s, focus item=%d, cur item=%d\n", + (infoPtr->bFocus) ? "Window has focus" : "Window not focused", + infoPtr->nFocusedItem, nItem); + + + focused = (infoPtr->bFocus && infoPtr->nFocusedItem == nItem); + selected = LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED); - if (infoPtr->bFocus && infoPtr->nFocusedItem == nItem) + uFormat |= (focused) ? DT_NOCLIP : DT_WORD_ELLIPSIS | DT_END_ELLIPSIS; + + if (focused || selected) { /* We (aim to) display the full text. In Windows 95 it appears to * calculate the size assuming the specified font and then it draws @@ -5549,10 +5643,31 @@ * to copy it. */ LISTVIEW_GetItemW (infoPtr, &lvItem, TRUE); - DrawTextW (hdc, lvItem.pszText, -1, rect, DT_CALCRECT | - DT_NOCLIP | DT_EDITCONTROL | DT_TOP | DT_CENTER | - DT_WORDBREAK | DT_NOPREFIX); - /* Maintain this DT_* list in line with LISTVIEW_DrawLargeItem */ + + InflateRect(&rcText, -2, 0); + DrawTextW (hdc, lvItem.pszText, -1, &rcText, uFormat); + /* Microsoft, in their great wisdom, have decided that the rectangle + * returned by DrawText on DT_CALCRECT will only guarantee the dimension, + * not the location. So we have to do the centring ourselves (and take + * responsibility for agreeing off-by-one consistency with them). + */ + + old_wid = rcText.right - rcText.left; + new_wid = rcBack.right - rcBack.left; + dx = rcBack.left - rcText.left + (new_wid-old_wid)/2; + dy = rcBack.top - rcText.top; + OffsetRect (&rcText, dx, dy); + + if (!focused) + { + LISTVIEW_GetIntegralLines(infoPtr, &rcText); + } + else + { + rcText.bottom += LABEL_VERT_PADDING - 2; + } + *rect = rcBack; + rect->bottom = rcText.bottom; } else { @@ -5565,9 +5680,15 @@ * Question; should the width be shrunk to the space required to * display the two lines? */ - rect->bottom = rect->top + 2 * infoPtr->ntmHeight; + LISTVIEW_GetIntegralLines(infoPtr, &rcText); + rect->bottom = rcText.bottom; } + TRACE("%s and %s, bounding rect=(%d,%d)-(%d,%d)\n", + (focused) ? "focused(full text)" : "not focused", + (selected) ? "selected" : "not selected", + rect->left, rect->top, rect->right, rect->bottom); + SelectObject (hdc, hOldFont); ReleaseDC (infoPtr->hwndSelf, hdc); } @@ -5585,8 +5706,41 @@ * * LVIR_BOUNDS Returns the bounding rectangle of the entire item, * including the icon and label. + * * + * * For LVS_ICON + * * Experiment shows that native control returns: + * * width = min (48, length of text line) + * * .left = position.x - (width - iconsize.cx)/2 + * * .right = .left + width + * * height = #lines of text * ntmHeight + icon height + 8 + * * .top = position.y - 2 + * * .bottom = .top + height + * * separation between items .y = itemSpacing.cy - height + * * .x = itemSpacing.cx - width * LVIR_ICON Returns the bounding rectangle of the icon or small icon. + * * + * * For LVS_ICON + * * Experiment shows that native control returns: + * * width = iconSize.cx + 16 + * * .left = position.x - (width - iconsize.cx)/2 + * * .right = .left + width + * * height = iconSize.cy + 4 + * * .top = position.y - 2 + * * .bottom = .top + height + * * separation between items .y = itemSpacing.cy - height + * * .x = itemSpacing.cx - width * LVIR_LABEL Returns the bounding rectangle of the item text. + * * + * * For LVS_ICON + * * Experiment shows that native control returns: + * * width = text length + * * .left = position.x - width/2 + * * .right = .left + width + * * height = ntmH * linecount + 2 + * * .top = position.y + iconSize.cy + 6 + * * .bottom = .top + height + * * separation between items .y = itemSpacing.cy - height + * * .x = itemSpacing.cx - width * LVIR_SELECTBOUNDS Returns the union of the LVIR_ICON and LVIR_LABEL * rectangles, but excludes columns in report view. * @@ -5612,7 +5766,8 @@ LVITEMW lvItem; RECT rcInternal; - TRACE("(nItem=%d, lprc=%p)\n", nItem, lprc); + TRACE("(hwnd=%x, nItem=%d, lprc=%p, uview=%d)\n", + infoPtr->hwndSelf, nItem, lprc, uView); if (uView & LVS_REPORT) { @@ -5644,11 +5799,11 @@ if (LISTVIEW_GetOrigin(infoPtr, &ptOrigin) != FALSE) { bResult = TRUE; - lprc->left = ptItem.x + ptOrigin.x; - lprc->top = ptItem.y + ptOrigin.y; - lprc->right = lprc->left + infoPtr->iconSize.cx; - lprc->bottom = (lprc->top + infoPtr->iconSize.cy + - ICON_BOTTOM_PADDING + ICON_TOP_PADDING); + lprc->left = ptItem.x + ptOrigin.x - 8; + lprc->top = ptItem.y + ptOrigin.y - ICON_TOP_PADDING; + lprc->right = lprc->left + infoPtr->iconSize.cx + 16; + lprc->bottom = lprc->top + infoPtr->iconSize.cy + + ICON_TOP_PADDING; } } } @@ -5698,22 +5853,29 @@ if (LISTVIEW_GetOrigin(infoPtr, &ptOrigin) != FALSE) { bResult = TRUE; + + /* Correct ptItem to icon upper-left */ + ptItem.x -= (infoPtr->nItemWidth - infoPtr->iconSize.cx)/2; + ptItem.y -= ICON_TOP_PADDING; + lprc->left = ptItem.x + ptOrigin.x; - lprc->top = (ptItem.y + ptOrigin.y + infoPtr->iconSize.cy + - ICON_BOTTOM_PADDING); + lprc->top = ptItem.y + ptOrigin.y + infoPtr->iconSize.cy + + 6; nLabelWidth = LISTVIEW_GetLabelWidth(infoPtr, nItem); if (infoPtr->iconSpacing.cx - nLabelWidth > 1) { lprc->left += (infoPtr->iconSpacing.cx - nLabelWidth) / 2; lprc->right = lprc->left + nLabelWidth; - } + lprc->bottom = lprc->top + infoPtr->ntmHeight + 1; + InflateRect(lprc, 2, 0); + } else { - lprc->left += 1; lprc->right = lprc->left + infoPtr->iconSpacing.cx - 1; + lprc->bottom = lprc->top + infoPtr->nItemHeight; LISTVIEW_UpdateLargeItemLabelRect (infoPtr, nItem, lprc); } - lprc->bottom = lprc->top + infoPtr->ntmHeight + HEIGHT_PADDING; + lprc->bottom += HEIGHT_PADDING; } } } @@ -5782,48 +5944,42 @@ { if (LISTVIEW_GetOrigin(infoPtr, &ptOrigin) != FALSE) { - RECT label_rect; - INT text_left, text_right, icon_left, text_pos_x; - /* for style LVS_ICON bounds - * left = min(icon.left, text.left) - * right = max(icon.right, text.right) - * top = boundbox.top + NOTHITABLE - * bottom = text.bottom + 1 - */ - bResult = TRUE; - icon_left = text_left = ptItem.x; + RECT label_rect, icon_rect; + + if (!LISTVIEW_GetItemPosition(infoPtr, nItem, &ptItem)) break; + /* make icon rectangle */ + icon_rect.left = ptItem.x + ptOrigin.x - 8; + icon_rect.top = ptItem.y + ptOrigin.y - ICON_TOP_PADDING; + icon_rect.right = icon_rect.left + infoPtr->iconSize.cx + 16; + icon_rect.bottom = icon_rect.top + infoPtr->iconSize.cy + + ICON_TOP_PADDING; + + /* make label rectangle */ /* Correct ptItem to icon upper-left */ - icon_left += (infoPtr->nItemWidth - infoPtr->iconSize.cx)/2; - ptItem.y += ICON_TOP_PADDING; + ptItem.x -= (infoPtr->nItemWidth - infoPtr->iconSize.cx)/2; + ptItem.y -= ICON_TOP_PADDING; - /* Compute the label left and right */ - nLabelWidth = LISTVIEW_GetLabelWidth(infoPtr, nItem); - text_pos_x = infoPtr->iconSpacing.cx - 2*CAPTION_BORDER - nLabelWidth; - if (text_pos_x > 1) - { - text_left += text_pos_x / 2; - text_right = text_left + nLabelWidth + 2*CAPTION_BORDER; - } - else - { - text_left += 1; - text_right = text_left + infoPtr->iconSpacing.cx - 1; - } - - /* Compute rectangle w/o the text height */ - lprc->left = min(icon_left, text_left) + ptOrigin.x; - lprc->right = max(icon_left + infoPtr->iconSize.cx, - text_right) + ptOrigin.x; - lprc->top = ptItem.y + ptOrigin.y - ICON_TOP_PADDING_HITABLE; - lprc->bottom = lprc->top + ICON_TOP_PADDING_HITABLE - + infoPtr->iconSize.cy + 1 - + ICON_BOTTOM_PADDING; - - CopyRect (&label_rect, lprc); - label_rect.top = lprc->bottom; - LISTVIEW_UpdateLargeItemLabelRect (infoPtr, nItem, &label_rect); - UnionRect (lprc, lprc, &label_rect); + label_rect.left = ptItem.x + ptOrigin.x; + label_rect.top = ptItem.y + ptOrigin.y + infoPtr->iconSize.cy + + 6; + nLabelWidth = LISTVIEW_GetLabelWidth(infoPtr, nItem); + if (infoPtr->iconSpacing.cx - nLabelWidth > 1) + { + label_rect.left += (infoPtr->iconSpacing.cx - nLabelWidth) / 2; + label_rect.right = label_rect.left + nLabelWidth; + label_rect.bottom = label_rect.top + infoPtr->ntmHeight + 1; + InflateRect(&label_rect, 2, 0); + } + else + { + label_rect.right = label_rect.left + infoPtr->iconSpacing.cx - 1; + label_rect.bottom = label_rect.top + infoPtr->nItemHeight; + LISTVIEW_UpdateLargeItemLabelRect (infoPtr, nItem, &label_rect); + } + label_rect.bottom += HEIGHT_PADDING; + bResult = TRUE; + UnionRect (lprc, &icon_rect, &label_rect); } } } @@ -5968,9 +6124,6 @@ } break; } - TRACE("result %s (%d,%d)-(%d,%d)\n", - (bResult) ? "TRUE" : "FALSE", - lprc->left, lprc->top, lprc->right, lprc->bottom); } TRACE("result %s (%d,%d)-(%d,%d)\n", bResult ? "TRUE" : "FALSE", @@ -7525,8 +7678,8 @@ { /* if 0 then compute height */ if (uView == LVS_ICON) infoPtr->iconSpacing.cy = infoPtr->iconSize.cy + 2 * infoPtr->ntmHeight - + ICON_BOTTOM_PADDING + ICON_TOP_PADDING + LABEL_VERT_OFFSET; - /* FIXME. I don't think so; I think it is based on twice the ntmHeight */ + + ICON_BOTTOM_PADDING + ICON_TOP_PADDING + LABEL_VERT_PADDING; + else /* FIXME: unknown computation for non LVS_ICON - this is a guess */ infoPtr->iconSpacing.cy = LISTVIEW_GetItemHeight(infoPtr); } @@ -8062,6 +8215,9 @@ /* initialize info pointer */ ZeroMemory(infoPtr, sizeof(LISTVIEW_INFO)); + /* set my handle for all the other routines */ + infoPtr->hwndSelf = hwnd; + /* determine the type of structures to use */ infoPtr->notifyFormat = SendMessageW(GetParent(infoPtr->hwndSelf), WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY); @@ -8072,7 +8228,6 @@ infoPtr->clrTextBk = CLR_DEFAULT; /* set default values */ - infoPtr->hwndSelf = hwnd; infoPtr->uCallbackMask = 0; infoPtr->nFocusedItem = -1; infoPtr->nSelectionMark = -1; @@ -8174,6 +8329,7 @@ if (infoPtr->clrBk == CLR_NONE) { bResult = SendMessageW(GetParent(infoPtr->hwndSelf), WM_ERASEBKGND, wParam, lParam); + TRACE("erase CLR_NONE result=%d\n", bResult); } else { @@ -8182,6 +8338,8 @@ GetClientRect(infoPtr->hwndSelf, &rc); FillRect((HDC)wParam, &rc, hBrush); DeleteObject(hBrush); + TRACE("erase rect=(%d,%d)-(%d,%d), clrBk=0x%08lx\n", + rc.left, rc.top, rc.right, rc.bottom, infoPtr->clrBk); bResult = TRUE; } @@ -8191,16 +8349,40 @@ static void LISTVIEW_FillBackground(LISTVIEW_INFO *infoPtr, HDC hdc, LPRECT rc) { - TRACE("(hdc=%x, rc=%p)\n", hdc, rc); + TRACE("(hwnd=%x, hdc=%x, clrBk=0x%08lx, rc=(%d,%d)-(%d,%d))\n", + infoPtr->hwndSelf, hdc, infoPtr->clrBk, + rc->left, rc->top, rc->right, rc->bottom); if (infoPtr->clrBk != CLR_NONE) { - HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk); +#if LISTVIEW_DEBUG + COLORREF clrbrsh = 0x00c08040; +#else + COLORREF clrbrsh = infoPtr->clrBk; +#endif + HBRUSH hBrush = CreateSolidBrush(clrbrsh); FillRect(hdc, rc, hBrush); DeleteObject(hBrush); } } +static void LISTVIEW_SuperFillBackground(LISTVIEW_INFO *infoPtr, HDC hdc, + LPRECT rc, COLORREF clrbrsh) +{ + TRACE("(hwnd=%x, hdc=%x, clrBk=0x%08lx, rc=(%d,%d)-(%d,%d))\n", + infoPtr->hwndSelf, hdc, infoPtr->clrBk, + rc->left, rc->top, rc->right, rc->bottom); + +#if !LISTVIEW_DEBUG + if (infoPtr->clrBk != CLR_NONE) +#endif + { + HBRUSH hBrush = CreateSolidBrush(clrbrsh); + FillRect(hdc, rc, hBrush); + DeleteObject(hBrush); + } +} + /*** * DESCRIPTION: * Retrieves the listview control font. @@ -8726,6 +8908,12 @@ TRACE("(key=%hu, X=%hu, Y=%hu)\n", wKey, pts.x, pts.y); + /* FIXME???? native does + * SetCapture(hwnd); + * ReleaseCapture(); + * prior to the notify + */ + /* send NM_RELEASEDCAPTURE notification */ hdr_notify(infoPtr, NM_RELEASEDCAPTURE); @@ -8768,9 +8956,44 @@ BOOL was_selected = (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED) & LVIS_SELECTED); + /* FIXME?? native does: + * RegQueryValueA (0, 0, "AppEvents\\Schemes\\Apps\\.Default\\CCSelect\\.current" + * gets "c:\\windows\media\\hoversel.wav" + * LoadLibrary("winmm.dll") + * GetProcAddress("waveOutGetNumDevs") + * GetProcAddress("PlaySoundW") + * waveOutGetNumDevs() + * PlaySoundW(...) + * GetDoubleClickTime() + * SetTimer(hwnd, 2b, time, 0) + */ + /* set selection (clears other pre-existing selections) */ LISTVIEW_SetSelection(infoPtr, nItem); + /* FIXME?? native does: + * notify LVN_ITEMCHANGING + * SendMessage(tooltips, 0x41c, 0, 0) + * UnionRect(&target, iconrect?, textrect?) + * RedrawWindow(hwnd, &target, 0, 1) + * notify LVN_ITEMCHANGED + * GetFocus() + * NotifyWinEvent(0008005, hwnd, -4, 7) + * NotifyWinEvent(0008006, hwnd, -4, 7) + * GetSystemMetrics(0x44) + * GetSystemMetrics(0x45) + * SetRect(&a, 0x1f5, 0x20, 0x1fd, 0x28) + * MapWindowPoints(hwnd, 0, &a, 2) + * SetCapture(hwnd) + * PeekMessage(???, 0, 0, 0, 1) + * CallMsgFilterA(???, 0x00004200) + * ReleaseCapture() + * IsWindow(hwnd) + * SetFocus(hwnd) + * notify NM_CLICK + * return DefWindowProcA() + */ + if (was_selected && infoPtr->nEditLabelItem == -1) infoPtr->nEditLabelItem = nItem; } @@ -9026,6 +9249,11 @@ if (hdc == 0) { hdc = BeginPaint(infoPtr->hwndSelf, &ps); + TRACE("ps erase=%s, rect=(%d,%d)-(%d,%d)\n", + ps.fErase ? "TRUE" : "FALSE", + ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); + if (ps.fErase) + LISTVIEW_EraseBackground(infoPtr, (WPARAM)hdc, 0); LISTVIEW_Refresh(infoPtr, hdc); EndPaint(infoPtr->hwndSelf, &ps); }