From e9e6f13996594e5a212c6fa77a7cf02c843588e3 Mon Sep 17 00:00:00 2001 From: Felix Nawothnig Date: Sat, 14 May 2005 11:03:17 +0000 Subject: [PATCH] Rewrote item layouting - new code fixes bitmap/image position for non-left-aligned text, prevents jumping when resizing non-left-aligned text, implements clipping for images and correctly aligns bitmaps when an image is already there. --- dlls/comctl32/header.c | 235 ++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 132 deletions(-) diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c index e8b2cf8a059..67e7a40dad6 100644 --- a/dlls/comctl32/header.c +++ b/dlls/comctl32/header.c @@ -163,7 +163,7 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); HEADER_ITEM *phdi = &infoPtr->items[iItem]; RECT r; - INT oldBkMode; + INT oldBkMode, cxEdge = GetSystemMetrics(SM_CXEDGE); TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem, bHotTrack, infoPtr->bUnicode); @@ -188,6 +188,9 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) else DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST); + r.left -= cxEdge; + r.right += cxEdge; + if (phdi->fmt & HDF_OWNERDRAW) { DRAWITEMSTRUCT dis; dis.CtlType = ODT_HEADER; @@ -206,149 +209,117 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) SetBkMode(hdc, oldBkMode); } else { - UINT uTextJustify = DT_LEFT; + UINT rw, rh, /* width and height of r */ + *x = NULL, *w = NULL; /* x and width of the pic (bmp or img) which is part of cnt */ + /* cnt,txt,img,bmp */ + UINT cx, tx, ix, bx, + cw, tw, iw, bw; + BITMAP bmp; - if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER) - uTextJustify = DT_CENTER; - else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT) - uTextJustify = DT_RIGHT; + cw = tw = iw = bw = 0; + rw = r.right - r.left; + rh = r.bottom - r.top; - if ((phdi->fmt & HDF_BITMAP) && !(phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) { - BITMAP bmp; - HDC hdcBitmap; - INT yD, yS, cx, cy, rx, ry; - - GetObjectW (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp); - - ry = r.bottom - r.top; - rx = r.right - r.left; - - if (ry >= bmp.bmHeight) { - cy = bmp.bmHeight; - yD = r.top + (ry - bmp.bmHeight) / 2; - yS = 0; - } - else { - cy = ry; - yD = r.top; - yS = (bmp.bmHeight - ry) / 2; - - } - - if (rx >= bmp.bmWidth + infoPtr->iMargin) { - cx = bmp.bmWidth; - } - else { - cx = rx - infoPtr->iMargin; - } - - hdcBitmap = CreateCompatibleDC (hdc); - SelectObject (hdcBitmap, phdi->hbm); - BitBlt (hdc, r.left + infoPtr->iMargin, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY); - DeleteDC (hdcBitmap); - - r.left += (bmp.bmWidth + infoPtr->iMargin); - } - - - if ((phdi->fmt & HDF_BITMAP) && (phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) { - BITMAP bmp; - HDC hdcBitmap; - INT xD, yD, yS, cx, cy, rx, ry, tx; - RECT textRect; - - GetObjectW (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp); - - textRect = r; - if (phdi->fmt & HDF_STRING) { - DrawTextW (hdc, phdi->pszText, -1, - &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT); - tx = textRect.right - textRect.left; - } - else - tx = 0; - ry = r.bottom - r.top; - rx = r.right - r.left; - - if (ry >= bmp.bmHeight) { - cy = bmp.bmHeight; - yD = r.top + (ry - bmp.bmHeight) / 2; - yS = 0; - } - else { - cy = ry; - yD = r.top; - yS = (bmp.bmHeight - ry) / 2; - - } - - if (r.left + tx + bmp.bmWidth + 2*infoPtr->iMargin <= r.right) { - cx = bmp.bmWidth; - xD = r.left + tx + infoPtr->iMargin; - } - else { - if (rx >= bmp.bmWidth + infoPtr->iMargin ) { - cx = bmp.bmWidth; - xD = r.right - bmp.bmWidth - infoPtr->iMargin; - r.right = xD - infoPtr->iMargin; - } - else { - cx = rx - infoPtr->iMargin; - xD = r.left; - r.right = r.left; - } - } - - hdcBitmap = CreateCompatibleDC (hdc); - SelectObject (hdcBitmap, phdi->hbm); - BitBlt (hdc, xD, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY); - DeleteDC (hdcBitmap); - } - - if ((phdi->fmt & HDF_IMAGE) && !(phdi->fmt & HDF_BITMAP_ON_RIGHT) && (infoPtr->himl)) { - r.left += infoPtr->iMargin; - ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, r.left, r.top + (r.bottom-r.top- infoPtr->himl->cy)/2, - infoPtr->himl->cx, r.bottom-r.top, CLR_DEFAULT, CLR_DEFAULT, 0); - r.left += infoPtr->himl->cx; - } - - if ((phdi->fmt & HDF_IMAGE) && (phdi->fmt & HDF_BITMAP_ON_RIGHT) && (infoPtr->himl)) { + if (phdi->fmt & HDF_STRING) { RECT textRect; - INT tx; - textRect = r; - if (phdi->fmt & HDF_STRING) { - DrawTextW (hdc, phdi->pszText, -1, - &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT); - tx = textRect.right - textRect.left; - } - else - tx = 0; + DrawTextW (hdc, phdi->pszText, -1, + &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT); + cw = textRect.right - textRect.left + 2 * infoPtr->iMargin; + } - if (tx < (r.right-r.left - infoPtr->himl->cx - GetSystemMetrics(SM_CXEDGE))) - ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, r.left + tx + 2*infoPtr->iMargin, - r.top + (r.bottom-r.top-infoPtr->himl->cy)/2, infoPtr->himl->cx, r.bottom-r.top, - CLR_DEFAULT, CLR_DEFAULT, 0); - else { - INT x = max(r.right - infoPtr->iMargin - infoPtr->himl->cx, r.left); - INT cx = min(infoPtr->himl->cx, r.right-r.left - GetSystemMetrics(SM_CXEDGE)); - ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, x , - r.top + (r.bottom-r.top-infoPtr->himl->cy)/2, cx, r.bottom-r.top, - CLR_DEFAULT, CLR_DEFAULT, 0); - r.right -= infoPtr->himl->cx - infoPtr->iMargin; + if ((phdi->fmt & HDF_IMAGE) && (infoPtr->himl)) { + iw = infoPtr->himl->cx + 2 * infoPtr->iMargin; + x = &ix; + w = &iw; + } + + if ((phdi->fmt & HDF_BITMAP) && (phdi->hbm)) { + GetObjectW (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp); + bw = bmp.bmWidth + 2 * infoPtr->iMargin; + if (!iw) { + x = &bx; + w = &bw; } - } + } - if (((phdi->fmt & HDF_STRING) + if (bw || iw) + cw += *w; + + /* align cx using the unclipped cw */ + if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_LEFT) + cx = r.left; + else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER) + cx = r.left + rw / 2 - cw / 2; + else /* HDF_RIGHT */ + cx = r.right - cw; + + /* clip cx & cw */ + if (cx < r.left) + cx = r.left; + if (cx + cw > r.right) + cw = r.right - cx; + + tx = cx + infoPtr->iMargin; + /* since cw might have changed we have to recalculate tw */ + tw = cw - infoPtr->iMargin * 2; + + if (iw || bw) { + tw -= *w; + if (phdi->fmt & HDF_BITMAP_ON_RIGHT) { + /* put pic behind text */ + *x = cx + tw + infoPtr->iMargin * 3; + } else { + *x = cx + infoPtr->iMargin; + /* move text behind pic */ + tx += *w; + } + } + + if (iw && bw) { + /* since we're done with the layout we can + now calculate the position of bmp which + has no influence on alignment and layout + because of img */ + if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT) + bx = cx - bw + infoPtr->iMargin; + else + bx = cx + cw + infoPtr->iMargin; + } + + if (iw || bw) { + HDC hClipDC = GetDC(hwnd); + HRGN hClipRgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); + SelectClipRgn(hClipDC, hClipRgn); + + if (bw) { + HDC hdcBitmap = CreateCompatibleDC (hClipDC); + SelectObject (hdcBitmap, phdi->hbm); + BitBlt (hClipDC, bx, r.top + ((INT)rh - bmp.bmHeight) / 2, + bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY); + DeleteDC (hdcBitmap); + } + + if (iw) { + ImageList_DrawEx (infoPtr->himl, phdi->iImage, hClipDC, + ix, r.top + ((INT)rh - infoPtr->himl->cy) / 2, + infoPtr->himl->cx, infoPtr->himl->cy, CLR_DEFAULT, CLR_DEFAULT, 0); + } + + DeleteObject(hClipRgn); + DeleteDC(hClipDC); + } + + if (((phdi->fmt & HDF_STRING) || (!(phdi->fmt & (HDF_OWNERDRAW|HDF_STRING|HDF_BITMAP| HDF_BITMAP_ON_RIGHT|HDF_IMAGE)))) /* no explicit format specified? */ && (phdi->pszText)) { - oldBkMode = SetBkMode(hdc, TRANSPARENT); - r.left += infoPtr->iMargin; - r.right -= infoPtr->iMargin; + oldBkMode = SetBkMode(hdc, TRANSPARENT); SetTextColor (hdc, (bHotTrack) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT); + r.left = tx; + r.right = tx + tw; DrawTextW (hdc, phdi->pszText, -1, - &r, uTextJustify|DT_END_ELLIPSIS|DT_VCENTER|DT_SINGLELINE); + &r, DT_LEFT|DT_END_ELLIPSIS|DT_VCENTER|DT_SINGLELINE); if (oldBkMode != TRANSPARENT) SetBkMode(hdc, oldBkMode); }