From: Zhiyi Zhang <zzhang(a)codeweavers.com>
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
Replaced {} -> {0} for struct initialization.
dlls/comctl32/button.c | 141 +++++++++++---------------
dlls/comctl32/tests/button.c | 234 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 295 insertions(+), 80 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 1e339ef19c..46a6ff4063 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -96,6 +96,7 @@ typedef struct _BUTTON_INFO
HFONT font;
WCHAR *note;
INT note_length;
+ DWORD image_type; /* IMAGE_BITMAP or IMAGE_ICON */
union
{
HICON icon;
@@ -718,18 +719,7 @@ static LRESULT CALLBACK BUTTON_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
break;
case BM_SETIMAGE:
- /* Check that image format matches button style */
- switch (style & (BS_BITMAP|BS_ICON))
- {
- case BS_BITMAP:
- if (wParam != IMAGE_BITMAP) return 0;
- break;
- case BS_ICON:
- if (wParam != IMAGE_ICON) return 0;
- break;
- default:
- return 0;
- }
+ infoPtr->image_type = (DWORD)wParam;
oldHbitmap = infoPtr->u.image;
infoPtr->u.image = (HANDLE)lParam;
InvalidateRect( hWnd, NULL, FALSE );
@@ -802,62 +792,51 @@ static UINT BUTTON_CalcLabelRect(const BUTTON_INFO *infoPtr, HDC hdc, RECT *rc)
{
LONG style = GetWindowLongW( infoPtr->hwnd, GWL_STYLE );
LONG ex_style = GetWindowLongW( infoPtr->hwnd, GWL_EXSTYLE );
- WCHAR *text;
+ WCHAR *text = get_button_text(infoPtr);
ICONINFO iconInfo;
- BITMAP bm;
+ BITMAP bm = { 0 };
UINT dtStyle = BUTTON_BStoDT( style, ex_style );
RECT r = *rc;
INT n;
/* Calculate label rectangle according to label type */
- switch (style & (BS_ICON|BS_BITMAP))
+ /* 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])
{
- case BS_TEXT:
- {
- HFONT hFont, hPrevFont = 0;
-
- if (!(text = get_button_text( infoPtr ))) goto empty_rect;
- if (!text[0])
- {
- heap_free( text );
- goto empty_rect;
- }
-
- if ((hFont = infoPtr->font)) hPrevFont = SelectObject( hdc, hFont );
- DrawTextW(hdc, text, -1, &r, dtStyle | DT_CALCRECT);
- if (hPrevFont) SelectObject( hdc, hPrevFont );
- heap_free( text );
- break;
- }
-
- case BS_ICON:
- if (!GetIconInfo(infoPtr->u.icon, &iconInfo))
- goto empty_rect;
-
- GetObjectW (iconInfo.hbmColor, sizeof(BITMAP), &bm);
-
- r.right = r.left + bm.bmWidth;
- r.bottom = r.top + bm.bmHeight;
-
- DeleteObject(iconInfo.hbmColor);
- DeleteObject(iconInfo.hbmMask);
- break;
-
- case BS_BITMAP:
- if (!GetObjectW( infoPtr->u.bitmap, sizeof(BITMAP), &bm))
- goto empty_rect;
-
- r.right = r.left + bm.bmWidth;
- r.bottom = r.top + bm.bmHeight;
- break;
-
- default:
- empty_rect:
- rc->right = r.left;
- rc->bottom = r.top;
- return (UINT)-1;
+ 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);
+ 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
@@ -934,28 +913,30 @@ static void BUTTON_DrawLabel(const BUTTON_INFO *infoPtr, HDC hdc, UINT dtFlags,
flags |= DSS_MONO;
}
- switch (style & (BS_ICON|BS_BITMAP))
+ /* FIXME: Support drawing label with both image and text */
+ if (infoPtr->u.image != 0)
+ {
+ 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
{
- case BS_TEXT:
- /* DST_COMPLEX -- is 0 */
- lpOutputProc = BUTTON_DrawTextCallback;
- if (!(text = get_button_text( infoPtr ))) return;
- lp = (LPARAM)text;
- wp = dtFlags;
- break;
-
- case BS_ICON:
- flags |= DST_ICON;
- lp = (LPARAM)infoPtr->u.icon;
- break;
-
- case BS_BITMAP:
- flags |= DST_BITMAP;
- lp = (LPARAM)infoPtr->u.bitmap;
- break;
-
- default:
- 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, rc->left, rc->top,
diff --git a/dlls/comctl32/tests/button.c b/dlls/comctl32/tests/button.c
index 5ad04d737f..6ac85a8aec 100644
--- a/dlls/comctl32/tests/button.c
+++ b/dlls/comctl32/tests/button.c
@@ -962,6 +962,239 @@ static void test_note(void)
}
}
+static void test_bm_get_set_image(void)
+{
+ HWND hwnd;
+ HDC hdc;
+ HBITMAP hbmp1x1;
+ HBITMAP hbmp2x2;
+ HBITMAP hmask2x2;
+ ICONINFO icon_info2x2;
+ HICON hicon2x2;
+ HBITMAP hbmp;
+ HICON hicon;
+ ICONINFO icon_info;
+ BITMAP bm;
+ static const DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE;
+
+ hdc = GetDC(0);
+ hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1);
+ hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2);
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+
+ hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2);
+ ZeroMemory(&icon_info2x2, sizeof(icon_info2x2));
+ icon_info2x2.fIcon = TRUE;
+ icon_info2x2.hbmMask = hmask2x2;
+ icon_info2x2.hbmColor = hbmp2x2;
+ hicon2x2 = CreateIconIndirect(&icon_info2x2);
+ ok(hicon2x2 !=NULL, "Expect CreateIconIndirect() success\n");
+
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ /* Get image when image is not set */
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ /* Set image */
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ /* Set null resets image */
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap without BS_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ if (hbmp == 0)
+ {
+ /* on xp or 2003*/
+ win_skip("Show both image and text is not supported. Skip following tests.\n");
+ DestroyWindow(hwnd);
+ goto done;
+ }
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0,
+ 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set icon without BS_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0,
+ 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_BITMAP and IMAGE_ICON*/
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_ICON and IMAGE_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0,
+ 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(BITMAP), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_ICON and IMAGE_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_BITMAP and IMAGE_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(BITMAP), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+done:
+ DestroyIcon(hicon2x2);
+ DeleteObject(hmask2x2);
+ DeleteObject(hbmp2x2);
+ DeleteObject(hbmp1x1);
+ ReleaseDC(0, hdc);
+}
+
static void register_parent_class(void)
{
WNDCLASSA cls;
@@ -1054,6 +1287,7 @@ START_TEST(button)
test_button_messages();
test_note();
test_button_data();
+ test_bm_get_set_image();
unload_v6_module(ctx_cookie, hCtx);
}
--
2.16.3