Commit 81f64374 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

comctl32/button: Support BCM_GETIDEALSIZE message.

parent eb79ebe5
......@@ -28,7 +28,6 @@
* - WM_SETFOCUS: For (manual or automatic) radio buttons, send the parent window BN_CLICKED
* - WM_NCCREATE: Turns any BS_OWNERDRAW button into a BS_PUSHBUTTON button.
* - WM_SYSKEYUP
* - BCM_GETIDEALSIZE
*
* Notifications
* - BCN_HOTITEMCHANGE
......@@ -42,7 +41,6 @@
*
* Structures/Macros/Definitions
* - NMBCHOTITEM
* - Button_GetIdealSize
*/
#include <stdarg.h>
......@@ -187,6 +185,32 @@ static const pfThemedPaint btnThemedPaintFunc[MAX_BTN_TYPE] =
NULL, /* BS_DEFCOMMANDLINK */
};
typedef BOOL (*pfGetIdealSize)(BUTTON_INFO *infoPtr, SIZE *size);
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 const pfGetIdealSize btnGetIdealSizeFunc[MAX_BTN_TYPE] = {
PB_GetIdealSize, /* BS_PUSHBUTTON */
PB_GetIdealSize, /* BS_DEFPUSHBUTTON */
CB_GetIdealSize, /* BS_CHECKBOX */
CB_GetIdealSize, /* BS_AUTOCHECKBOX */
CB_GetIdealSize, /* BS_RADIOBUTTON */
GB_GetIdealSize, /* BS_3STATE */
GB_GetIdealSize, /* BS_AUTO3STATE */
GB_GetIdealSize, /* BS_GROUPBOX */
PB_GetIdealSize, /* BS_USERBUTTON */
CB_GetIdealSize, /* BS_AUTORADIOBUTTON */
GB_GetIdealSize, /* BS_PUSHBOX */
GB_GetIdealSize, /* BS_OWNERDRAW */
/* GetIdealSize() for following types are unimplemented, use BS_PUSHBUTTON's for now */
PB_GetIdealSize, /* BS_SPLITBUTTON */
PB_GetIdealSize, /* BS_DEFSPLITBUTTON */
PB_GetIdealSize, /* BS_COMMANDLINK */
PB_GetIdealSize /* BS_DEFCOMMANDLINK */
};
static inline UINT get_button_type( LONG window_style )
{
return (window_style & BS_TYPEMASK);
......@@ -846,6 +870,15 @@ static LRESULT CALLBACK BUTTON_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
return TRUE;
}
case BCM_GETIDEALSIZE:
{
SIZE *size = (SIZE *)lParam;
if (!size) return FALSE;
return btnGetIdealSizeFunc[btn_type](infoPtr, size);
}
case WM_NCHITTEST:
if(btn_type == BS_GROUPBOX) return HTTRANSPARENT;
/* fall through */
......@@ -1038,6 +1071,164 @@ static const RECT *BUTTON_GetTextMargin(const BUTTON_INFO *infoPtr)
return &oneMargin;
}
static void BUTTON_GetClientRectSize(BUTTON_INFO *infoPtr, SIZE *size)
{
RECT rect;
GetClientRect(infoPtr->hwnd, &rect);
size->cx = rect.right - rect.left;
size->cy = rect.bottom - rect.top;
}
static void BUTTON_GetTextIdealSize(BUTTON_INFO *infoPtr, LONG maxWidth, SIZE *size)
{
WCHAR *text = get_button_text(infoPtr);
HDC hdc;
RECT rect;
const RECT *margin = BUTTON_GetTextMargin(infoPtr);
if (maxWidth != 0)
{
maxWidth -= margin->right + margin->right;
if (maxWidth <= 0) maxWidth = 1;
}
hdc = GetDC(infoPtr->hwnd);
rect = BUTTON_GetTextRect(infoPtr, hdc, text, maxWidth);
ReleaseDC(infoPtr->hwnd, hdc);
heap_free(text);
size->cx = rect.right - rect.left + margin->left + margin->right;
size->cy = rect.bottom - rect.top + margin->top + margin->bottom;
}
static void BUTTON_GetLabelIdealSize(BUTTON_INFO *infoPtr, LONG maxWidth, SIZE *size)
{
LONG style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
SIZE imageSize;
SIZE textSize;
BOOL horizontal;
imageSize = BUTTON_GetImageSize(infoPtr);
if (infoPtr->imagelist.himl)
{
imageSize.cx += infoPtr->imagelist.margin.left + infoPtr->imagelist.margin.right;
imageSize.cy += infoPtr->imagelist.margin.top + infoPtr->imagelist.margin.bottom;
if (infoPtr->imagelist.uAlign == BUTTON_IMAGELIST_ALIGN_TOP
|| infoPtr->imagelist.uAlign == BUTTON_IMAGELIST_ALIGN_BOTTOM)
horizontal = FALSE;
else
horizontal = TRUE;
}
else
{
/* horizontal alignment flags has priority over vertical ones if both are specified */
if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER) && (style & BS_CENTER) != BS_CENTER)
|| !(style & BS_VCENTER) || (style & BS_VCENTER) == BS_VCENTER)
horizontal = TRUE;
else
horizontal = FALSE;
}
if (horizontal)
{
if (maxWidth != 0)
{
maxWidth -= imageSize.cx;
if (maxWidth <= 0) maxWidth = 1;
}
BUTTON_GetTextIdealSize(infoPtr, maxWidth, &textSize);
size->cx = textSize.cx + imageSize.cx;
size->cy = max(textSize.cy, imageSize.cy);
}
else
{
BUTTON_GetTextIdealSize(infoPtr, maxWidth, &textSize);
size->cx = max(textSize.cx, imageSize.cx);
size->cy = textSize.cy + imageSize.cy;
}
}
static BOOL GB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size)
{
BUTTON_GetClientRectSize(infoPtr, size);
return TRUE;
}
static BOOL CB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size)
{
LONG style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
WCHAR *text = get_button_text(infoPtr);
HDC hdc;
HFONT hfont;
SIZE labelSize;
INT textOffset;
INT textLength = 0;
double scaleX;
double scaleY;
LONG checkboxWidth, checkboxHeight;
LONG maxWidth = 0;
if (text) textLength = lstrlenW(text);
heap_free(text);
if (textLength == 0)
{
BUTTON_GetClientRectSize(infoPtr, size);
return TRUE;
}
hdc = GetDC(infoPtr->hwnd);
scaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0;
scaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0;
if ((hfont = infoPtr->font)) SelectObject(hdc, hfont);
GetCharWidthW(hdc, '0', '0', &textOffset);
textOffset /= 2;
ReleaseDC(infoPtr->hwnd, hdc);
checkboxWidth = 12 * scaleX + 1;
checkboxHeight = 12 * scaleY + 1;
if (size->cx)
{
maxWidth = size->cx - checkboxWidth - textOffset;
if (maxWidth <= 0) maxWidth = 1;
}
/* Checkbox doesn't support both image(but not image list) and text */
if (!(style & (BS_ICON | BS_BITMAP)) && infoPtr->u.image)
BUTTON_GetTextIdealSize(infoPtr, maxWidth, &labelSize);
else
BUTTON_GetLabelIdealSize(infoPtr, maxWidth, &labelSize);
size->cx = labelSize.cx + checkboxWidth + textOffset;
size->cy = max(labelSize.cy, checkboxHeight);
return TRUE;
}
static BOOL PB_GetIdealSize(BUTTON_INFO *infoPtr, SIZE *size)
{
WCHAR *text = get_button_text(infoPtr);
SIZE labelSize;
INT textLength = 0;
if (text) textLength = lstrlenW(text);
if (textLength == 0)
{
BUTTON_GetClientRectSize(infoPtr, size);
heap_free(text);
return TRUE;
}
heap_free(text);
/* Ideal size include text size even if image only flags(BS_ICON, BS_BITMAP) are specified */
BUTTON_GetLabelIdealSize(infoPtr, size->cx, &labelSize);
size->cx = labelSize.cx;
size->cy = labelSize.cy;
return TRUE;
}
/**********************************************************************
* BUTTON_CalcLayoutRects
*
......
......@@ -1109,6 +1109,8 @@ typedef struct tagNMBCHOTITEM
(BOOL)SNDMSG(button, BCM_GETTEXTMARGIN, 0, (LPARAM)(margin))
#define Button_SetTextMargin(button, margin) \
(BOOL)SNDMSG(button, BCM_SETTEXTMARGIN, 0, (LPARAM)(margin))
#define Button_GetIdealSize(button, size) \
(BOOL)SNDMSG(button, BCM_GETIDEALSIZE, 0, (LPARAM)(size))
/* Toolbar */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment