comctl32/button: Support displaying both image and text.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45727 Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fa4183ef84
commit
1f323f31d6
|
@ -98,7 +98,7 @@ typedef struct _BUTTON_INFO
|
||||||
} u;
|
} u;
|
||||||
} BUTTON_INFO;
|
} 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 PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
||||||
static void CB_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 );
|
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 */
|
/* FIXME: check other BS_* handlers */
|
||||||
if (btn_type == BS_GROUPBOX)
|
if (btn_type == BS_GROUPBOX)
|
||||||
InflateRect(&rc, -7, 1); /* GB_Paint does this */
|
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 */
|
/* Clip by client rect bounds */
|
||||||
if (rc.right > client.right) rc.right = client.right;
|
if (rc.right > client.right) rc.right = client.right;
|
||||||
if (rc.bottom > client.bottom) rc.bottom = client.bottom;
|
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;
|
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.
|
* Returns flags to be passed to DrawText.
|
||||||
* Calculated rectangle doesn't take into account button state
|
* Calculated rectangle doesn't take into account button state
|
||||||
* (pushed, etc.). If there is nothing to draw (no text/image) output
|
* (pushed, etc.). If there is nothing to draw (no text/image) output
|
||||||
* rectangle is empty, and return value is (UINT)-1.
|
* 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 style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
|
||||||
LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
|
LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
|
||||||
WCHAR *text = get_button_text(infoPtr);
|
WCHAR *text = get_button_text(infoPtr);
|
||||||
ICONINFO iconInfo;
|
SIZE imageSize = BUTTON_GetImageSize(infoPtr);
|
||||||
BITMAP bm = { 0 };
|
UINT dtStyle = BUTTON_BStoDT(style, ex_style);
|
||||||
UINT dtStyle = BUTTON_BStoDT( style, ex_style );
|
RECT labelRect, imageRect, textRect;
|
||||||
RECT r = *rc;
|
RECT emptyMargin = {0}, oneMargin = {1, 1, 1, 1};
|
||||||
INT n;
|
LONG maxTextWidth;
|
||||||
|
|
||||||
/* Calculate label rectangle according to label type */
|
/* Calculate label rectangle according to label type */
|
||||||
/* FIXME: Doesn't support showing both image and text yet */
|
if ((imageSize.cx == 0 && imageSize.cy == 0) && (text == NULL || text[0] == '\0'))
|
||||||
if (infoPtr->u.image)
|
|
||||||
{
|
{
|
||||||
if (infoPtr->image_type == IMAGE_ICON)
|
SetRectEmpty(labelRc);
|
||||||
{
|
SetRectEmpty(imageRc);
|
||||||
GetIconInfo(infoPtr->u.icon, &iconInfo);
|
SetRectEmpty(textRc);
|
||||||
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])
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
heap_free(text);
|
heap_free(text);
|
||||||
return (UINT)-1;
|
return (UINT)-1;
|
||||||
}
|
}
|
||||||
heap_free(text);
|
|
||||||
|
|
||||||
/* Position label inside bounding rectangle according to
|
SetRect(&imageRect, 0, 0, imageSize.cx, imageSize.cy);
|
||||||
* alignment flags. (calculated rect is always left-top aligned).
|
|
||||||
* If label is aligned to any side - shift label in opposite
|
/* Show image only */
|
||||||
* direction to leave extra space for focus rectangle.
|
if (show_image_only(infoPtr))
|
||||||
*/
|
|
||||||
switch (dtStyle & (DT_CENTER|DT_RIGHT))
|
|
||||||
{
|
{
|
||||||
case DT_LEFT: r.left++; r.right++; break;
|
BUTTON_PositionRect(style, labelRc, &imageRect,
|
||||||
case DT_CENTER: n = r.right - r.left;
|
infoPtr->imagelist.himl ? &infoPtr->imagelist.margin : &emptyMargin);
|
||||||
r.left = rc->left + ((rc->right - rc->left) - n) / 2;
|
labelRect = imageRect;
|
||||||
r.right = r.left + n; break;
|
SetRectEmpty(&textRect);
|
||||||
case DT_RIGHT: n = r.right - r.left;
|
}
|
||||||
r.right = rc->right - 1;
|
else
|
||||||
r.left = r.right - 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dtStyle & (DT_VCENTER|DT_BOTTOM))
|
CopyRect(labelRc, &labelRect);
|
||||||
{
|
CopyRect(imageRc, &imageRect);
|
||||||
case DT_TOP: r.top++; r.bottom++; break;
|
CopyRect(textRc, &textRect);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*rc = r;
|
|
||||||
return dtStyle;
|
return dtStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,19 +1124,25 @@ static BOOL CALLBACK BUTTON_DrawTextCallback(HDC hdc, LPARAM lp, WPARAM wp, int
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* BUTTON_DrawLabel
|
* BUTTON_DrawLabel
|
||||||
*
|
*
|
||||||
* Common function for drawing button label.
|
* 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;
|
DRAWSTATEPROC lpOutputProc = NULL;
|
||||||
LPARAM lp;
|
LPARAM lp;
|
||||||
WPARAM wp = 0;
|
WPARAM wp = 0;
|
||||||
HBRUSH hbr = 0;
|
HBRUSH hbr = 0;
|
||||||
UINT flags = IsWindowEnabled(infoPtr->hwnd) ? DSS_NORMAL : DSS_DISABLED;
|
UINT flags = IsWindowEnabled(infoPtr->hwnd) ? DSS_NORMAL : DSS_DISABLED;
|
||||||
|
UINT imageFlags;
|
||||||
LONG state = infoPtr->state;
|
LONG state = infoPtr->state;
|
||||||
LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
|
LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
|
||||||
WCHAR *text = NULL;
|
WCHAR *text = NULL;
|
||||||
|
@ -990,35 +1158,34 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
|
||||||
flags |= DSS_MONO;
|
flags |= DSS_MONO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Support drawing label with both image and text */
|
switch (infoPtr->image_type)
|
||||||
if (infoPtr->u.image != 0)
|
|
||||||
{
|
{
|
||||||
switch (infoPtr->image_type)
|
case IMAGE_ICON:
|
||||||
{
|
imageFlags = flags | DST_ICON;
|
||||||
case IMAGE_ICON:
|
lp = (LPARAM)infoPtr->u.icon;
|
||||||
flags |= DST_ICON;
|
break;
|
||||||
lp = (LPARAM)infoPtr->u.icon;
|
case IMAGE_BITMAP:
|
||||||
break;
|
imageFlags = flags | DST_BITMAP;
|
||||||
case IMAGE_BITMAP:
|
lp = (LPARAM)infoPtr->u.bitmap;
|
||||||
flags |= DST_BITMAP;
|
break;
|
||||||
lp = (LPARAM)infoPtr->u.bitmap;
|
default:
|
||||||
break;
|
return;
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 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, rc->left, rc->top,
|
if (show_image(infoPtr))
|
||||||
rc->right - rc->left, rc->bottom - rc->top, flags);
|
DrawStateW(hdc, hbr, lpOutputProc, lp, wp, imageRect->left, imageRect->top,
|
||||||
heap_free( text );
|
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 )
|
static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
||||||
{
|
{
|
||||||
RECT rc, r;
|
RECT rc, labelRect, imageRect, textRect;
|
||||||
UINT dtFlags, uState;
|
UINT dtFlags, uState;
|
||||||
HPEN hOldPen, hpen;
|
HPEN hOldPen, hpen;
|
||||||
HBRUSH hOldBrush;
|
HBRUSH hOldBrush;
|
||||||
|
@ -1082,18 +1249,17 @@ static void PB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
||||||
DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
|
DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
|
||||||
|
|
||||||
/* draw button label */
|
/* draw button label */
|
||||||
r = rc;
|
labelRect = rc;
|
||||||
dtFlags = BUTTON_CalcLabelRect(infoPtr, hDC, &r);
|
dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
|
||||||
|
|
||||||
if (dtFlags == (UINT)-1L)
|
if (dtFlags == (UINT)-1L)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (pushedState)
|
if (pushedState) OffsetRect(&labelRect, 1, 1);
|
||||||
OffsetRect(&r, 1, 1);
|
|
||||||
|
|
||||||
oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
|
oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
|
||||||
|
|
||||||
BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &r);
|
BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
|
||||||
|
|
||||||
SetTextColor( hDC, oldTxtColor );
|
SetTextColor( hDC, oldTxtColor );
|
||||||
|
|
||||||
|
@ -1119,7 +1285,7 @@ draw_focus:
|
||||||
|
|
||||||
static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
||||||
{
|
{
|
||||||
RECT rbox, rtext, client;
|
RECT rbox, labelRect, imageRect, textRect, client;
|
||||||
HBRUSH hBrush;
|
HBRUSH hBrush;
|
||||||
int delta, text_offset, checkBoxWidth, checkBoxHeight;
|
int delta, text_offset, checkBoxWidth, checkBoxHeight;
|
||||||
UINT dtFlags;
|
UINT dtFlags;
|
||||||
|
@ -1137,7 +1303,7 @@ static void CB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
||||||
}
|
}
|
||||||
|
|
||||||
GetClientRect(infoPtr->hwnd, &client);
|
GetClientRect(infoPtr->hwnd, &client);
|
||||||
rbox = rtext = client;
|
rbox = labelRect = client;
|
||||||
|
|
||||||
checkBoxWidth = 12 * GetDpiForWindow( infoPtr->hwnd ) / 96 + 1;
|
checkBoxWidth = 12 * GetDpiForWindow( infoPtr->hwnd ) / 96 + 1;
|
||||||
checkBoxHeight = 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)
|
if (style & BS_LEFTTEXT || ex_style & WS_EX_RIGHT)
|
||||||
{
|
{
|
||||||
rtext.right -= checkBoxWidth + text_offset;
|
labelRect.right -= checkBoxWidth + text_offset;
|
||||||
rbox.left = rbox.right - checkBoxWidth;
|
rbox.left = rbox.right - checkBoxWidth;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rtext.left += checkBoxWidth + text_offset;
|
labelRect.left += checkBoxWidth + text_offset;
|
||||||
rbox.right = checkBoxWidth;
|
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 );
|
if (action == ODA_DRAWENTIRE) FillRect( hDC, &client, hBrush );
|
||||||
|
|
||||||
/* Draw label */
|
/* Draw label */
|
||||||
client = rtext;
|
client = labelRect;
|
||||||
dtFlags = BUTTON_CalcLabelRect(infoPtr, hDC, &rtext);
|
dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
|
||||||
|
|
||||||
/* Only adjust rbox when rtext is valid */
|
/* Only adjust rbox when rtext is valid */
|
||||||
if (dtFlags != (UINT)-1L)
|
if (dtFlags != (UINT)-1L)
|
||||||
{
|
{
|
||||||
rbox.top = rtext.top;
|
rbox.top = labelRect.top;
|
||||||
rbox.bottom = rtext.bottom;
|
rbox.bottom = labelRect.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the check-box bitmap */
|
/* 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 */
|
if (dtFlags == (UINT)-1L) /* Noting to draw */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (action == ODA_DRAWENTIRE)
|
if (action == ODA_DRAWENTIRE) BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
|
||||||
BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &rtext);
|
|
||||||
|
|
||||||
/* ... and focus */
|
/* ... and focus */
|
||||||
if (action == ODA_FOCUS || (state & BST_FOCUS))
|
if (action == ODA_FOCUS || (state & BST_FOCUS))
|
||||||
{
|
{
|
||||||
rtext.left--;
|
labelRect.left--;
|
||||||
rtext.right++;
|
labelRect.right++;
|
||||||
IntersectRect(&rtext, &rtext, &client);
|
IntersectRect(&labelRect, &labelRect, &client);
|
||||||
DrawFocusRect( hDC, &rtext );
|
DrawFocusRect(hDC, &labelRect);
|
||||||
}
|
}
|
||||||
SelectClipRgn( hDC, hrgn );
|
SelectClipRgn( hDC, hrgn );
|
||||||
if (hrgn) DeleteObject( 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 )
|
static void GB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
||||||
{
|
{
|
||||||
RECT rc, rcFrame;
|
RECT labelRect, imageRect, textRect, rcFrame;
|
||||||
HBRUSH hbr;
|
HBRUSH hbr;
|
||||||
HFONT hFont;
|
HFONT hFont;
|
||||||
UINT dtFlags;
|
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);
|
hbr = (HBRUSH)SendMessageW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
|
||||||
if (!hbr) /* did the app forget to call defwindowproc ? */
|
if (!hbr) /* did the app forget to call defwindowproc ? */
|
||||||
hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
|
hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
|
||||||
GetClientRect( infoPtr->hwnd, &rc);
|
GetClientRect(infoPtr->hwnd, &labelRect);
|
||||||
rcFrame = rc;
|
rcFrame = labelRect;
|
||||||
hrgn = set_control_clipping( hDC, &rc );
|
hrgn = set_control_clipping(hDC, &labelRect);
|
||||||
|
|
||||||
GetTextMetricsW (hDC, &tm);
|
GetTextMetricsW (hDC, &tm);
|
||||||
rcFrame.top += (tm.tmHeight / 2) - 1;
|
rcFrame.top += (tm.tmHeight / 2) - 1;
|
||||||
DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT | ((style & BS_FLAT) ? BF_FLAT : 0));
|
DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT | ((style & BS_FLAT) ? BF_FLAT : 0));
|
||||||
|
|
||||||
InflateRect(&rc, -7, 1);
|
InflateRect(&labelRect, -7, 1);
|
||||||
dtFlags = BUTTON_CalcLabelRect(infoPtr, hDC, &rc);
|
dtFlags = BUTTON_CalcLayoutRects(infoPtr, hDC, &labelRect, &imageRect, &textRect);
|
||||||
|
|
||||||
if (dtFlags != (UINT)-1)
|
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 */
|
/* There is 1-pixel margin at the left, right, and bottom */
|
||||||
rc.left--; rc.right++; rc.bottom++;
|
labelRect.left--;
|
||||||
FillRect(hDC, &rc, hbr);
|
labelRect.right++;
|
||||||
rc.left++; rc.right--; rc.bottom--;
|
labelRect.bottom++;
|
||||||
|
FillRect(hDC, &labelRect, hbr);
|
||||||
|
labelRect.left++;
|
||||||
|
labelRect.right--;
|
||||||
|
labelRect.bottom--;
|
||||||
|
|
||||||
BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &rc);
|
BUTTON_DrawLabel(infoPtr, hDC, dtFlags, &imageRect, &textRect);
|
||||||
}
|
}
|
||||||
SelectClipRgn( hDC, hrgn );
|
SelectClipRgn( hDC, hrgn );
|
||||||
if (hrgn) DeleteObject( hrgn );
|
if (hrgn) DeleteObject( hrgn );
|
||||||
|
|
Loading…
Reference in New Issue