Hi all, I should maybe have posted this to the patches list, but I would like your comments first.
I have fixed a few problems with the ListView control when using icons larger than the sizes returned by the system metrics. This (attached) patch also causes LISTVIEW_Arrange (which was previously a stub) to call the LISTVIEW_AlignTop/Left when appropriate. Please let me know what you think. This is my first time doing any of this, so let me know what I'm doing wrong/right. Cheers Steve
? listview.c.new ? patch.diff Index: listview.c =================================================================== RCS file: /home/wine/wine/dlls/comctl32/listview.c,v retrieving revision 1.134 diff -u -r1.134 listview.c --- listview.c 23 Jul 2002 20:54:52 -0000 1.134 +++ listview.c 15 Aug 2002 14:04:18 -0000 @@ -1009,6 +1009,7 @@ POINT ptItem; RECT rcView; INT i, off_x=0, off_y=0; + SIZE spacing; if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) { @@ -1018,7 +1019,13 @@ { off_y = ICON_TOP_PADDING; off_x = (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2; + spacing = infoPtr->iconSpacing; } + else + { + spacing.cx = infoPtr->nItemWidth; + spacing.cy = GetSystemMetrics(SM_CYSMICON); + } ptItem.x = off_x; ptItem.y = off_y; ZeroMemory(&rcView, sizeof(RECT)); @@ -1026,18 +1033,18 @@ off_x, off_y, infoPtr->rcList.left, infoPtr->rcList.right); - if (nListWidth > infoPtr->nItemWidth) + if (nListWidth > spacing.cx) { for (i = 0; i < GETITEMCOUNT(infoPtr); i++) { if ((ptItem.x-off_x) + infoPtr->nItemWidth > nListWidth) { ptItem.x = off_x; - ptItem.y += infoPtr->nItemHeight; + ptItem.y += spacing.cy; } LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y); - ptItem.x += infoPtr->nItemWidth; + ptItem.x += spacing.cx; rcView.right = max(rcView.right, ptItem.x); } @@ -1049,10 +1056,10 @@ for (i = 0; i < GETITEMCOUNT(infoPtr); i++) { LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y); - ptItem.y += infoPtr->nItemHeight; + ptItem.y += spacing.cy; } - rcView.right = infoPtr->nItemWidth; + rcView.right = spacing.cx; rcView.bottom = ptItem.y-off_y; } @@ -1277,35 +1284,32 @@ nItemWidth = max(nItemWidth, nLabelWidth); } - /* default label size */ - if (GETITEMCOUNT(infoPtr) == 0) + if (nItemWidth == 0) { - nItemWidth = DEFAULT_COLUMN_WIDTH; + nItemWidth = DEFAULT_LABEL_WIDTH; } else { - if (nItemWidth == 0) + /* add padding */ + nItemWidth += WIDTH_PADDING; + + if (infoPtr->himlSmall) { - nItemWidth = DEFAULT_LABEL_WIDTH; + INT nIconWidth = 0, nIconHeight = 0; + ImageList_GetIconSize(infoPtr->himlSmall, &nIconWidth, &nIconHeight); + nItemWidth += nIconWidth; } - else - { - /* add padding */ - nItemWidth += WIDTH_PADDING; - if (infoPtr->himlSmall != NULL) - { - nItemWidth += infoPtr->iconSize.cx; - } - - if (infoPtr->himlState != NULL) - { - nItemWidth += infoPtr->iconSize.cx; - } - nItemWidth = max(DEFAULT_COLUMN_WIDTH, nItemWidth); + if (infoPtr->himlState) + { + INT nIconWidth = 0, nIconHeight = 0; + ImageList_GetIconSize(infoPtr->himlSmall, &nIconWidth, &nIconHeight); + nItemWidth += nIconWidth; } + nItemWidth = max(DEFAULT_COLUMN_WIDTH, nItemWidth); } } + if(nItemWidth == 0) { /* nItemWidth Cannot be Zero */ @@ -1438,7 +1442,7 @@ if (uView == LVS_ICON) { - nItemHeight = infoPtr->iconSpacing.cy; + nItemHeight = infoPtr->iconSize.cy + (GetSystemMetrics(SM_CYICONSPACING) - 32); } else { @@ -3465,8 +3469,8 @@ } /* Since rcItem.left is left point of icon, compute left point of item box */ - rcItem.left -= ((infoPtr->nItemWidth - infoPtr->iconSize.cx) / 2); - rcItem.right = rcItem.left + infoPtr->nItemWidth; + rcItem.left -= ((infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2); + rcItem.right = rcItem.left + infoPtr->iconSpacing.cx; rcItem.bottom = rcItem.top + infoPtr->nItemHeight; TRACE("bound box for text+icon (%d,%d)-(%d,%d), iS.cx=%ld, nItemWidth=%d\n", rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, @@ -4092,10 +4096,10 @@ switch (nAlignCode) { case LVA_ALIGNLEFT: - FIXME("nAlignCode=LVA_ALIGNLEFT: not implemented\n"); + LISTVIEW_AlignLeft(hwnd); break; case LVA_ALIGNTOP: - FIXME("nAlignCode=LVA_ALIGNTOP: not implemented\n"); + LISTVIEW_AlignTop(hwnd); break; case LVA_DEFAULT: FIXME("nAlignCode=LVA_DEFAULT: not implemented\n"); @@ -4106,6 +4110,8 @@ } } + InvalidateRect(hwnd, NULL, TRUE); + return bResult; } @@ -7697,19 +7703,36 @@ static HIMAGELIST LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongW(hwnd, 0); + UINT uView = GetWindowLongW(hwnd, GWL_STYLE) & LVS_TYPEMASK; HIMAGELIST himlOld = 0; - INT oldHeight; + INT width, height, oldHeight; + + ImageList_GetIconSize(himl, &width, &height); switch (nType) { case LVSIL_NORMAL: himlOld = infoPtr->himlNormal; infoPtr->himlNormal = himl; + + if (uView == LVS_ICON) + { + infoPtr->iconSize.cx = width; + infoPtr->iconSize.cy = height; + infoPtr->iconSpacing.cx = (GetSystemMetrics(SM_CXICONSPACING) - 32) + width; + infoPtr->iconSpacing.cy = (GetSystemMetrics(SM_CYICONSPACING) - 32) + height; + } break; case LVSIL_SMALL: himlOld = infoPtr->himlSmall; infoPtr->himlSmall = himl; + + if (uView != LVS_ICON) + { + infoPtr->iconSize.cx = width; + infoPtr->iconSize.cy = height; + } break; case LVSIL_STATE: @@ -8216,8 +8239,10 @@ infoPtr->nFocusedItem = -1; infoPtr->nSelectionMark = -1; infoPtr->nHotItem = -1; - infoPtr->iconSpacing.cx = GetSystemMetrics(SM_CXICONSPACING); - infoPtr->iconSpacing.cy = GetSystemMetrics(SM_CYICONSPACING); + infoPtr->iconSize.cx = 0; + infoPtr->iconSize.cy = 0; + infoPtr->iconSpacing.cx = GetSystemMetrics(SM_CXICONSPACING) - 32; + infoPtr->iconSpacing.cy = GetSystemMetrics(SM_CYICONSPACING) - 32; ZeroMemory(&infoPtr->rcList, sizeof(RECT)); infoPtr->hwndEdit = 0; infoPtr->pedititem = NULL; @@ -8243,12 +8268,7 @@ SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, (LPARAM)TRUE); - if (uView == LVS_ICON) - { - infoPtr->iconSize.cx = GetSystemMetrics(SM_CXICON); - infoPtr->iconSize.cy = GetSystemMetrics(SM_CYICON); - } - else if (uView == LVS_REPORT) + if (uView == LVS_REPORT) { if (!(LVS_NOCOLUMNHEADER & lpcs->style)) { @@ -8260,15 +8280,6 @@ SetWindowLongW(infoPtr->hwndHeader, GWL_STYLE, GetWindowLongW(infoPtr->hwndHeader, GWL_STYLE) | HDS_HIDDEN); } - - - infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON); - infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON); - } - else - { - infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON); - infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON); } /* display unsupported listview window styles */ @@ -9576,12 +9587,15 @@ * decide. */ if (uNewView != uOldView) - ShowScrollBar(hwnd, SB_BOTH, FALSE); + ShowScrollBar(hwnd, SB_BOTH, FALSE); if (uNewView == LVS_ICON) { - infoPtr->iconSize.cx = GetSystemMetrics(SM_CXICON); - infoPtr->iconSize.cy = GetSystemMetrics(SM_CYICON); + INT nIconWidth = 0, nIconHeight = 0; + if (infoPtr->himlNormal) + ImageList_GetIconSize(infoPtr->himlNormal, &nIconWidth, &nIconHeight); + infoPtr->iconSize.cx = nIconWidth; + infoPtr->iconSize.cy = nIconHeight; infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd); infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd); if (lpss->styleNew & LVS_ALIGNLEFT) @@ -9593,6 +9607,7 @@ { HDLAYOUT hl; WINDOWPOS wp; + INT nIconWidth = 0, nIconHeight = 0; hl.prc = &rcList; hl.pwpos = ℘ @@ -9602,15 +9617,23 @@ if (!(LVS_NOCOLUMNHEADER & lpss->styleNew)) ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); - infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON); - infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON); + if (infoPtr->himlSmall) + ImageList_GetIconSize(infoPtr->himlSmall, &nIconWidth, &nIconHeight); + + infoPtr->iconSize.cx = nIconWidth; + infoPtr->iconSize.cy = nIconHeight; infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd); infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd); } else if (uNewView == LVS_LIST) { - infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON); - infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON); + INT nIconWidth = 0, nIconHeight = 0; + + if (infoPtr->himlSmall) + ImageList_GetIconSize(infoPtr->himlSmall, &nIconWidth, &nIconHeight); + + infoPtr->iconSize.cx = nIconWidth; + infoPtr->iconSize.cy = nIconHeight; infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd); infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd); }