=?UTF-8?Q?Gabriel=20Iv=C4=83ncescu=20?=: comctl32/button: Implement BCM_GETIDEALSIZE for command links.
Alexandre Julliard
julliard at winehq.org
Mon Apr 22 16:30:39 CDT 2019
Module: wine
Branch: master
Commit: b15859d871c50fff812c117ebc5d6eaa2e06fb5b
URL: https://source.winehq.org/git/wine.git/?a=commit;h=b15859d871c50fff812c117ebc5d6eaa2e06fb5b
Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date: Fri Apr 19 15:14:02 2019 +0300
comctl32/button: Implement BCM_GETIDEALSIZE for command links.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/comctl32/button.c | 137 ++++++++++++++++++++++++++++++++++++++++++-
dlls/comctl32/tests/button.c | 10 ++--
2 files changed, 139 insertions(+), 8 deletions(-)
diff --git a/dlls/comctl32/button.c b/dlls/comctl32/button.c
index 37212fb..0a8bdf1 100644
--- a/dlls/comctl32/button.c
+++ b/dlls/comctl32/button.c
@@ -200,6 +200,7 @@ static BOOL PB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size);
static BOOL CB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size);
static BOOL GB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size);
static BOOL SB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size);
+static BOOL CL_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size);
static const pfGetIdealSize btnGetIdealSizeFunc[MAX_BTN_TYPE] = {
PB_GetIdealSize, /* BS_PUSHBUTTON */
@@ -216,9 +217,8 @@ static const pfGetIdealSize btnGetIdealSizeFunc[MAX_BTN_TYPE] = {
GB_GetIdealSize, /* BS_OWNERDRAW */
SB_GetIdealSize, /* BS_SPLITBUTTON */
SB_GetIdealSize, /* BS_DEFSPLITBUTTON */
- /* GetIdealSize() for following types are unimplemented, use BS_PUSHBUTTON's for now */
- PB_GetIdealSize, /* BS_COMMANDLINK */
- PB_GetIdealSize /* BS_DEFCOMMANDLINK */
+ CL_GetIdealSize, /* BS_COMMANDLINK */
+ CL_GetIdealSize /* BS_DEFCOMMANDLINK */
};
/* Fixed margin for command links, regardless of DPI (based on tests done on Windows) */
@@ -1363,6 +1363,137 @@ static BOOL SB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size)
return TRUE;
}
+static BOOL CL_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size)
+{
+ HTHEME theme = GetWindowTheme(infoPtr->hwnd);
+ HDC hdc = GetDC(infoPtr->hwnd);
+ LONG w, text_w = 0, text_h = 0;
+ UINT flags = DT_TOP | DT_LEFT;
+ HFONT font, old_font = NULL;
+ RECT text_bound = { 0 };
+ SIZE img_size;
+ RECT margin;
+ WCHAR *text;
+
+ /* Get the image size */
+ if (infoPtr->u.image || infoPtr->imagelist.himl)
+ img_size = BUTTON_GetImageSize(infoPtr);
+ else
+ {
+ if (theme)
+ GetThemePartSize(theme, NULL, BP_COMMANDLINKGLYPH, CMDLS_NORMAL, NULL, TS_DRAW, &img_size);
+ else
+ img_size.cx = img_size.cy = command_link_defglyph_size;
+ }
+
+ /* Get the content margins */
+ if (theme)
+ {
+ RECT r = { 0, 0, 0xffff, 0xffff };
+ GetThemeBackgroundContentRect(theme, hdc, BP_COMMANDLINK, CMDLS_NORMAL, &r, &margin);
+ margin.left -= r.left;
+ margin.top -= r.top;
+ margin.right = r.right - margin.right;
+ margin.bottom = r.bottom - margin.bottom;
+ }
+ else
+ {
+ margin.left = margin.right = command_link_margin;
+ margin.top = margin.bottom = command_link_margin;
+ }
+
+ /* Account for the border margins and the margin between image and text */
+ w = margin.left + margin.right + (img_size.cx ? (img_size.cx + command_link_margin) : 0);
+
+ /* If a rectangle with a specific width was requested, bound the text to it */
+ if (size->cx > w)
+ {
+ text_bound.right = size->cx - w;
+ flags |= DT_WORDBREAK;
+ }
+
+ if (theme)
+ {
+ if (infoPtr->font) old_font = SelectObject(hdc, infoPtr->font);
+
+ /* Find the text's rect */
+ if ((text = get_button_text(infoPtr)))
+ {
+ RECT r;
+ GetThemeTextExtent(theme, hdc, BP_COMMANDLINK, CMDLS_NORMAL,
+ text, -1, flags, &text_bound, &r);
+ heap_free(text);
+ text_w = r.right - r.left;
+ text_h = r.bottom - r.top;
+ }
+
+ /* Find the note's rect */
+ if (infoPtr->note)
+ {
+ DTTOPTS opts;
+
+ opts.dwSize = sizeof(opts);
+ opts.dwFlags = DTT_FONTPROP | DTT_CALCRECT;
+ opts.iFontPropId = TMT_BODYFONT;
+ DrawThemeTextEx(theme, hdc, BP_COMMANDLINK, CMDLS_NORMAL,
+ infoPtr->note, infoPtr->note_length,
+ flags | DT_NOPREFIX | DT_CALCRECT, &text_bound, &opts);
+ text_w = max(text_w, text_bound.right - text_bound.left);
+ text_h += text_bound.bottom - text_bound.top;
+ }
+ }
+ else
+ {
+ NONCLIENTMETRICSW ncm;
+
+ ncm.cbSize = sizeof(ncm);
+ if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+ {
+ LONG note_weight = ncm.lfMessageFont.lfWeight;
+
+ /* Find the text's rect */
+ ncm.lfMessageFont.lfWeight = FW_BOLD;
+ if ((font = CreateFontIndirectW(&ncm.lfMessageFont)))
+ {
+ if ((text = get_button_text(infoPtr)))
+ {
+ RECT r = text_bound;
+ old_font = SelectObject(hdc, font);
+ DrawTextW(hdc, text, -1, &r, flags | DT_CALCRECT);
+ heap_free(text);
+
+ text_w = r.right - r.left;
+ text_h = r.bottom - r.top;
+ }
+ DeleteObject(font);
+ }
+
+ /* Find the note's rect */
+ ncm.lfMessageFont.lfWeight = note_weight;
+ if (infoPtr->note && (font = CreateFontIndirectW(&ncm.lfMessageFont)))
+ {
+ HFONT tmp = SelectObject(hdc, font);
+ if (!old_font) old_font = tmp;
+
+ DrawTextW(hdc, infoPtr->note, infoPtr->note_length, &text_bound,
+ flags | DT_NOPREFIX | DT_CALCRECT);
+ DeleteObject(font);
+
+ text_w = max(text_w, text_bound.right - text_bound.left);
+ text_h += text_bound.bottom - text_bound.top + 2;
+ }
+ }
+ }
+ w += text_w;
+
+ size->cx = min(size->cx, w);
+ size->cy = max(text_h, img_size.cy) + margin.top + margin.bottom;
+
+ if (old_font) SelectObject(hdc, old_font);
+ ReleaseDC(infoPtr->hwnd, hdc);
+ return TRUE;
+}
+
/**********************************************************************
* BUTTON_CalcLayoutRects
*
diff --git a/dlls/comctl32/tests/button.c b/dlls/comctl32/tests/button.c
index e0c4736..c31603f 100644
--- a/dlls/comctl32/tests/button.c
+++ b/dlls/comctl32/tests/button.c
@@ -2162,8 +2162,8 @@ static void test_bcm_get_ideal_size(void)
if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
{
- todo_wine ok((size.cx == 0 && size.cy > 0), "Style 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n",
- style, size.cx, 0, size.cy, 0);
+ ok((size.cx == 0 && size.cy > 0), "Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n",
+ style, size.cx, 0, size.cy, 0);
}
else
{
@@ -2199,9 +2199,9 @@ static void test_bcm_get_ideal_size(void)
}
else if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
{
- todo_wine ok((size.cx == 0 && size.cy > 0),
- "Style 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 0,
- size.cy, 0);
+ ok((size.cx == 0 && size.cy > 0),
+ "Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n", style, size.cx, 0,
+ size.cy, 0);
}
else
{
More information about the wine-cvs
mailing list