Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/comctl32/Makefile.in | 1 - dlls/comctl32/combo.c | 173 +++++++++++++++++------- dlls/comctl32/theme_combo.c | 319 -------------------------------------------- dlls/comctl32/theming.c | 5 - 4 files changed, 126 insertions(+), 372 deletions(-) delete mode 100644 dlls/comctl32/theme_combo.c
diff --git a/dlls/comctl32/Makefile.in b/dlls/comctl32/Makefile.in index 080f78c3fe..4adca3c93e 100644 --- a/dlls/comctl32/Makefile.in +++ b/dlls/comctl32/Makefile.in @@ -35,7 +35,6 @@ C_SRCS = \ syslink.c \ tab.c \ taskdialog.c \ - theme_combo.c \ theme_dialog.c \ theme_listbox.c \ theme_scrollbar.c \ diff --git a/dlls/comctl32/combo.c b/dlls/comctl32/combo.c index b478bfca6c..0acb7318a6 100644 --- a/dlls/comctl32/combo.c +++ b/dlls/comctl32/combo.c @@ -2,6 +2,7 @@ * Combo controls * * Copyright 1997 Alex Korobka + * Copyright (c) 2005 by Frank Richter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,6 +33,8 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "uxtheme.h" +#include "vssym32.h" #include "commctrl.h" #include "wine/unicode.h" #include "wine/debug.h" @@ -87,6 +90,7 @@ static UINT CBitHeight, CBitWidth; #define CBF_NOTIFY 0x0100 #define CBF_NOREDRAW 0x0200 #define CBF_SELCHANGE 0x0400 +#define CBF_HOT 0x0800 #define CBF_NOEDITNOTIFY 0x1000 #define CBF_NOLBSELECT 0x2000 /* do not change current selection */ #define CBF_BEENFOCUSED 0x4000 /* has it ever had focus */ @@ -472,6 +476,7 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG static const WCHAR clbName[] = {'C','o','m','b','o','L','B','o','x',0}; static const WCHAR editName[] = {'E','d','i','t',0};
+ OpenThemeData( hwnd, WC_COMBOBOXW ); if( !CB_GETTYPE(lphc) ) lphc->dwStyle |= CBS_SIMPLE; if( CB_GETTYPE(lphc) != CBS_DROPDOWNLIST ) lphc->wState |= CBF_EDIT;
@@ -684,9 +689,7 @@ static HBRUSH COMBO_PrepareColors( * * Paint CBS_DROPDOWNLIST text field / update edit control contents. */ -static void CBPaintText( - LPHEADCOMBO lphc, - HDC hdc_paint) +static void CBPaintText(HEADCOMBO *lphc, HDC hdc_paint) { RECT rectEdit = lphc->textRect; INT id, size = 0; @@ -828,64 +831,86 @@ static void CBPaintBorder( DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_RECT); }
-/*********************************************************************** - * COMBO_Paint - */ -static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC) +static LRESULT COMBO_ThemedPaint(HTHEME theme, HEADCOMBO *lphc, HDC hdc) { - PAINTSTRUCT ps; - HDC hDC; + int button_state; + RECT frame;
- hDC = (hParamDC) ? hParamDC - : BeginPaint( lphc->self, &ps); + /* paint border */ + if (CB_GETTYPE(lphc) != CBS_SIMPLE) + GetClientRect(lphc->self, &frame); + else + { + frame = lphc->textRect; + InflateRect(&frame, EDIT_CONTROL_PADDING(), EDIT_CONTROL_PADDING()); + InflateRect(&frame, COMBO_XBORDERSIZE(), COMBO_YBORDERSIZE()); + }
- TRACE("hdc=%p\n", hDC); + DrawThemeBackground(theme, hdc, 0, IsWindowEnabled(lphc->self) ? CBXS_NORMAL : CBXS_DISABLED, &frame, NULL);
- if( hDC && !(lphc->wState & CBF_NOREDRAW) ) - { - HBRUSH hPrevBrush, hBkgBrush; + /* Paint button */ + if (!IsRectEmpty(&lphc->buttonRect)) + { + if (!IsWindowEnabled(lphc->self)) + button_state = CBXS_DISABLED; + else if (lphc->wState & CBF_BUTTONDOWN) + button_state = CBXS_PRESSED; + else if (lphc->wState & CBF_HOT) + button_state = CBXS_HOT; + else + button_state = CBXS_NORMAL; + DrawThemeBackground(theme, hdc, CP_DROPDOWNBUTTON, button_state, &lphc->buttonRect, NULL); + }
- /* - * Retrieve the background brush and select it in the - * DC. - */ - hBkgBrush = COMBO_PrepareColors(lphc, hDC); + if ((lphc->dwStyle & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST) + CBPaintText(lphc, hdc); + + return 0; +}
- hPrevBrush = SelectObject( hDC, hBkgBrush ); - if (!(lphc->wState & CBF_EDIT)) - FillRect(hDC, &lphc->textRect, hBkgBrush); +/*********************************************************************** + * COMBO_Paint + */ +static LRESULT COMBO_Paint(HEADCOMBO *lphc, HDC hdc) +{ + HBRUSH hPrevBrush, hBkgBrush;
- /* - * In non 3.1 look, there is a sunken border on the combobox - */ - CBPaintBorder(lphc->self, lphc, hDC); + TRACE("hdc=%p\n", hdc);
- if( !IsRectEmpty(&lphc->buttonRect) ) - { - CBPaintButton(lphc, hDC, lphc->buttonRect); - } + /* + * Retrieve the background brush and select it in the + * DC. + */ + hBkgBrush = COMBO_PrepareColors(lphc, hdc); + hPrevBrush = SelectObject(hdc, hBkgBrush); + if (!(lphc->wState & CBF_EDIT)) + FillRect(hdc, &lphc->textRect, hBkgBrush);
- /* paint the edit control padding area */ - if (CB_GETTYPE(lphc) != CBS_DROPDOWNLIST) - { - RECT rPadEdit = lphc->textRect; + /* + * In non 3.1 look, there is a sunken border on the combobox + */ + CBPaintBorder(lphc->self, lphc, hdc);
- InflateRect(&rPadEdit, EDIT_CONTROL_PADDING(), EDIT_CONTROL_PADDING()); + if (!IsRectEmpty(&lphc->buttonRect)) + CBPaintButton(lphc, hdc, lphc->buttonRect);
- FrameRect( hDC, &rPadEdit, GetSysColorBrush(COLOR_WINDOW) ); - } + /* paint the edit control padding area */ + if (CB_GETTYPE(lphc) != CBS_DROPDOWNLIST) + { + RECT rPadEdit = lphc->textRect;
- if( !(lphc->wState & CBF_EDIT) ) - CBPaintText( lphc, hDC ); + InflateRect(&rPadEdit, EDIT_CONTROL_PADDING(), EDIT_CONTROL_PADDING());
- if( hPrevBrush ) - SelectObject( hDC, hPrevBrush ); - } + FrameRect(hdc, &rPadEdit, GetSysColorBrush(COLOR_WINDOW)); + } + + if (!(lphc->wState & CBF_EDIT)) + CBPaintText( lphc, hdc );
- if( !hParamDC ) - EndPaint(lphc->self, &ps); + if (hPrevBrush) + SelectObject( hdc, hPrevBrush );
- return 0; + return 0; }
/*********************************************************************** @@ -1727,6 +1752,7 @@ static LRESULT COMBO_GetComboBoxInfo(const HEADCOMBO *lphc, COMBOBOXINFO *pcbi) LRESULT CALLBACK COMBO_WindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { HEADCOMBO *lphc = (HEADCOMBO *)GetWindowLongPtrW( hwnd, 0 ); + HTHEME theme;
TRACE("[%p]: msg %#x wp %08lx lp %08lx\n", hwnd, message, wParam, lParam );
@@ -1755,10 +1781,41 @@ LRESULT CALLBACK COMBO_WindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARA return COMBO_Create(hwnd, lphc, hwndParent, style); }
+ case WM_DESTROY: + theme = GetWindowTheme( hwnd ); + CloseThemeData( theme ); + break; + + case WM_THEMECHANGED: + theme = GetWindowTheme( hwnd ); + CloseThemeData( theme ); + OpenThemeData( hwnd, WC_COMBOBOXW ); + break; + case WM_PRINTCLIENT: case WM_PAINT: - return COMBO_Paint(lphc, (HDC)wParam); + { + LRESULT ret = 0; + PAINTSTRUCT ps; + HDC hdc; + + hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps); + + if (hdc && !(lphc->wState & CBF_NOREDRAW)) + { + HTHEME theme = GetWindowTheme(hwnd); + + if (theme) + ret = COMBO_ThemedPaint(theme, lphc, hdc); + else + ret = COMBO_Paint(lphc, hdc); + }
+ if (!wParam) + EndPaint(hwnd, &ps); + + return ret; + } case WM_ERASEBKGND: /* do all painting in WM_PAINT like Windows does */ return 1; @@ -1912,6 +1969,28 @@ LRESULT CALLBACK COMBO_WindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARA return TRUE;
case WM_MOUSEMOVE: + if (!IsRectEmpty(&lphc->buttonRect)) + { + POINT pt; + + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + + if (PtInRect(&lphc->buttonRect, pt)) + { + if (!(lphc->wState & CBF_HOT)) + { + lphc->wState |= CBF_HOT; + RedrawWindow(hwnd, &lphc->buttonRect, 0, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + else if (lphc->wState & CBF_HOT) + { + lphc->wState &= ~CBF_HOT; + RedrawWindow(hwnd, &lphc->buttonRect, 0, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + if ( lphc->wState & CBF_CAPTURE ) COMBO_MouseMove( lphc, wParam, lParam ); return TRUE; diff --git a/dlls/comctl32/theme_combo.c b/dlls/comctl32/theme_combo.c deleted file mode 100644 index 3ee1d92277..0000000000 --- a/dlls/comctl32/theme_combo.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Theming - Combo box control - * - * Copyright (c) 2005 by Frank Richter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - */ - -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "uxtheme.h" -#include "vssym32.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(themingcombo); - -/* Subclass-private state flags */ -#define STATE_NOREDRAW 1 -#define STATE_HOT 2 - -/* some constants for metrics, same as in user32 */ -#define COMBO_XBORDERSIZE 2 -#define COMBO_YBORDERSIZE 2 -#define COMBO_EDITBUTTONSPACE 0 -#define EDIT_CONTROL_PADDING 1 - -/* paint text of combobox, needed for read-only drop downs. */ -static void paint_text (HWND hwnd, HDC hdc, DWORD dwStyle, const COMBOBOXINFO *cbi) -{ - INT id, size = 0; - LPWSTR pText = NULL; - UINT itemState = ODS_COMBOBOXEDIT; - HFONT font = (HFONT)SendMessageW (hwnd, WM_GETFONT, 0, 0); - HFONT hPrevFont = (font) ? SelectObject(hdc, font) : 0; - RECT rectEdit; - BOOL focused = GetFocus () == hwnd; - BOOL dropped = cbi->stateButton == STATE_SYSTEM_PRESSED; - - TRACE("\n"); - - /* follow Windows combobox that sends a bunch of text - * inquiries to its listbox while processing WM_PAINT. */ - - if( (id = SendMessageW (cbi->hwndList, LB_GETCURSEL, 0, 0) ) != LB_ERR ) - { - size = SendMessageW (cbi->hwndList, LB_GETTEXTLEN, id, 0); - if (size == LB_ERR) - FIXME("LB_ERR probably not handled yet\n"); - if( (pText = HeapAlloc( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR))) ) - { - /* size from LB_GETTEXTLEN may be too large, from LB_GETTEXT is accurate */ - size = SendMessageW (cbi->hwndList, LB_GETTEXT, id, (LPARAM)pText); - pText[size] = '\0'; /* just in case */ - } else return; - } - else - if( !(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) ) - return; - - /* - * Give ourselves some space. - */ - rectEdit = cbi->rcItem; - InflateRect( &rectEdit, -1, -1 ); - - if(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) - { - DRAWITEMSTRUCT dis; - HRGN clipRegion; - UINT ctlid = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID ); - - /* setup state for DRAWITEM message. Owner will highlight */ - if ( focused && !dropped ) - itemState |= ODS_SELECTED | ODS_FOCUS; - - /* - * Save the current clip region. - * To retrieve the clip region, we need to create one "dummy" - * clip region. - */ - clipRegion = CreateRectRgnIndirect(&rectEdit); - - if (GetClipRgn(hdc, clipRegion)!=1) - { - DeleteObject(clipRegion); - clipRegion=NULL; - } - - if (!IsWindowEnabled(hwnd)) itemState |= ODS_DISABLED; - - dis.CtlType = ODT_COMBOBOX; - dis.CtlID = ctlid; - dis.hwndItem = hwnd; - dis.itemAction = ODA_DRAWENTIRE; - dis.itemID = id; - dis.itemState = itemState; - dis.hDC = hdc; - dis.rcItem = rectEdit; - dis.itemData = SendMessageW(cbi->hwndList, LB_GETITEMDATA, id, 0); - - /* - * Clip the DC and have the parent draw the item. - */ - IntersectClipRect(hdc, - rectEdit.left, rectEdit.top, - rectEdit.right, rectEdit.bottom); - - SendMessageW(GetParent (hwnd), WM_DRAWITEM, ctlid, (LPARAM)&dis ); - - /* - * Reset the clipping region. - */ - SelectClipRgn(hdc, clipRegion); - } - else - { - static const WCHAR empty_stringW[] = { 0 }; - - if ( focused && !dropped ) { - - /* highlight */ - FillRect( hdc, &rectEdit, GetSysColorBrush(COLOR_HIGHLIGHT) ); - SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) ); - SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) ); - } - - ExtTextOutW( hdc, - rectEdit.left + 1, - rectEdit.top + 1, - ETO_OPAQUE | ETO_CLIPPED, - &rectEdit, - pText ? pText : empty_stringW , size, NULL ); - - if ( focused && !dropped ) - DrawFocusRect( hdc, &rectEdit ); - } - - if( hPrevFont ) - SelectObject(hdc, hPrevFont ); - - HeapFree( GetProcessHeap(), 0, pText ); -} - -/* paint the combobox */ -static LRESULT paint (HTHEME theme, HWND hwnd, HDC hParamDC, ULONG state) -{ - PAINTSTRUCT ps; - HDC hDC; - COMBOBOXINFO cbi; - DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE); - - hDC = (hParamDC) ? hParamDC - : BeginPaint( hwnd, &ps); - - TRACE("hdc=%p\n", hDC); - - if( hDC && !(state & STATE_NOREDRAW) ) - { - RECT frameRect; - int buttonState; - - cbi.cbSize = sizeof (cbi); - SendMessageW (hwnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)&cbi); - - /* paint border */ - if ((dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE) - GetClientRect (hwnd, &frameRect); - else - { - frameRect = cbi.rcItem; - InflateRect(&frameRect, - EDIT_CONTROL_PADDING + COMBO_XBORDERSIZE, - EDIT_CONTROL_PADDING + COMBO_YBORDERSIZE); - } - - DrawThemeBackground (theme, hDC, 0, - IsWindowEnabled (hwnd) ? CBXS_NORMAL : CBXS_DISABLED, &frameRect, NULL); - - /* paint button */ - if (cbi.stateButton != STATE_SYSTEM_INVISIBLE) - { - if (!IsWindowEnabled (hwnd)) - buttonState = CBXS_DISABLED; - else if (cbi.stateButton == STATE_SYSTEM_PRESSED) - buttonState = CBXS_PRESSED; - else if (state & STATE_HOT) - buttonState = CBXS_HOT; - else - buttonState = CBXS_NORMAL; - DrawThemeBackground (theme, hDC, CP_DROPDOWNBUTTON, buttonState, - &cbi.rcButton, NULL); - } - - /* paint text, if we need to */ - if ((dwStyle & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST) - paint_text (hwnd, hDC, dwStyle, &cbi); - } - - if( !hParamDC ) - EndPaint(hwnd, &ps); - - return 0; -} - - -/********************************************************************** - * The combo control subclass window proc. - */ -LRESULT CALLBACK THEMING_ComboSubclassProc (HWND hwnd, UINT msg, - WPARAM wParam, LPARAM lParam, - ULONG_PTR dwRefData) -{ - const WCHAR* themeClass = WC_COMBOBOXW; - 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) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); - return paint (theme, hwnd, (HDC)wParam, dwRefData); - - case WM_SETREDRAW: - /* Since there doesn't seem to be WM_GETREDRAW, do redraw tracking in - * the subclass as well. */ - if( wParam ) - dwRefData &= ~STATE_NOREDRAW; - else - dwRefData |= STATE_NOREDRAW; - THEMING_SetSubclassData (hwnd, dwRefData); - return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); - - case WM_MOUSEMOVE: - { - /* Dropdown button hot-tracking */ - COMBOBOXINFO cbi; - POINT pt; - - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - cbi.cbSize = sizeof (cbi); - SendMessageW (hwnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)&cbi); - - if (cbi.stateButton != STATE_SYSTEM_INVISIBLE) - { - if (PtInRect (&cbi.rcButton, pt)) - { - if (!(dwRefData & STATE_HOT)) - { - dwRefData |= STATE_HOT; - THEMING_SetSubclassData (hwnd, dwRefData); - RedrawWindow (hwnd, &cbi.rcButton, 0, - RDW_INVALIDATE | RDW_UPDATENOW); - } - } - else - { - if (dwRefData & STATE_HOT) - { - dwRefData &= ~STATE_HOT; - THEMING_SetSubclassData (hwnd, dwRefData); - RedrawWindow (hwnd, &cbi.rcButton, 0, - RDW_INVALIDATE | RDW_UPDATENOW); - } - } - } - } - return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); - - default: - /* Call old proc */ - return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); - } - return 0; -} diff --git a/dlls/comctl32/theming.c b/dlls/comctl32/theming.c index 06bdf81d41..0d47489dd5 100644 --- a/dlls/comctl32/theming.c +++ b/dlls/comctl32/theming.c @@ -34,8 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(theming); typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM, ULONG_PTR);
-extern LRESULT CALLBACK THEMING_ComboSubclassProc (HWND, UINT, WPARAM, LPARAM, - ULONG_PTR) DECLSPEC_HIDDEN; extern LRESULT CALLBACK THEMING_DialogSubclassProc (HWND, UINT, WPARAM, LPARAM, ULONG_PTR) DECLSPEC_HIDDEN; extern LRESULT CALLBACK THEMING_ListBoxSubclassProc (HWND, UINT, WPARAM, LPARAM, @@ -53,7 +51,6 @@ static const struct ThemingSubclass } subclasses[] = { /* Note: list must be sorted by class name */ {dialogClass, THEMING_DialogSubclassProc}, - {WC_COMBOBOXW, THEMING_ComboSubclassProc}, {comboLboxClass, THEMING_ListBoxSubclassProc}, {WC_LISTBOXW, THEMING_ListBoxSubclassProc}, {WC_SCROLLBARW, THEMING_ScrollbarSubclassProc} @@ -90,14 +87,12 @@ MAKE_SUBCLASS_PROC(0) MAKE_SUBCLASS_PROC(1) MAKE_SUBCLASS_PROC(2) MAKE_SUBCLASS_PROC(3) -MAKE_SUBCLASS_PROC(4)
static const WNDPROC subclassProcs[NUM_SUBCLASSES] = { subclass_proc0, subclass_proc1, subclass_proc2, subclass_proc3, - subclass_proc4, };
/***********************************************************************