[PATCH 3/7] comctl32/button: Support displaying both image and text.

Zhiyi Zhang zzhang at codeweavers.com
Wed Sep 5 09:57:39 CDT 2018


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45727
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/comctl32/button.c | 421 +++++++++++++++++++++++++++++------------
 1 file changed, 295 insertions(+), 126 deletions(-)

diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 6f9bc39de5..653586a748 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -98,7 +98,7 @@ typedef struct _BUTTON_INFO
     } u;
 } BUTTON_INFO;
 
-static UINT BUTTON_CalcLabelRect( const BUTTON_INFO *infoPtr, HDC hdc, RECT *rc );
+static UINT BUTTON_CalcLayoutRects( const BUTTON_INFO *infoPtr, HDC hdc, RECT *labelRc, RECT *imageRc, RECT *textRc );
 static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
 static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
 static void GB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
@@ -615,7 +615,7 @@ static LRESULT CALLBACK BUTTON_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
             /* FIXME: check other BS_* handlers */
             if (btn_type == BS_GROUPBOX)
                 InflateRect(&rc, -7, 1); /* GB_Paint does this */
-            BUTTON_CalcLabelRect(infoPtr, hdc, &rc);
+            BUTTON_CalcLayoutRects(infoPtr, hdc, &rc, NULL, NULL);
             /* Clip by client rect bounds */
             if (rc.right > client.right) rc.right = client.right;
             if (rc.bottom > client.bottom) rc.bottom = client.bottom;
@@ -855,95 +855,257 @@ static LRESULT CALLBACK BUTTON_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
     return 0;
 }
 
+/* If maxWidth is zero, rectangle width is unlimited */
+static RECT BUTTON_GetTextRect(const BUTTON_INFO *infoPtr, HDC hdc, const WCHAR *text, LONG maxWidth)
+{
+    LONG style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
+    LONG exStyle = GetWindowLongW(infoPtr->hwnd, GWL_EXSTYLE);
+    UINT dtStyle = BUTTON_BStoDT(style, exStyle);
+    HFONT hPrevFont;
+    RECT rect = {0};
+
+    rect.right = maxWidth;
+    hPrevFont = SelectObject(hdc, infoPtr->font);
+    /* Calculate height without DT_VCENTER and DT_BOTTOM to get the correct height */
+    DrawTextW(hdc, text, -1, &rect, (dtStyle & ~(DT_VCENTER | DT_BOTTOM)) | DT_CALCRECT);
+    if (hPrevFont) SelectObject(hdc, hPrevFont);
+
+    return rect;
+}
+
+static BOOL show_image_only(const BUTTON_INFO *infoPtr)
+{
+    LONG style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
+    return (style & (BS_ICON | BS_BITMAP)) && infoPtr->u.image;
+}
+
+static BOOL show_image_and_text(const BUTTON_INFO *infoPtr)
+{
+    LONG style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
+    UINT type = get_button_type(style);
+    return !(style & (BS_ICON | BS_BITMAP)) && infoPtr->u.image
+           && (type == BS_PUSHBUTTON || type == BS_DEFPUSHBUTTON || type == BS_USERBUTTON || type == BS_SPLITBUTTON
+               || type == BS_DEFSPLITBUTTON || type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK);
+}
+
+static BOOL show_image(const BUTTON_INFO *infoPtr)
+{
+    return show_image_only(infoPtr) || show_image_and_text(infoPtr);
+}
+
+/* Get a bounding rectangle that is large enough to contain a image and a text side by side.
+ * Note: (left,top) of the result rectangle may not be (0,0), offset it by yourself if needed */
+static RECT BUTTON_GetBoundingLabelRect(LONG style, const RECT *textRect, const RECT *imageRect)
+{
+    RECT labelRect;
+    RECT rect = *imageRect;
+    INT textWidth = textRect->right - textRect->left;
+    INT textHeight = textRect->bottom - textRect->top;
+    INT imageWidth = imageRect->right - imageRect->left;
+    INT imageHeight = imageRect->bottom - imageRect->top;
+
+    if ((style & BS_CENTER) == BS_RIGHT)
+        OffsetRect(&rect, textWidth, 0);
+    else if ((style & BS_CENTER) == BS_LEFT)
+        OffsetRect(&rect, -imageWidth, 0);
+    else if ((style & BS_VCENTER) == BS_BOTTOM)
+        OffsetRect(&rect, 0, textHeight);
+    else if ((style & BS_VCENTER) == BS_TOP)
+        OffsetRect(&rect, 0, -imageHeight);
+    else
+        OffsetRect(&rect, -imageWidth, 0);
+
+    UnionRect(&labelRect, textRect, &rect);
+    return labelRect;
+}
+
+/* Position a rectangle inside a bounding rectangle according to button alignment flags */
+static void BUTTON_PositionRect(LONG style, const RECT *outerRect, RECT *innerRect, const RECT *margin)
+{
+    INT width = innerRect->right - innerRect->left;
+    INT height = innerRect->bottom - innerRect->top;
+
+    if ((style & WS_EX_RIGHT) && !(style & BS_CENTER)) style |= BS_CENTER;
+
+    if (!(style & BS_CENTER))
+    {
+        /* Push button's text is centered by default, all other types have left aligned text */
+        if (get_button_type(style) <= BS_DEFPUSHBUTTON)
+            style |= BS_CENTER;
+        else
+            style |= BS_LEFT;
+    }
+
+    if (!(style & BS_VCENTER))
+    {
+        /* Group box's text is top aligned by default */
+        if (get_button_type(style) == BS_GROUPBOX)
+            style |= BS_TOP;
+    }
+
+    switch (style & BS_CENTER)
+    {
+    case BS_CENTER:
+        innerRect->left = outerRect->left + (outerRect->right - outerRect->left - width) / 2;
+        innerRect->right = innerRect->left + width;
+        break;
+    case BS_RIGHT:
+        innerRect->right = outerRect->right - margin->right;
+        innerRect->left = innerRect->right - width;
+        break;
+    case BS_LEFT:
+    default:
+        innerRect->left = outerRect->left + margin->left;
+        innerRect->right = innerRect->left + width;
+        break;
+    }
+
+    switch (style & BS_VCENTER)
+    {
+    case BS_TOP:
+        innerRect->top = outerRect->top + margin->top;
+        innerRect->bottom = innerRect->top + height;
+        break;
+    case BS_BOTTOM:
+        innerRect->bottom = outerRect->bottom - margin->bottom;
+        innerRect->top = innerRect->bottom - height;
+        break;
+    case BS_VCENTER:
+    default:
+        innerRect->top = outerRect->top + (outerRect->bottom - outerRect->top - height) / 2;
+        innerRect->bottom = innerRect->top + height;
+        break;
+    }
+}
+
+static SIZE BUTTON_GetImageSize(const BUTTON_INFO *infoPtr)
+{
+    ICONINFO iconInfo;
+    BITMAP bm = {0};
+    SIZE size = {0};
+
+    if (infoPtr->u.image)
+    {
+        if (infoPtr->image_type == IMAGE_ICON)
+        {
+            GetIconInfo(infoPtr->u.icon, &iconInfo);
+            GetObjectW(iconInfo.hbmColor, sizeof(bm), &bm);
+            DeleteObject(iconInfo.hbmColor);
+            DeleteObject(iconInfo.hbmMask);
+        }
+        else if (infoPtr->image_type == IMAGE_BITMAP)
+            GetObjectW(infoPtr->u.bitmap, sizeof(bm), &bm);
+
+        size.cx = bm.bmWidth;
+        size.cy = bm.bmHeight;
+    }
+
+    return size;
+}
+
 /**********************************************************************
- *       BUTTON_CalcLabelRect
+ *       BUTTON_CalcLayoutRects
  *
- *   Calculates label's rectangle depending on button style.
+ *   Calculates the rectangles of the button label(image and text) and its parts depending on a button's style.
  *
  * Returns flags to be passed to DrawText.
  * Calculated rectangle doesn't take into account button state
  * (pushed, etc.). If there is nothing to draw (no text/image) output
  * rectangle is empty, and return value is (UINT)-1.
+ *
+ * PARAMS:
+ * infoPtr [I]   Button pointer
+ * hdc     [I]   Handle to device context to draw to
+ * labelRc [I/O] Input the rect the label to be positioned in, and output the label rect
+ * imageRc [O]   Optional, output the image rect
+ * textRc  [O]   Optional, output the text rect
  */
-static UINT BUTTON_CalcLabelRect(const BUTTON_INFO *infoPtr, HDC hdc, RECT *rc)
+static UINT BUTTON_CalcLayoutRects(const BUTTON_INFO *infoPtr, HDC hdc, RECT *labelRc, RECT *imageRc, RECT *textRc)
 {
    LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
    LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
    WCHAR *text = get_button_text(infoPtr);
-   ICONINFO    iconInfo;
-   BITMAP      bm = { 0 };
-   UINT        dtStyle = BUTTON_BStoDT( style, ex_style );
-   RECT        r = *rc;
-   INT         n;
+   SIZE imageSize = BUTTON_GetImageSize(infoPtr);
+   UINT dtStyle = BUTTON_BStoDT(style, ex_style);
+   RECT labelRect, imageRect, textRect;
+   RECT emptyMargin = {0}, oneMargin = {1, 1, 1, 1};
+   LONG maxTextWidth;
 
    /* Calculate label rectangle according to label type */
-   /* FIXME: Doesn't support showing both image and text yet */
-   if (infoPtr->u.image)
-   {
-       if (infoPtr->image_type == IMAGE_ICON)
-       {
-           GetIconInfo(infoPtr->u.icon, &iconInfo);
-           GetObjectW(iconInfo.hbmColor, sizeof(bm), &bm);
-           DeleteObject(iconInfo.hbmColor);
-           DeleteObject(iconInfo.hbmMask);
-       }
-       else if (infoPtr->image_type == IMAGE_BITMAP)
-       {
-           GetObjectW(infoPtr->u.bitmap, sizeof(bm), &bm);
-       }
-
-       r.right = r.left + bm.bmWidth;
-       r.bottom = r.top + bm.bmHeight;
-   }
-   else if (text && text[0])
+   if ((imageSize.cx == 0 && imageSize.cy == 0) && (text == NULL || text[0] == '\0'))
    {
-       HFONT hFont, hPrevFont = 0;
-
-       if ((hFont = infoPtr->font)) hPrevFont = SelectObject(hdc, hFont);
-       DrawTextW(hdc, text, -1, &r, dtStyle | DT_CALCRECT);
-       if (hPrevFont) SelectObject(hdc, hPrevFont);
-   }
-
-   if ((infoPtr->u.image && bm.bmWidth == 0 && bm.bmHeight == 0)
-       || (text == NULL || text[0] == '\0'))
-   {
-       rc->right = r.left;
-       rc->bottom = r.top;
+       SetRectEmpty(labelRc);
+       SetRectEmpty(imageRc);
+       SetRectEmpty(textRc);
        heap_free(text);
        return (UINT)-1;
    }
-   heap_free(text);
 
-   /* Position label inside bounding rectangle according to
-    * alignment flags. (calculated rect is always left-top aligned).
-    * If label is aligned to any side - shift label in opposite
-    * direction to leave extra space for focus rectangle.
-    */
-   switch (dtStyle & (DT_CENTER|DT_RIGHT))
+   SetRect(&imageRect, 0, 0, imageSize.cx, imageSize.cy);
+
+   /* Show image only */
+   if (show_image_only(infoPtr))
    {
-      case DT_LEFT:    r.left++;  r.right++;  break;
-      case DT_CENTER:  n = r.right - r.left;
-                       r.left   = rc->left + ((rc->right - rc->left) - n) / 2;
-                       r.right  = r.left + n; break;
-      case DT_RIGHT:   n = r.right - r.left;
-                       r.right  = rc->right - 1;
-                       r.left   = r.right - n;
-                       break;
+       BUTTON_PositionRect(style, labelRc, &imageRect,
+                           infoPtr->imagelist.himl ? &infoPtr->imagelist.margin : &emptyMargin);
+       labelRect = imageRect;
+       SetRectEmpty(&textRect);
    }
-
-   switch (dtStyle & (DT_VCENTER|DT_BOTTOM))
+   else
    {
-      case DT_TOP:     r.top++;  r.bottom++;  break;
-      case DT_VCENTER: n = r.bottom - r.top;
-                       r.top    = rc->top + ((rc->bottom - rc->top) - n) / 2;
-                       r.bottom = r.top + n;  break;
-      case DT_BOTTOM:  n = r.bottom - r.top;
-                       r.bottom = rc->bottom - 1;
-                       r.top    = r.bottom - n;
-                       break;
+       /* Get text rect */
+       maxTextWidth = labelRc->right - labelRc->left;
+       textRect = BUTTON_GetTextRect(infoPtr, hdc, text, maxTextWidth);
+       heap_free(text);
+
+       /* Show image and text */
+       if (show_image_and_text(infoPtr))
+       {
+           RECT boundingLabelRect, boundingImageRect, boundingTextRect;
+
+           /* Get label rect */
+           /* Get a label bounding rect to position the label in the user specified label rect because text and
+            * image need to align together. */
+           boundingLabelRect = BUTTON_GetBoundingLabelRect(style, &textRect, &imageRect);
+           BUTTON_PositionRect(style, labelRc, &boundingLabelRect, &emptyMargin);
+           labelRect = boundingLabelRect;
+
+           /* Get image rect */
+           /* Split the label rect to two halves as two bounding rects for image and text */
+           boundingImageRect = labelRect;
+           if ((style & BS_CENTER) == BS_RIGHT)
+               boundingImageRect.left = boundingImageRect.right - imageSize.cx;
+           else if ((style & BS_CENTER) == BS_LEFT)
+               boundingImageRect.right = boundingImageRect.left + imageSize.cx;
+           else if ((style & BS_VCENTER) == BS_BOTTOM)
+               boundingImageRect.top = boundingImageRect.bottom - imageSize.cy;
+           else if ((style & BS_VCENTER) == BS_TOP)
+               boundingImageRect.bottom = boundingImageRect.top + imageSize.cy;
+           else
+               boundingImageRect.right = boundingImageRect.left + imageSize.cx;
+           BUTTON_PositionRect(style, &boundingImageRect, &imageRect, &emptyMargin);
+
+           /* Get text rect */
+           SubtractRect(&boundingTextRect, &labelRect, &boundingImageRect);
+           BUTTON_PositionRect(style, &boundingTextRect, &textRect, &oneMargin);
+       }
+       /* Show text only */
+       else
+       {
+           if (get_button_type(style) != BS_GROUPBOX)
+               BUTTON_PositionRect(style, labelRc, &textRect, &oneMargin);
+           else
+               /* GroupBox is always top aligned */
+               BUTTON_PositionRect((style & ~BS_VCENTER) | BS_TOP, labelRc, &textRect, &oneMargin);
+           labelRect = textRect;
+           SetRectEmpty(&imageRect);
+       }
    }
 
-   *rc = r;
+   CopyRect(labelRc, &labelRect);
+   CopyRect(imageRc, &imageRect);
+   CopyRect(textRc, &textRect);
+
    return dtStyle;
 }
 
@@ -962,19 +1124,25 @@ static BOOL CALLBACK BUTTON_DrawTextCallback(HDC hdc, LPARAM lp, WPARAM wp, int
    return TRUE;
 }
 
-
 /**********************************************************************
  *       BUTTON_DrawLabel
  *
  *   Common function for drawing button label.
+ *
+ * FIXME:
+ *      1. When BS_SINGLELINE is specified and text contains '\t', '\n' or '\r' in the middle, they are rendered as
+ *         squares now whereas they should be ignored.
+ *      2. When BS_MULTILINE is specified and text contains space in the middle, the space mistakenly be rendered as newline.
  */
-static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags, const RECT *rc)
+static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags, const RECT *imageRect,
+                             const RECT *textRect)
 {
    DRAWSTATEPROC lpOutputProc = NULL;
    LPARAM lp;
    WPARAM wp = 0;
    HBRUSH hbr = 0;
    UINT flags = IsWindowEnabled(infoPtr->hwnd) ? DSS_NORMAL : DSS_DISABLED;
+   UINT imageFlags;
    LONG state = infoPtr->state;
    LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
    WCHAR *text = NULL;
@@ -990,35 +1158,34 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
       flags |= DSS_MONO;
    }
 
-   /* FIXME: Support drawing label with both image and text */
-   if (infoPtr->u.image != 0)
+   switch (infoPtr->image_type)
    {
-       switch (infoPtr->image_type)
-       {
-       case IMAGE_ICON:
-           flags |= DST_ICON;
-           lp = (LPARAM)infoPtr->u.icon;
-           break;
-       case IMAGE_BITMAP:
-           flags |= DST_BITMAP;
-           lp = (LPARAM)infoPtr->u.bitmap;
-           break;
-       default:
-           return;
-       }
-   }
-   else
-   {
-       /* DST_COMPLEX -- is 0 */
-       lpOutputProc = BUTTON_DrawTextCallback;
-       if (!(text = get_button_text(infoPtr))) return;
-       lp = (LPARAM)text;
-       wp = dtFlags;
+   case IMAGE_ICON:
+       imageFlags = flags | DST_ICON;
+       lp = (LPARAM)infoPtr->u.icon;
+       break;
+   case IMAGE_BITMAP:
+       imageFlags = flags | DST_BITMAP;
+       lp = (LPARAM)infoPtr->u.bitmap;
+       break;
+   default:
+       return;
    }
 
-   DrawStateW(hdc, hbr, lpOutputProc, lp, wp, rc->left, rc->top,
-              rc->right - rc->left, rc->bottom - rc->top, flags);
-   heap_free( text );
+   if (show_image(infoPtr))
+       DrawStateW(hdc, hbr, lpOutputProc, lp, wp, imageRect->left, imageRect->top,
+                  imageRect->right - imageRect->left, imageRect->bottom - imageRect->top, imageFlags);
+
+   if (show_image_only(infoPtr)) return;
+
+   /* DST_COMPLEX -- is 0 */
+   lpOutputProc = BUTTON_DrawTextCallback;
+   if (!(text = get_button_text(infoPtr))) return;
+   lp = (LPARAM)text;
+   wp = dtFlags;
+   DrawStateW(hdc, hbr, lpOutputProc, lp, wp, textRect->left, textRect->top, textRect->right - textRect->left,
+              textRect->bottom - textRect->top, flags);
+   heap_free(text);
 }
 
 /**********************************************************************
@@ -1026,7 +1193,7 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
  */
 static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
 {
-    RECT     rc, r;
+    RECT     rc, labelRect, imageRect, textRect;
     UINT     dtFlags, uState;
     HPEN     hOldPen, hpen;
     HBRUSH   hOldBrush;
@@ -1082,18 +1249,17 @@ static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
     DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
 
     /* draw button label */
-    r = rc;
-    dtFlags = BUTTON_CalcLabelRect(infoPtr, hDC, &r);
+    labelRect = rc;
+    dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
 
     if (dtFlags == (UINT)-1L)
        goto cleanup;
 
-    if (pushedState)
-       OffsetRect(&r, 1, 1);
+    if (pushedState) OffsetRect(&labelRect, 1, 1);
 
     oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
 
-    BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &r);
+    BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
 
     SetTextColor( hDC, oldTxtColor );
 
@@ -1119,7 +1285,7 @@ draw_focus:
 
 static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
 {
-    RECT rbox, rtext, client;
+    RECT rbox, labelRect, imageRect, textRect, client;
     HBRUSH hBrush;
     int delta, text_offset, checkBoxWidth, checkBoxHeight;
     UINT dtFlags;
@@ -1137,7 +1303,7 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
     }
 
     GetClientRect(infoPtr->hwnd, &client);
-    rbox = rtext = client;
+    rbox = labelRect = client;
 
     checkBoxWidth  = 12 * GetDpiForWindow( infoPtr->hwnd ) / 96 + 1;
     checkBoxHeight = 12 * GetDpiForWindow( infoPtr->hwnd ) / 96 + 1;
@@ -1155,12 +1321,12 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
 
     if (style & BS_LEFTTEXT || ex_style & WS_EX_RIGHT)
     {
-        rtext.right -= checkBoxWidth + text_offset;
+        labelRect.right -= checkBoxWidth + text_offset;
         rbox.left = rbox.right - checkBoxWidth;
     }
     else
     {
-        rtext.left += checkBoxWidth + text_offset;
+        labelRect.left += checkBoxWidth + text_offset;
         rbox.right = checkBoxWidth;
     }
 
@@ -1169,14 +1335,14 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
     if (action == ODA_DRAWENTIRE) FillRect( hDC, &client, hBrush );
 
     /* Draw label */
-    client = rtext;
-    dtFlags = BUTTON_CalcLabelRect(infoPtr, hDC, &rtext);
+    client = labelRect;
+    dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
 
     /* Only adjust rbox when rtext is valid */
     if (dtFlags != (UINT)-1L)
     {
-	rbox.top = rtext.top;
-	rbox.bottom = rtext.bottom;
+        rbox.top = labelRect.top;
+        rbox.bottom = labelRect.bottom;
     }
 
     /* Draw the check-box bitmap */
@@ -1229,16 +1395,15 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
     if (dtFlags == (UINT)-1L) /* Noting to draw */
 	return;
 
-    if (action == ODA_DRAWENTIRE)
-        BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &rtext);
+    if (action == ODA_DRAWENTIRE) BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
 
     /* ... and focus */
     if (action == ODA_FOCUS || (state & BST_FOCUS))
     {
-	rtext.left--;
-	rtext.right++;
-	IntersectRect(&rtext, &rtext, &client);
-	DrawFocusRect( hDC, &rtext );
+        labelRect.left--;
+        labelRect.right++;
+        IntersectRect(&labelRect, &labelRect, &client);
+        DrawFocusRect(hDC, &labelRect);
     }
     SelectClipRgn( hDC, hrgn );
     if (hrgn) DeleteObject( hrgn );
@@ -1274,7 +1439,7 @@ static void BUTTON_CheckAutoRadioButton( HWND hwnd )
 
 static void GB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
 {
-    RECT rc, rcFrame;
+    RECT labelRect, imageRect, textRect, rcFrame;
     HBRUSH hbr;
     HFONT hFont;
     UINT dtFlags;
@@ -1290,16 +1455,16 @@ static void GB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
     hbr = (HBRUSH)SendMessageW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
     if (!hbr) /* did the app forget to call defwindowproc ? */
         hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
-    GetClientRect( infoPtr->hwnd, &rc);
-    rcFrame = rc;
-    hrgn = set_control_clipping( hDC, &rc );
+    GetClientRect(infoPtr->hwnd, &labelRect);
+    rcFrame = labelRect;
+    hrgn = set_control_clipping(hDC, &labelRect);
 
     GetTextMetricsW (hDC, &tm);
     rcFrame.top += (tm.tmHeight / 2) - 1;
     DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT | ((style & BS_FLAT) ? BF_FLAT : 0));
 
-    InflateRect(&rc, -7, 1);
-    dtFlags = BUTTON_CalcLabelRect(infoPtr, hDC, &rc);
+    InflateRect(&labelRect, -7, 1);
+    dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
 
     if (dtFlags != (UINT)-1)
     {
@@ -1309,11 +1474,15 @@ static void GB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
          */
 
         /* There is 1-pixel margin at the left, right, and bottom */
-        rc.left--; rc.right++; rc.bottom++;
-        FillRect(hDC, &rc, hbr);
-        rc.left++; rc.right--; rc.bottom--;
-
-        BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &rc);
+        labelRect.left--;
+        labelRect.right++;
+        labelRect.bottom++;
+        FillRect(hDC, &labelRect, hbr);
+        labelRect.left++;
+        labelRect.right--;
+        labelRect.bottom--;
+
+        BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
     }
     SelectClipRgn( hDC, hrgn );
     if (hrgn) DeleteObject( hrgn );
-- 
2.18.0





More information about the wine-devel mailing list