[comctl32] header.c: item layout rewrite

Felix Nawothnig felix.nawothnig at t-online.de
Wed May 11 18:36:58 CDT 2005


For screenshots (pre-patch, native, post-patch) and an example 
application which tests all 3 alignments will different flag 
combinations see: http://tinyurl.com/dy9a7

ChangeLog:
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.
-------------- next part --------------
Index: header.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/header.c,v
retrieving revision 1.73
diff -u -r1.73 header.c
--- header.c	23 Mar 2005 13:15:21 -0000	1.73
+++ header.c	11 May 2005 23:33:53 -0000
@@ -163,7 +163,7 @@
     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 @@
     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 @@
             SetBkMode(hdc, oldBkMode);
     }
     else {
-        UINT uTextJustify = DT_LEFT;
-
-        if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER)
-            uTextJustify = DT_CENTER;
-        else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT)
-            uTextJustify = DT_RIGHT;
-
-	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;
-
-	    }
+	UINT rw, rh, /* width and height of r */
+	     *x, *w; /* 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;
+
+	cw = tw = iw = bw = 0;
+	rw = r.right - r.left;
+	rh = r.bottom - r.top;
 
-	    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);
+	if (phdi->fmt & HDF_STRING) {
+	    RECT textRect;
 
-	    r.left += (bmp.bmWidth + infoPtr->iMargin);
+	    DrawTextW (hdc, phdi->pszText, -1,
+	               &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT);
+	    cw = textRect.right - textRect.left + 2 * 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->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) {
-	    BITMAP bmp;
-	    HDC    hdcBitmap;
-	    INT    xD, yD, yS, cx, cy, rx, ry, tx;
-	    RECT   textRect;
-
+	if ((phdi->fmt & HDF_BITMAP) && (phdi->hbm)) {
 	    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;
+	    bw = bmp.bmWidth + 2 * infoPtr->iMargin;
+	    if (!iw) {
+		x = &bx;
+		w = &bw;
 	    }
-	    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 (bw || iw)
+	    cw += *w; 
 
-	    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;
-		}
+	/* 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;
 	    }
-
-	    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 (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 ((phdi->fmt & HDF_IMAGE) && (phdi->fmt & HDF_BITMAP_ON_RIGHT) && (infoPtr->himl)) {
-	    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;
+	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 (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 (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);
 	    }
-	}	
 
-        if (((phdi->fmt & HDF_STRING)
+	    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);
         }


More information about the wine-patches mailing list