comctl32/button: Implement 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:
parent
4fa7aa29b5
commit
9fee8a7d25
|
@ -105,6 +105,7 @@ static void GB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
||||||
static void UB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
static void UB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
||||||
static void OB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
static void OB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
||||||
static void SB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
static void SB_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
||||||
|
static void CL_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action );
|
||||||
static void BUTTON_CheckAutoRadioButton( HWND hwnd );
|
static void BUTTON_CheckAutoRadioButton( HWND hwnd );
|
||||||
static void get_split_button_rects(const BUTTON_INFO*, const RECT*, RECT*, RECT*);
|
static void get_split_button_rects(const BUTTON_INFO*, const RECT*, RECT*, RECT*);
|
||||||
static BOOL notify_split_button_dropdown(const BUTTON_INFO*, const POINT*, HWND);
|
static BOOL notify_split_button_dropdown(const BUTTON_INFO*, const POINT*, HWND);
|
||||||
|
@ -161,8 +162,8 @@ static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
|
||||||
OB_Paint, /* BS_OWNERDRAW */
|
OB_Paint, /* BS_OWNERDRAW */
|
||||||
SB_Paint, /* BS_SPLITBUTTON */
|
SB_Paint, /* BS_SPLITBUTTON */
|
||||||
SB_Paint, /* BS_DEFSPLITBUTTON */
|
SB_Paint, /* BS_DEFSPLITBUTTON */
|
||||||
PB_Paint, /* BS_COMMANDLINK */
|
CL_Paint, /* BS_COMMANDLINK */
|
||||||
PB_Paint /* BS_DEFCOMMANDLINK */
|
CL_Paint /* BS_DEFCOMMANDLINK */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*pfThemedPaint)( HTHEME theme, const BUTTON_INFO *infoPtr, HDC hdc, int drawState, UINT dtflags, BOOL focused);
|
typedef void (*pfThemedPaint)( HTHEME theme, const BUTTON_INFO *infoPtr, HDC hdc, int drawState, UINT dtflags, BOOL focused);
|
||||||
|
@ -219,6 +220,12 @@ static const pfGetIdealSize btnGetIdealSizeFunc[MAX_BTN_TYPE] = {
|
||||||
PB_GetIdealSize /* BS_DEFCOMMANDLINK */
|
PB_GetIdealSize /* BS_DEFCOMMANDLINK */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Fixed margin for command links, regardless of DPI (based on tests done on Windows) */
|
||||||
|
enum { command_link_margin = 6 };
|
||||||
|
|
||||||
|
/* The width and height for the default command link glyph (when there's no image) */
|
||||||
|
enum { command_link_defglyph_size = 17 };
|
||||||
|
|
||||||
static inline UINT get_button_type( LONG window_style )
|
static inline UINT get_button_type( LONG window_style )
|
||||||
{
|
{
|
||||||
return (window_style & BS_TYPEMASK);
|
return (window_style & BS_TYPEMASK);
|
||||||
|
@ -2297,6 +2304,186 @@ static void draw_split_button_dropdown_glyph(const BUTTON_INFO *infoPtr, HDC hdc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Command Link Functions
|
||||||
|
*/
|
||||||
|
static void CL_Paint( const BUTTON_INFO *infoPtr, HDC hDC, UINT action )
|
||||||
|
{
|
||||||
|
LONG style = GetWindowLongW(infoPtr->hwnd, GWL_STYLE);
|
||||||
|
LONG state = infoPtr->state;
|
||||||
|
|
||||||
|
RECT rc, content_rect;
|
||||||
|
NMCUSTOMDRAW nmcd;
|
||||||
|
HPEN pen, old_pen;
|
||||||
|
HBRUSH old_brush;
|
||||||
|
INT old_bk_mode;
|
||||||
|
LRESULT cdrf;
|
||||||
|
HWND parent;
|
||||||
|
HRGN hrgn;
|
||||||
|
|
||||||
|
GetClientRect(infoPtr->hwnd, &rc);
|
||||||
|
|
||||||
|
/* Command Links are not affected by the button's font, and are based
|
||||||
|
on the default message font. Furthermore, they are not affected by
|
||||||
|
any of the alignment styles (and always align with the top-left). */
|
||||||
|
if (!(parent = GetParent(infoPtr->hwnd))) parent = infoPtr->hwnd;
|
||||||
|
SendMessageW(parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)infoPtr->hwnd);
|
||||||
|
|
||||||
|
hrgn = set_control_clipping(hDC, &rc);
|
||||||
|
|
||||||
|
pen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
|
||||||
|
old_pen = SelectObject(hDC, pen);
|
||||||
|
old_brush = SelectObject(hDC, GetSysColorBrush(COLOR_BTNFACE));
|
||||||
|
old_bk_mode = SetBkMode(hDC, TRANSPARENT);
|
||||||
|
|
||||||
|
init_custom_draw(&nmcd, infoPtr, hDC, &rc);
|
||||||
|
|
||||||
|
/* Send erase notifications */
|
||||||
|
cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
|
||||||
|
if (cdrf & CDRF_SKIPDEFAULT) goto cleanup;
|
||||||
|
content_rect = rc;
|
||||||
|
|
||||||
|
if (get_button_type(style) == BS_DEFCOMMANDLINK)
|
||||||
|
{
|
||||||
|
if (action != ODA_FOCUS)
|
||||||
|
Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
|
||||||
|
InflateRect(&rc, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the frame drawing if only focus has changed */
|
||||||
|
if (action != ODA_FOCUS)
|
||||||
|
{
|
||||||
|
if (!(state & (BST_HOT | BST_PUSHED | BST_CHECKED | BST_INDETERMINATE)))
|
||||||
|
FillRect(hDC, &rc, GetSysColorBrush(COLOR_BTNFACE));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT flags = DFCS_BUTTONPUSH;
|
||||||
|
|
||||||
|
if (style & BS_FLAT) flags |= DFCS_MONO;
|
||||||
|
else if (state & BST_PUSHED) flags |= DFCS_PUSHED;
|
||||||
|
|
||||||
|
if (state & (BST_CHECKED | BST_INDETERMINATE))
|
||||||
|
flags |= DFCS_CHECKED;
|
||||||
|
DrawFrameControl(hDC, &rc, DFC_BUTTON, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdrf & CDRF_NOTIFYPOSTERASE)
|
||||||
|
{
|
||||||
|
nmcd.dwDrawStage = CDDS_POSTERASE;
|
||||||
|
SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send paint notifications */
|
||||||
|
nmcd.dwDrawStage = CDDS_PREPAINT;
|
||||||
|
cdrf = SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
|
||||||
|
if (cdrf & CDRF_SKIPDEFAULT) goto cleanup;
|
||||||
|
|
||||||
|
if (!(cdrf & CDRF_DOERASE) && action != ODA_FOCUS)
|
||||||
|
{
|
||||||
|
UINT flags = IsWindowEnabled(infoPtr->hwnd) ? DSS_NORMAL : DSS_DISABLED;
|
||||||
|
COLORREF old_color = SetTextColor(hDC, GetSysColor(flags == DSS_NORMAL ?
|
||||||
|
COLOR_BTNTEXT : COLOR_GRAYTEXT));
|
||||||
|
HIMAGELIST defimg = NULL;
|
||||||
|
NONCLIENTMETRICSW ncm;
|
||||||
|
UINT txt_h = 0;
|
||||||
|
SIZE img_size;
|
||||||
|
|
||||||
|
/* Command Links ignore the margins of the image list or its alignment */
|
||||||
|
if (infoPtr->u.image || infoPtr->imagelist.himl)
|
||||||
|
img_size = BUTTON_GetImageSize(infoPtr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
img_size.cx = img_size.cy = command_link_defglyph_size;
|
||||||
|
defimg = ImageList_LoadImageW(COMCTL32_hModule, (LPCWSTR)MAKEINTRESOURCE(IDB_CMDLINK),
|
||||||
|
img_size.cx, 3, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shrink rect by the command link margin, except on bottom (just the frame) */
|
||||||
|
InflateRect(&content_rect, -command_link_margin, -command_link_margin);
|
||||||
|
content_rect.bottom += command_link_margin - 2;
|
||||||
|
|
||||||
|
ncm.cbSize = sizeof(ncm);
|
||||||
|
if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
|
||||||
|
{
|
||||||
|
LONG note_weight = ncm.lfMessageFont.lfWeight;
|
||||||
|
RECT r = content_rect;
|
||||||
|
WCHAR *text;
|
||||||
|
HFONT font;
|
||||||
|
|
||||||
|
if (img_size.cx) r.left += img_size.cx + command_link_margin;
|
||||||
|
|
||||||
|
/* Draw the text */
|
||||||
|
ncm.lfMessageFont.lfWeight = FW_BOLD;
|
||||||
|
if ((font = CreateFontIndirectW(&ncm.lfMessageFont)))
|
||||||
|
{
|
||||||
|
if ((text = get_button_text(infoPtr)))
|
||||||
|
{
|
||||||
|
SelectObject(hDC, font);
|
||||||
|
txt_h = DrawTextW(hDC, text, -1, &r,
|
||||||
|
DT_TOP | DT_LEFT | DT_WORDBREAK | DT_END_ELLIPSIS);
|
||||||
|
heap_free(text);
|
||||||
|
}
|
||||||
|
DeleteObject(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the note */
|
||||||
|
ncm.lfMessageFont.lfWeight = note_weight;
|
||||||
|
if (infoPtr->note && (font = CreateFontIndirectW(&ncm.lfMessageFont)))
|
||||||
|
{
|
||||||
|
r.top += txt_h + 2;
|
||||||
|
SelectObject(hDC, font);
|
||||||
|
DrawTextW(hDC, infoPtr->note, infoPtr->note_length, &r,
|
||||||
|
DT_TOP | DT_LEFT | DT_WORDBREAK | DT_NOPREFIX);
|
||||||
|
DeleteObject(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position the image at the vertical center of the drawn text (not note) */
|
||||||
|
txt_h = min(txt_h, content_rect.bottom - content_rect.top);
|
||||||
|
if (img_size.cy < txt_h) content_rect.top += (txt_h - img_size.cy) / 2;
|
||||||
|
|
||||||
|
content_rect.right = content_rect.left + img_size.cx;
|
||||||
|
content_rect.bottom = content_rect.top + img_size.cy;
|
||||||
|
|
||||||
|
if (defimg)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
if (flags == DSS_DISABLED) i = 2;
|
||||||
|
else if (state & BST_HOT) i = 1;
|
||||||
|
|
||||||
|
ImageList_Draw(defimg, i, hDC, content_rect.left, content_rect.top, ILD_NORMAL);
|
||||||
|
ImageList_Destroy(defimg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BUTTON_DrawImage(infoPtr, hDC, NULL, flags, &content_rect);
|
||||||
|
|
||||||
|
SetTextColor(hDC, old_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdrf & CDRF_NOTIFYPOSTPAINT)
|
||||||
|
{
|
||||||
|
nmcd.dwDrawStage = CDDS_POSTPAINT;
|
||||||
|
SendMessageW(parent, WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd);
|
||||||
|
}
|
||||||
|
if (cdrf & CDRF_SKIPPOSTPAINT) goto cleanup;
|
||||||
|
|
||||||
|
if (action == ODA_FOCUS || (state & BST_FOCUS))
|
||||||
|
{
|
||||||
|
InflateRect(&rc, -2, -2);
|
||||||
|
DrawFocusRect(hDC, &rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
SelectObject(hDC, old_pen);
|
||||||
|
SelectObject(hDC, old_brush);
|
||||||
|
SetBkMode(hDC, old_bk_mode);
|
||||||
|
SelectClipRgn(hDC, hrgn);
|
||||||
|
if (hrgn) DeleteObject(hrgn);
|
||||||
|
DeleteObject(pen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Themed Paint Functions
|
* Themed Paint Functions
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -80,6 +80,9 @@ extern HBRUSH COMCTL32_hPattern55AABrush DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
#define IDT_CHECK 401
|
#define IDT_CHECK 401
|
||||||
|
|
||||||
|
/* Command Link arrow */
|
||||||
|
#define IDB_CMDLINK 402
|
||||||
|
|
||||||
|
|
||||||
/* Cursors */
|
/* Cursors */
|
||||||
#define IDC_MOVEBUTTON 102
|
#define IDC_MOVEBUTTON 102
|
||||||
|
|
|
@ -144,6 +144,9 @@ IDB_HIST_SMALL BITMAP idb_hist_small.bmp
|
||||||
/* @makedep: idb_hist_large.bmp */
|
/* @makedep: idb_hist_large.bmp */
|
||||||
IDB_HIST_LARGE BITMAP idb_hist_large.bmp
|
IDB_HIST_LARGE BITMAP idb_hist_large.bmp
|
||||||
|
|
||||||
|
/* @makedep: idb_cmdlink.bmp */
|
||||||
|
IDB_CMDLINK BITMAP idb_cmdlink.bmp
|
||||||
|
|
||||||
/* @makedep: idc_copy.cur */
|
/* @makedep: idc_copy.cur */
|
||||||
IDC_COPY CURSOR idc_copy.cur
|
IDC_COPY CURSOR idc_copy.cur
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
Loading…
Reference in New Issue