comctl32/button: Support imagelist rendering.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40445 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40062 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45246 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
790d13ee98
commit
c9aa8dab8f
|
@ -876,16 +876,18 @@ static RECT BUTTON_GetTextRect(const BUTTON_INFO *infoPtr, HDC hdc, const WCHAR
|
|||
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;
|
||||
return (style & (BS_ICON | BS_BITMAP)) && (infoPtr->u.image || infoPtr->imagelist.himl);
|
||||
}
|
||||
|
||||
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);
|
||||
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))
|
||||
|| (infoPtr->imagelist.himl && type != BS_GROUPBOX));
|
||||
}
|
||||
|
||||
static BOOL show_image(const BUTTON_INFO *infoPtr)
|
||||
|
@ -978,13 +980,35 @@ static void BUTTON_PositionRect(LONG style, const RECT *outerRect, RECT *innerRe
|
|||
}
|
||||
}
|
||||
|
||||
/* Convert imagelist align style to button align style */
|
||||
static UINT BUTTON_ILStoBS(UINT align)
|
||||
{
|
||||
switch (align)
|
||||
{
|
||||
case BUTTON_IMAGELIST_ALIGN_TOP:
|
||||
return BS_CENTER | BS_TOP;
|
||||
case BUTTON_IMAGELIST_ALIGN_BOTTOM:
|
||||
return BS_CENTER | BS_BOTTOM;
|
||||
case BUTTON_IMAGELIST_ALIGN_CENTER:
|
||||
return BS_CENTER | BS_VCENTER;
|
||||
case BUTTON_IMAGELIST_ALIGN_RIGHT:
|
||||
return BS_RIGHT | BS_VCENTER;
|
||||
case BUTTON_IMAGELIST_ALIGN_LEFT:
|
||||
default:
|
||||
return BS_LEFT | BS_VCENTER;
|
||||
}
|
||||
}
|
||||
|
||||
static SIZE BUTTON_GetImageSize(const BUTTON_INFO *infoPtr)
|
||||
{
|
||||
ICONINFO iconInfo;
|
||||
BITMAP bm = {0};
|
||||
SIZE size = {0};
|
||||
|
||||
if (infoPtr->u.image)
|
||||
/* ImageList has priority over image */
|
||||
if (infoPtr->imagelist.himl)
|
||||
ImageList_GetIconSize(infoPtr->imagelist.himl, &size.cx, &size.cy);
|
||||
else if (infoPtr->u.image)
|
||||
{
|
||||
if (infoPtr->image_type == IMAGE_ICON)
|
||||
{
|
||||
|
@ -1024,10 +1048,12 @@ static UINT BUTTON_CalcLayoutRects(const BUTTON_INFO *infoPtr, HDC hdc, RECT *la
|
|||
{
|
||||
LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
|
||||
LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
|
||||
LONG split_style = infoPtr->imagelist.himl ? BUTTON_ILStoBS(infoPtr->imagelist.uAlign) : style;
|
||||
WCHAR *text = get_button_text(infoPtr);
|
||||
SIZE imageSize = BUTTON_GetImageSize(infoPtr);
|
||||
UINT dtStyle = BUTTON_BStoDT(style, ex_style);
|
||||
RECT labelRect, imageRect, textRect;
|
||||
RECT labelRect, imageRect, imageRectWithMargin, textRect;
|
||||
LONG imageMarginWidth, imageMarginHeight;
|
||||
RECT emptyMargin = {0}, oneMargin = {1, 1, 1, 1};
|
||||
LONG maxTextWidth;
|
||||
|
||||
|
@ -1042,6 +1068,14 @@ static UINT BUTTON_CalcLayoutRects(const BUTTON_INFO *infoPtr, HDC hdc, RECT *la
|
|||
}
|
||||
|
||||
SetRect(&imageRect, 0, 0, imageSize.cx, imageSize.cy);
|
||||
imageRectWithMargin = imageRect;
|
||||
if (infoPtr->imagelist.himl)
|
||||
{
|
||||
imageRectWithMargin.top -= infoPtr->imagelist.margin.top;
|
||||
imageRectWithMargin.bottom += infoPtr->imagelist.margin.bottom;
|
||||
imageRectWithMargin.left -= infoPtr->imagelist.margin.left;
|
||||
imageRectWithMargin.right += infoPtr->imagelist.margin.right;
|
||||
}
|
||||
|
||||
/* Show image only */
|
||||
if (show_image_only(infoPtr))
|
||||
|
@ -1064,30 +1098,53 @@ static UINT BUTTON_CalcLayoutRects(const BUTTON_INFO *infoPtr, HDC hdc, RECT *la
|
|||
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;
|
||||
/* Image list may have different alignment than the button, use the whole rect for label in this case */
|
||||
if (infoPtr->imagelist.himl)
|
||||
labelRect = *labelRc;
|
||||
else
|
||||
boundingImageRect.right = boundingImageRect.left + imageSize.cx;
|
||||
BUTTON_PositionRect(style, &boundingImageRect, &imageRect, &emptyMargin);
|
||||
{
|
||||
/* Get a label bounding rectangle to position the label in the user specified label rectangle because
|
||||
* text and image need to align together. */
|
||||
boundingLabelRect = BUTTON_GetBoundingLabelRect(split_style, &textRect, &imageRectWithMargin);
|
||||
BUTTON_PositionRect(split_style, labelRc, &boundingLabelRect, &emptyMargin);
|
||||
labelRect = boundingLabelRect;
|
||||
}
|
||||
|
||||
/* Get text rect */
|
||||
SubtractRect(&boundingTextRect, &labelRect, &boundingImageRect);
|
||||
BUTTON_PositionRect(style, &boundingTextRect, &textRect, &oneMargin);
|
||||
/* When imagelist has center align, use the whole rect for imagelist and text */
|
||||
if(infoPtr->imagelist.himl && infoPtr->imagelist.uAlign == BUTTON_IMAGELIST_ALIGN_CENTER)
|
||||
{
|
||||
boundingImageRect = labelRect;
|
||||
boundingTextRect = labelRect;
|
||||
BUTTON_PositionRect(split_style, &boundingImageRect, &imageRect,
|
||||
infoPtr->imagelist.himl ? &infoPtr->imagelist.margin : &emptyMargin);
|
||||
/* Text doesn't use imagelist align */
|
||||
BUTTON_PositionRect(style, &boundingTextRect, &textRect, &oneMargin);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get image rect */
|
||||
/* Split the label rect to two halves as two bounding rectangles for image and text */
|
||||
boundingImageRect = labelRect;
|
||||
imageMarginWidth = imageRectWithMargin.right - imageRectWithMargin.left;
|
||||
imageMarginHeight = imageRectWithMargin.bottom - imageRectWithMargin.top;
|
||||
if ((split_style & BS_CENTER) == BS_RIGHT)
|
||||
boundingImageRect.left = boundingImageRect.right - imageMarginWidth;
|
||||
else if ((split_style & BS_CENTER) == BS_LEFT)
|
||||
boundingImageRect.right = boundingImageRect.left + imageMarginWidth;
|
||||
else if ((split_style & BS_VCENTER) == BS_BOTTOM)
|
||||
boundingImageRect.top = boundingImageRect.bottom - imageMarginHeight;
|
||||
else if ((split_style & BS_VCENTER) == BS_TOP)
|
||||
boundingImageRect.bottom = boundingImageRect.top + imageMarginHeight;
|
||||
else
|
||||
boundingImageRect.right = boundingImageRect.left + imageMarginWidth;
|
||||
BUTTON_PositionRect(split_style, &boundingImageRect, &imageRect,
|
||||
infoPtr->imagelist.himl ? &infoPtr->imagelist.margin : &emptyMargin);
|
||||
|
||||
/* Get text rect */
|
||||
SubtractRect(&boundingTextRect, &labelRect, &boundingImageRect);
|
||||
/* Text doesn't use imagelist align */
|
||||
BUTTON_PositionRect(style, &boundingTextRect, &textRect, &oneMargin);
|
||||
}
|
||||
}
|
||||
/* Show text only */
|
||||
else
|
||||
|
@ -1144,6 +1201,7 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
|
|||
UINT flags = IsWindowEnabled(infoPtr->hwnd) ? DSS_NORMAL : DSS_DISABLED;
|
||||
UINT imageFlags;
|
||||
LONG state = infoPtr->state;
|
||||
LONG draw_state;
|
||||
LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
|
||||
WCHAR *text = NULL;
|
||||
|
||||
|
@ -1158,23 +1216,39 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
|
|||
flags |= DSS_MONO;
|
||||
}
|
||||
|
||||
switch (infoPtr->image_type)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (show_image(infoPtr))
|
||||
DrawStateW(hdc, hbr, lpOutputProc, lp, wp, imageRect->left, imageRect->top,
|
||||
imageRect->right - imageRect->left, imageRect->bottom - imageRect->top, imageFlags);
|
||||
{
|
||||
if (infoPtr->imagelist.himl)
|
||||
{
|
||||
if (ImageList_GetImageCount(infoPtr->imagelist.himl) == 1)
|
||||
ImageList_Draw(infoPtr->imagelist.himl, 0, hdc, imageRect->left, imageRect->top, ILD_NORMAL);
|
||||
else
|
||||
{
|
||||
draw_state = get_draw_state(infoPtr);
|
||||
ImageList_Draw(infoPtr->imagelist.himl, draw_state - 1, hdc, imageRect->left, imageRect->top,
|
||||
ILD_NORMAL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (infoPtr->image_type)
|
||||
{
|
||||
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, imageRect->left, imageRect->top,
|
||||
imageRect->right - imageRect->left, imageRect->bottom - imageRect->top, imageFlags);
|
||||
}
|
||||
}
|
||||
|
||||
if (show_image_only(infoPtr)) return;
|
||||
|
||||
|
|
Loading…
Reference in New Issue