comctl32/button: Implement BCM_GETIDEALSIZE for command links.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2019-04-19 15:14:02 +03:00 committed by Alexandre Julliard
parent 7316f69389
commit b15859d871
2 changed files with 139 additions and 8 deletions

View file

@ -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
*

View file

@ -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
{