From 61f89b4dd118d91f926edb145187bc3c6391d40a Mon Sep 17 00:00:00 2001 From: Reece Dunn Date: Tue, 29 Jul 2008 00:01:41 +0100 Subject: [PATCH] comctl32: support for drawing themed push buttons. --- dlls/comctl32/theme_button.c | 92 +++++++++++++++++++++++++++++++++++++++--- 1 files changed, 86 insertions(+), 6 deletions(-) diff --git a/dlls/comctl32/theme_button.c b/dlls/comctl32/theme_button.c index 54955fa..3c47825 100644 --- a/dlls/comctl32/theme_button.c +++ b/dlls/comctl32/theme_button.c @@ -36,15 +36,90 @@ WINE_DEFAULT_DEBUG_CHANNEL(themingbutton); #define BUTTON_TYPE 0x0f /* bit mask for the available button types */ -typedef void (*pfThemedPaint)(HTHEME theme, HWND hwnd, HDC hdc); +/* These are indices into a states array to determine the theme state for a given theme part. */ +#define STATE_NORMAL 0 +#define STATE_DISABLED 1 +#define STATE_HOT 2 +#define STATE_PRESSED 3 +#define STATE_DEFAULTED 4 -static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC) +typedef void (*pfThemedPaint)(HTHEME theme, HWND hwnd, HDC hdc, int drawState, UINT dtFlags); + +static UINT get_drawtext_flags(DWORD style, DWORD ex_style) { + UINT flags = 0; + + if (style & BS_PUSHLIKE) + style &= ~BUTTON_TYPE; + + if (!(style & BS_MULTILINE)) + flags |= DT_SINGLELINE; + else + flags |= DT_WORDBREAK; + + switch (style & BS_CENTER) + { + case BS_LEFT: flags |= DT_LEFT; break; + case BS_RIGHT: flags |= DT_RIGHT; break; + case BS_CENTER: flags |= DT_CENTER; break; + default: + flags |= ((style & BUTTON_TYPE) <= BS_DEFPUSHBUTTON) + ? DT_CENTER : DT_LEFT; + } + + if (ex_style & WS_EX_RIGHT) + flags = DT_RIGHT | (flags & ~(DT_LEFT | DT_CENTER)); + + if ((style & BUTTON_TYPE) != BS_GROUPBOX) + { + switch (style & BS_VCENTER) + { + case BS_TOP: flags |= DT_TOP; break; + case BS_BOTTOM: flags |= DT_BOTTOM; break; + case BS_VCENTER: /* fall through */ + default: flags |= DT_VCENTER; break; + } + } + else + /* GroupBox's text is always single line and is top aligned. */ + flags |= DT_SINGLELINE | DT_TOP; + + return flags; +} + +static void PB_draw(HTHEME theme, HWND hwnd, HDC hDC, int drawState, UINT dtFlags) +{ + static const int states[] = { PBS_NORMAL, PBS_DISABLED, PBS_HOT, PBS_PRESSED, PBS_DEFAULTED }; + + RECT bgRect, textRect; + HFONT font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); + HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; + int state = states[ drawState ]; + WCHAR text[MAX_PATH]; + int len = MAX_PATH; + + GetClientRect(hwnd, &bgRect); + textRect = bgRect; + + len = GetWindowTextW(hwnd, text, len); + + if (IsThemeBackgroundPartiallyTransparent(theme, BP_PUSHBUTTON, state)) + DrawThemeParentBackground(hwnd, hDC, NULL); + DrawThemeBackground(theme, hDC, BP_PUSHBUTTON, state, &bgRect, NULL); + DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, len, dtFlags, 0, &textRect); + + if (hPrevFont) SelectObject(hDC, hPrevFont); +} + +static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC, int drawState, UINT dtFlags) +{ + static const int states[] = { GBS_NORMAL, GBS_DISABLED, GBS_NORMAL, GBS_NORMAL, GBS_NORMAL }; + RECT bgRect, textRect; SIZE textExtent; HFONT font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; - int state = IsWindowEnabled(hwnd) ? GBS_NORMAL : GBS_DISABLED; + int state = states[ drawState ]; WCHAR text[MAX_PATH]; int len = MAX_PATH; @@ -62,6 +137,8 @@ static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC) ExcludeClipRect(hDC, textRect.left, textRect.top, textRect.right, textRect.bottom); + if (IsThemeBackgroundPartiallyTransparent(theme, BP_GROUPBOX, state)) + DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, BP_GROUPBOX, state, &bgRect, NULL); SelectClipRgn(hDC, NULL); @@ -75,8 +152,8 @@ static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC) static const pfThemedPaint btnThemedPaintFunc[BUTTON_TYPE + 1] = { - NULL, /* BS_PUSHBUTTON */ - NULL, /* BS_DEFPUSHBUTTON */ + PB_draw, /* BS_PUSHBUTTON */ + PB_draw, /* BS_DEFPUSHBUTTON */ NULL, /* BS_CHECKBOX */ NULL, /* BS_AUTOCHECKBOX */ NULL, /* BS_RADIOBUTTON */ @@ -98,12 +175,15 @@ static BOOL BUTTON_Paint(HTHEME theme, HWND hwnd, HDC hParamDC) PAINTSTRUCT ps; HDC hDC; DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); + DWORD dwStyleEx = GetWindowLongW(hwnd, GWL_EXSTYLE); + UINT dtFlags = get_drawtext_flags(dwStyle, dwStyleEx); + int drawState = IsWindowEnabled(hwnd) ? STATE_NORMAL : STATE_DISABLED; pfThemedPaint paint = btnThemedPaintFunc[ dwStyle & BUTTON_TYPE ]; if (paint) { hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps); - paint(theme, hwnd, hDC); + paint(theme, hwnd, hDC, drawState, dtFlags); if (!hParamDC) EndPaint(hwnd, &ps); return TRUE; } -- 1.5.4.3