This one completes the column related code rewrite. ChangeLog SetColumnWidth rewrite: simpler, cleaner code. Bugs squashed. --- dlls/comctl32/listview.c.V2 Sun Oct 20 03:56:28 2002 +++ dlls/comctl32/listview.c Sun Oct 20 10:44:18 2002 @@ -6106,32 +6106,21 @@ * * PARAMETERS: * [I] infoPtr : valid pointer to the listview structure - * [I] iCol : column index + * [I] nColumn : column index * [I] cx : column width * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static BOOL LISTVIEW_SetColumnWidth(LISTVIEW_INFO *infoPtr, INT iCol, INT cx) +static BOOL LISTVIEW_SetColumnWidth(LISTVIEW_INFO *infoPtr, INT nColumn, INT cx) { - HDITEMW hdi; - LRESULT lret; - LONG lStyle = infoPtr->dwStyle; - UINT uView = lStyle & LVS_TYPEMASK; - HDC hdc; - HFONT header_font; - HFONT old_font; - SIZE size; - WCHAR text_buffer[DISP_TEXT_SIZE]; - INT header_item_count; - INT item_index; - INT nLabelWidth; - RECT rcHeader; - LVITEMW lvItem; + UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; WCHAR szDispText[DISP_TEXT_SIZE] = { 0 }; + INT max_cx = 0; + HDITEMW hdi; - TRACE("(iCol=%d, cx=%d\n", iCol, cx); + TRACE("(nColumn=%d, cx=%d\n", nColumn, cx); /* set column width only if in report or list mode */ if (uView != LVS_REPORT && uView != LVS_LIST) return FALSE; @@ -6148,117 +6137,81 @@ return TRUE; } - /* FIXME: update COLUMN_INFO */ + if (nColumn < 0 || nColumn >= infoPtr->hdpaColumns->nItemCount) return FALSE; + + if (cx == LVSCW_AUTOSIZE || (cx == LVSCW_AUTOSIZE_USEHEADER && nColumn < infoPtr->hdpaColumns->nItemCount -1)) + { + INT nLabelWidth; + LVITEMW lvItem; + + lvItem.mask = LVIF_TEXT; + lvItem.iItem = 0; + lvItem.iSubItem = nColumn; + lvItem.pszText = szDispText; + lvItem.cchTextMax = DISP_TEXT_SIZE; + for (; lvItem.iItem < infoPtr->nItemCount; lvItem.iItem++) + { + if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue; + nLabelWidth = LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE); + if (max_cx < nLabelWidth) max_cx = nLabelWidth; + } + if (infoPtr->himlSmall && (nColumn == 0 || (LISTVIEW_GetColumnInfo(infoPtr, nColumn)->fmt & LVCFMT_IMAGE))) + max_cx += infoPtr->iconSize.cx + IMAGE_PADDING; + max_cx += REPORT_MARGINX + TRAILING_PADDING; + } /* autosize based on listview items width */ if(cx == LVSCW_AUTOSIZE) - { - /* set the width of the column to the width of the widest item */ - if (iCol == 0 || uView == LVS_LIST) - { - cx = 0; - for(item_index = 0; item_index < infoPtr->nItemCount; item_index++) - { - nLabelWidth = LISTVIEW_GetLabelWidth(infoPtr, item_index); - cx = (nLabelWidth>cx)?nLabelWidth:cx; - } - if (infoPtr->himlSmall) - cx += infoPtr->iconSize.cx + IMAGE_PADDING; - } - else - { - lvItem.iSubItem = iCol; - lvItem.mask = LVIF_TEXT; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - cx = 0; - for(item_index = 0; item_index < infoPtr->nItemCount; item_index++) - { - lvItem.iItem = item_index; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue; - nLabelWidth = LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE); - cx = (nLabelWidth>cx)?nLabelWidth:cx; - } - } - cx += TRAILING_PADDING; - } /* autosize based on listview header width */ + cx = max_cx; else if(cx == LVSCW_AUTOSIZE_USEHEADER) { - header_item_count = infoPtr->hdpaColumns->nItemCount; + /* if iCol is the last column make it fill the remainder of the controls width */ + if(nColumn == infoPtr->hdpaColumns->nItemCount - 1) + { + RECT rcHeader; + POINT Origin; - /* if iCol is the last column make it fill the remainder of the controls width */ - if(iCol == (header_item_count - 1)) { - cx = 0; + LISTVIEW_GetOrigin(infoPtr, &Origin); + LISTVIEW_GetHeaderRect(infoPtr, nColumn, &rcHeader); - for(item_index = 0; item_index < (header_item_count - 1); item_index++) + cx = infoPtr->rcList.right - Origin.x - rcHeader.left; + } + else { - LISTVIEW_GetHeaderRect(infoPtr, item_index, &rcHeader); - cx += rcHeader.right - rcHeader.left; - } - - /* retrieve the layout of the header */ - GetWindowRect(infoPtr->hwndHeader, &rcHeader); - - cx = (rcHeader.right - rcHeader.left) - cx; - } - else - { - /* Despite what the MS docs say, if this is not the last - column, then MS resizes the column to the width of the - largest text string in the column, including headers - and items. This is different from LVSCW_AUTOSIZE in that - LVSCW_AUTOSIZE ignores the header string length. - */ - - /* retrieve header font */ - header_font = SendMessageW(infoPtr->hwndHeader, WM_GETFONT, 0L, 0L); - - /* retrieve header text */ - hdi.mask = HDI_TEXT; - hdi.cchTextMax = sizeof(text_buffer)/sizeof(text_buffer[0]); - hdi.pszText = text_buffer; - - Header_GetItemW(infoPtr->hwndHeader, iCol, (LPARAM)(&hdi)); - - /* determine the width of the text in the header */ - hdc = GetDC(infoPtr->hwndSelf); - old_font = SelectObject(hdc, header_font); /* select the font into hdc */ - - GetTextExtentPoint32W(hdc, text_buffer, lstrlenW(text_buffer), &size); - - SelectObject(hdc, old_font); /* restore the old font */ - ReleaseDC(infoPtr->hwndSelf, hdc); - - lvItem.iSubItem = iCol; - lvItem.mask = LVIF_TEXT; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - cx = size.cx; - for(item_index = 0; item_index < infoPtr->nItemCount; item_index++) - { - lvItem.iItem = item_index; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue; - nLabelWidth = LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE); - nLabelWidth += TRAILING_PADDING; - /* While it is possible for subitems to have icons, even MS messes - up the positioning, so I suspect no applications actually use - them. */ - if (item_index == 0 && infoPtr->himlSmall) - nLabelWidth += infoPtr->iconSize.cx + IMAGE_PADDING; - cx = (nLabelWidth>cx)?nLabelWidth:cx; - } - } - } - - /* call header to update the column change */ - hdi.mask = HDI_WIDTH; - - hdi.cxy = cx; - lret = Header_SetItemW(infoPtr->hwndHeader, (WPARAM)iCol, (LPARAM)&hdi); + /* Despite what the MS docs say, if this is not the last + column, then MS resizes the column to the width of the + largest text string in the column, including headers + and items. This is different from LVSCW_AUTOSIZE in that + LVSCW_AUTOSIZE ignores the header string length. */ + cx = 0; + + /* retrieve header text */ + hdi.mask = HDI_TEXT; + hdi.cchTextMax = DISP_TEXT_SIZE; + hdi.pszText = szDispText; + if (Header_GetItemW(infoPtr->hwndHeader, nColumn, (LPARAM)&hdi)) + { + HDC hdc = GetDC(infoPtr->hwndSelf); + HFONT old_font = SelectObject(hdc, SendMessageW(infoPtr->hwndHeader, WM_GETFONT, 0, 0)); + SIZE size; + + if (GetTextExtentPoint32W(hdc, hdi.pszText, lstrlenW(hdi.pszText), &size)) + cx = size.cx; + /* FIXME: Take into account the header image, if one is present */ + SelectObject(hdc, old_font); + ReleaseDC(infoPtr->hwndSelf, hdc); + } + cx = max (cx, max_cx); + } + } - LISTVIEW_InvalidateList(infoPtr); /* FIXME: optimize */ + if (cx < 0) return FALSE; - return lret; + /* call header to update the column change */ + hdi.mask = HDI_WIDTH; + hdi.cxy = cx; + TRACE("hdi.cxy=%d\n", hdi.cxy); + return Header_SetItemW(infoPtr->hwndHeader, nColumn, (LPARAM)&hdi); } /*** @@ -6365,8 +6318,7 @@ { INT cy = HIWORD(spacing), cx = LOWORD(spacing); DWORD oldspacing = MAKELONG(infoPtr->iconSpacing.cx, infoPtr->iconSpacing.cy); - LONG lStyle = infoPtr->dwStyle; - UINT uView = lStyle & LVS_TYPEMASK; + UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; TRACE("requested=(%d,%d)\n", cx, cy);