From a4ea17218f3062e7089d5913985473f78f284cbf Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Fri, 17 Nov 2017 14:00:30 +0200 Subject: [PATCH] [COMCTL32] Implement using different image list images depending on the button state --- dll/win32/comctl32/button.c | 21 +++- dll/win32/comctl32/theme_button.c | 179 ++++-------------------------- 2 files changed, 39 insertions(+), 161 deletions(-) diff --git a/dll/win32/comctl32/button.c b/dll/win32/comctl32/button.c index eb627145f3a..bdc91840d5c 100644 --- a/dll/win32/comctl32/button.c +++ b/dll/win32/comctl32/button.c @@ -395,10 +395,10 @@ cleanup: return ret; } -BOOL BUTTON_DrawIml(HDC hDC, BUTTON_IMAGELIST *pimlData, RECT *prc, BOOL bOnlyCalc) +BOOL BUTTON_DrawIml(HDC hDC, BUTTON_IMAGELIST *pimlData, RECT *prc, BOOL bOnlyCalc, int index) { SIZE ImageSize; - int left, top; + int left, top, count; if (!pimlData->himl) return FALSE; @@ -436,8 +436,17 @@ BOOL BUTTON_DrawIml(HDC hDC, BUTTON_IMAGELIST *pimlData, RECT *prc, BOOL bOnlyCa top = prc->top + (prc->bottom - prc->top - ImageSize.cy) / 2; } - if (!bOnlyCalc) - ImageList_Draw(pimlData->himl, 0, hDC, left, top, 0); + if (bOnlyCalc) + return TRUE; + + count = ImageList_GetImageCount(pimlData->himl); + + if (count == 1) + index = 0; + else if (index >= count) + return TRUE; + + ImageList_Draw(pimlData->himl, index, hDC, left, top, 0); return TRUE; } @@ -1220,7 +1229,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) #endif #ifndef _USER32_ - BOOL bHasIml = BUTTON_DrawIml(hdc, &pdata->imlData, &r, TRUE); + BOOL bHasIml = BUTTON_DrawIml(hdc, &pdata->imlData, &r, TRUE, 0); #endif /* Calculate label rectangle according to label type */ @@ -1378,7 +1387,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, RECT *rc) #ifndef _USER32_ PBUTTON_DATA pdata = _GetButtonData(hwnd); - BUTTON_DrawIml(hdc, &pdata->imlData, rc, FALSE); + BUTTON_DrawIml(hdc, &pdata->imlData, rc, FALSE, 0); #endif if ((style & BS_PUSHLIKE) && (state & BST_INDETERMINATE)) diff --git a/dll/win32/comctl32/theme_button.c b/dll/win32/comctl32/theme_button.c index 9b851837996..755f4a7f060 100644 --- a/dll/win32/comctl32/theme_button.c +++ b/dll/win32/comctl32/theme_button.c @@ -28,9 +28,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(theme_button); typedef enum { STATE_NORMAL, - STATE_DISABLED, STATE_HOT, STATE_PRESSED, + STATE_DISABLED, STATE_DEFAULTED } ButtonState; @@ -56,7 +56,7 @@ static inline LONG_PTR get_button_image(HWND hwnd) return _GetButtonData(hwnd)->image; } -BOOL BUTTON_DrawIml(HDC hdc, BUTTON_IMAGELIST *pimlData, RECT *prc, BOOL bOnlyCalc); +BOOL BUTTON_DrawIml(HDC hdc, BUTTON_IMAGELIST *pimlData, RECT *prc, BOOL bOnlyCalc, int index); DWORD BUTTON_SendCustomDraw(HWND hwnd, HDC hDC, DWORD dwDrawStage, RECT* prc); #endif @@ -113,7 +113,7 @@ static inline WCHAR *get_button_text(HWND hwnd) static void PB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused, LPARAM prfFlag) { - static const int states[] = { PBS_NORMAL, PBS_DISABLED, PBS_HOT, PBS_PRESSED, PBS_DEFAULTED }; + static const int states[] = { PBS_NORMAL, PBS_HOT, PBS_PRESSED, PBS_DISABLED, PBS_DEFAULTED }; RECT bgRect, textRect; HFONT font = get_button_font(hwnd); @@ -150,7 +150,7 @@ static void PB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UIN if (cdrf == CDRF_SKIPDEFAULT) goto cleanup; - BUTTON_DrawIml(hDC, &pdata->imlData, &textRect, FALSE); + BUTTON_DrawIml(hDC, &pdata->imlData, &textRect, FALSE, drawState); text = get_button_text(hwnd); if (text) @@ -185,15 +185,15 @@ static void CB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UIN { static const int cb_states[3][5] = { - { CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDDISABLED, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDNORMAL }, - { CBS_CHECKEDNORMAL, CBS_CHECKEDDISABLED, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDNORMAL }, - { CBS_MIXEDNORMAL, CBS_MIXEDDISABLED, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDNORMAL } + { CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDDISABLED, CBS_UNCHECKEDNORMAL }, + { CBS_CHECKEDNORMAL, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDDISABLED, CBS_CHECKEDNORMAL }, + { CBS_MIXEDNORMAL, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDDISABLED, CBS_MIXEDNORMAL } }; static const int rb_states[2][5] = { - { RBS_UNCHECKEDNORMAL, RBS_UNCHECKEDDISABLED, RBS_UNCHECKEDHOT, RBS_UNCHECKEDPRESSED, RBS_UNCHECKEDNORMAL }, - { RBS_CHECKEDNORMAL, RBS_CHECKEDDISABLED, RBS_CHECKEDHOT, RBS_CHECKEDPRESSED, RBS_CHECKEDNORMAL } + { RBS_UNCHECKEDNORMAL, RBS_UNCHECKEDHOT, RBS_UNCHECKEDPRESSED, RBS_UNCHECKEDDISABLED, RBS_UNCHECKEDNORMAL }, + { RBS_CHECKEDNORMAL, RBS_CHECKEDHOT, RBS_CHECKEDPRESSED, RBS_CHECKEDDISABLED, RBS_CHECKEDNORMAL } }; SIZE sz; @@ -307,7 +307,7 @@ static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UIN static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused) #endif { - static const int states[] = { GBS_NORMAL, GBS_DISABLED, GBS_NORMAL, GBS_NORMAL, GBS_NORMAL }; + static const int states[] = { GBS_NORMAL, GBS_NORMAL, GBS_NORMAL, GBS_DISABLED, GBS_NORMAL }; RECT bgRect, textRect, contentRect; int state = states[ drawState ]; @@ -415,30 +415,20 @@ static const pfThemedPaint btnThemedPaintFunc[BUTTON_TYPE + 1] = NULL, /* Not defined */ }; -#ifdef __REACTOS__ /* r73873 */ BOOL BUTTON_PaintWithTheme(HTHEME theme, HWND hwnd, HDC hParamDC, LPARAM prfFlag) -#else -static BOOL BUTTON_Paint(HTHEME theme, HWND hwnd, HDC hParamDC) -#endif { -#ifdef __REACTOS__ /* r73873, r73897 and r74120 */ DWORD dwStyle; DWORD dwStyleEx; DWORD type; UINT dtFlags; int state; -#else - PAINTSTRUCT ps; - HDC hDC; - DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); - DWORD dwStyleEx = GetWindowLongW(hwnd, GWL_EXSTYLE); - UINT dtFlags = get_drawtext_flags(dwStyle, dwStyleEx); - int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); -#endif ButtonState drawState; -#ifdef __REACTOS__ /* r73873, r73897, r73907 and r74120 */ pfThemedPaint paint; + /* Don't draw with themes on a button with BS_ICON or BS_BITMAP */ + if (get_button_image(hwnd) != 0) + return FALSE; + dwStyle = GetWindowLongW(hwnd, GWL_STYLE); type = dwStyle & BUTTON_TYPE; @@ -449,144 +439,23 @@ static BOOL BUTTON_Paint(HTHEME theme, HWND hwnd, HDC hParamDC) if (!paint) return FALSE; - if (get_button_image(hwnd) != 0) - return FALSE; - dwStyleEx = GetWindowLongW(hwnd, GWL_EXSTYLE); dtFlags = get_drawtext_flags(dwStyle, dwStyleEx); state = get_button_state(hwnd); -#else - pfThemedPaint paint = btnThemedPaintFunc[ dwStyle & BUTTON_TYPE ]; -#endif - if(IsWindowEnabled(hwnd)) - { - if(state & BST_PUSHED) - drawState = STATE_PRESSED; - else if ((dwStyle & BS_PUSHLIKE) && (state & (BST_CHECKED|BST_INDETERMINATE))) - drawState = STATE_PRESSED; - else if(state & BST_HOT) - drawState = STATE_HOT; - else if(state & BST_FOCUS) - drawState = STATE_DEFAULTED; - else - drawState = STATE_NORMAL; - } - else + if(dwStyle & WS_DISABLED) drawState = STATE_DISABLED; - -#ifndef __REACTOS__ /* r73873 */ - hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps); - if (paint) paint(theme, hwnd, hDC, drawState, dtFlags, state & BST_FOCUS); - if (!hParamDC) EndPaint(hwnd, &ps); -#endif - -#ifdef __REACTOS__ /* r74074 & r74120 */ - if (drawState == STATE_NORMAL && type == BS_DEFPUSHBUTTON) - { + else if(state & BST_PUSHED) + drawState = STATE_PRESSED; + else if ((dwStyle & BS_PUSHLIKE) && (state & (BST_CHECKED|BST_INDETERMINATE))) + drawState = STATE_PRESSED; + else if(state & BST_HOT) + drawState = STATE_HOT; + else if((state & BST_FOCUS) || (dwStyle & BS_DEFPUSHBUTTON)) drawState = STATE_DEFAULTED; - } -#endif + else + drawState = STATE_NORMAL; paint(theme, hwnd, hParamDC, drawState, dtFlags, state & BST_FOCUS, prfFlag); return TRUE; } - -#ifndef __REACTOS__ /* r73873 */ -/********************************************************************** - * The button control subclass window proc. - */ -LRESULT CALLBACK THEMING_ButtonSubclassProc(HWND hwnd, UINT msg, - WPARAM wParam, LPARAM lParam, - ULONG_PTR dwRefData) -{ - const WCHAR* themeClass = WC_BUTTONW; - HTHEME theme; - LRESULT result; - - switch (msg) - { - case WM_CREATE: - result = THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - OpenThemeData(hwnd, themeClass); - return result; - - case WM_DESTROY: - theme = GetWindowTheme(hwnd); - CloseThemeData (theme); - return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - - case WM_THEMECHANGED: - theme = GetWindowTheme(hwnd); - CloseThemeData (theme); - OpenThemeData(hwnd, themeClass); - break; - - case WM_SYSCOLORCHANGE: - theme = GetWindowTheme(hwnd); - if (!theme) return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - /* Do nothing. When themed, a WM_THEMECHANGED will be received, too, - * which will do the repaint. */ - break; - - case WM_PAINT: - theme = GetWindowTheme(hwnd); - if (theme && BUTTON_Paint(theme, hwnd, (HDC)wParam)) - return 0; - else - return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - - case WM_ENABLE: - theme = GetWindowTheme(hwnd); - if (theme) { - RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); - return 0; - } else - return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - - case WM_MOUSEMOVE: - { - TRACKMOUSEEVENT mouse_event; - mouse_event.cbSize = sizeof(TRACKMOUSEEVENT); - mouse_event.dwFlags = TME_QUERY; - if(!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags&(TME_HOVER|TME_LEAVE))) - { - mouse_event.dwFlags = TME_HOVER|TME_LEAVE; - mouse_event.hwndTrack = hwnd; - mouse_event.dwHoverTime = 1; - TrackMouseEvent(&mouse_event); - } - break; - } - - case WM_MOUSEHOVER: - { - int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); - SetWindowLongW(hwnd, 0, state|BST_HOT); - InvalidateRect(hwnd, NULL, FALSE); - break; - } - - case WM_MOUSELEAVE: - { - int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); - SetWindowLongW(hwnd, 0, state&(~BST_HOT)); - InvalidateRect(hwnd, NULL, FALSE); - break; - } - - case BM_SETCHECK: - case BM_SETSTATE: - theme = GetWindowTheme(hwnd); - if (theme) { - InvalidateRect(hwnd, NULL, FALSE); - } - return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - - default: - /* Call old proc */ - return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); - } - return 0; -} -#endif /* !__REACTOS__ */