Attempt to make buttons themed
res
resqu at gmx.ch
Mon Mar 21 17:59:37 CST 2005
To see how easy (or not) it would be to make the controls use themes, I
tried to get themed buttons; the result is the attached patch (to try it
out, you need an .msstyles file and appropriate registry setup).
ChangeLog:
Add initial theming support for push buttons.
-------------- next part --------------
Index: dlls/user/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/user/Makefile.in,v
retrieving revision 1.88
diff -u -r1.88 Makefile.in
--- dlls/user/Makefile.in 10 Mar 2005 15:47:53 -0000 1.88
+++ dlls/user/Makefile.in 21 Mar 2005 23:54:19 -0000
@@ -4,7 +4,7 @@
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = user32.dll
-IMPORTS = gdi32 advapi32 kernel32 ntdll
+IMPORTS = gdi32 advapi32 kernel32 uxtheme ntdll
EXTRALIBS = $(LIBUNICODE)
SPEC_SRCS16 = \
Index: dlls/user/button.c
===================================================================
RCS file: /home/wine/wine/dlls/user/button.c,v
retrieving revision 1.6
diff -u -r1.6 button.c
--- dlls/user/button.c 23 Dec 2004 17:21:05 -0000 1.6
+++ dlls/user/button.c 21 Mar 2005 23:54:20 -0000
@@ -71,6 +71,9 @@
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
+#include "winuser.h" /* Indirectly required by uxtheme.h */
+#include "uxtheme.h"
+#include "tmschema.h"
#include "wine/winuser16.h"
#include "controls.h"
#include "user_private.h"
@@ -79,7 +82,8 @@
#define STATE_GWL_OFFSET 0
#define HFONT_GWL_OFFSET (sizeof(LONG))
#define HIMAGE_GWL_OFFSET (HFONT_GWL_OFFSET+sizeof(HFONT))
-#define NB_EXTRA_BYTES (HIMAGE_GWL_OFFSET+sizeof(HANDLE))
+#define HTHEME_GWL_OFFSET (HIMAGE_GWL_OFFSET+sizeof(HANDLE))
+#define NB_EXTRA_BYTES (HTHEME_GWL_OFFSET+sizeof(HTHEME))
/* Button state values */
#define BUTTON_UNCHECKED 0x00
@@ -95,6 +99,7 @@
static UINT BUTTON_CalcLabelRect( HWND hwnd, HDC hdc, RECT *rc );
static void PB_Paint( HWND hwnd, HDC hDC, UINT action );
+static void PB_PaintThemed( HWND hwnd, HDC hDC, UINT action );
static void CB_Paint( HWND hwnd, HDC hDC, UINT action );
static void GB_Paint( HWND hwnd, HDC hDC, UINT action );
static void UB_Paint( HWND hwnd, HDC hDC, UINT action );
@@ -123,7 +128,7 @@
typedef void (*pfPaint)( HWND hwnd, HDC hdc, UINT action );
-static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
+static const pfPaint btnUnthemedPaintFunc[MAX_BTN_TYPE] =
{
PB_Paint, /* BS_PUSHBUTTON */
PB_Paint, /* BS_DEFPUSHBUTTON */
@@ -139,6 +144,22 @@
OB_Paint /* BS_OWNERDRAW */
};
+static const pfPaint btnThemedPaintFunc[MAX_BTN_TYPE] =
+{
+ PB_PaintThemed, /* BS_PUSHBUTTON */
+ PB_PaintThemed, /* BS_DEFPUSHBUTTON */
+ CB_Paint, /* BS_CHECKBOX */
+ CB_Paint, /* BS_AUTOCHECKBOX */
+ CB_Paint, /* BS_RADIOBUTTON */
+ CB_Paint, /* BS_3STATE */
+ CB_Paint, /* BS_AUTO3STATE */
+ GB_Paint, /* BS_GROUPBOX */
+ UB_Paint, /* BS_USERBUTTON */
+ CB_Paint, /* BS_AUTORADIOBUTTON */
+ NULL, /* Not defined */
+ OB_Paint /* BS_OWNERDRAW */
+};
+
static HBITMAP hbitmapCheckBoxes = 0;
static WORD checkBoxWidth = 0, checkBoxHeight = 0;
@@ -183,9 +204,28 @@
return (window_style & 0x0f);
}
+inline static HTHEME get_button_theme( HWND hwnd )
+{
+ return (HTHEME)GetWindowLongPtrW( hwnd, HTHEME_GWL_OFFSET );
+}
+
+inline static void set_button_theme( HWND hwnd, HTHEME theme )
+{
+ SetWindowLongPtrW( hwnd, HTHEME_GWL_OFFSET, (ULONG_PTR)theme );
+}
+
+/* Get list of painting funcs, depending on whether theming is available
+ or not. */
+inline static const pfPaint* get_paint_funcs ( HWND hwnd )
+{
+ HTHEME theme = get_button_theme( hwnd );
+ return ( theme != NULL ) ? btnThemedPaintFunc : btnUnthemedPaintFunc;
+}
+
/* paint a button of any type */
inline static void paint_button( HWND hwnd, LONG style, UINT action )
{
+ const pfPaint* btnPaintFunc = get_paint_funcs( hwnd );
if (btnPaintFunc[style] && IsWindowVisible(hwnd))
{
HDC hdc = GetDC( hwnd );
@@ -215,6 +255,9 @@
UINT btn_type = get_button_type( style );
LONG state;
HANDLE oldHbitmap;
+ static const WCHAR themeClass[] = { 'B','u','t','t','o','n',0 };
+ HTHEME theme;
+ const pfPaint* btnPaintFunc = get_paint_funcs( hWnd );
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
@@ -249,8 +292,24 @@
if (btn_type >= MAX_BTN_TYPE)
return -1; /* abort */
set_button_state( hWnd, BUTTON_UNCHECKED );
+ theme = OpenThemeData( hWnd, themeClass );
+ set_button_theme( hWnd, theme );
return 0;
+
+ case WM_DESTROY:
+ theme = get_button_theme( hWnd );
+ if ( theme != NULL )
+ CloseThemeData ( theme );
+ break;
+ case WM_THEMECHANGED:
+ theme = get_button_theme( hWnd );
+ if ( theme != NULL )
+ CloseThemeData ( theme );
+ theme = OpenThemeData( hWnd, themeClass );
+ set_button_theme( hWnd, theme );
+ break;
+
case WM_ERASEBKGND:
if (btn_type == BS_OWNERDRAW)
{
@@ -842,6 +901,39 @@
SetBkMode(hDC, oldBkMode);
}
+static void PB_PaintThemed( HWND hwnd, HDC hDC, UINT action )
+{
+ LONG state = get_button_state( hwnd );
+ LONG style = GetWindowLongW( hwnd, GWL_STYLE );
+ BOOL pushedState = (state & BUTTON_HIGHLIGHTED);
+ HTHEME theme = get_button_theme( hwnd );
+ int partID = BP_PUSHBUTTON;
+ int stateID;
+ RECT rc;
+ WCHAR *text = NULL;
+ BOOL disabledState = !IsWindowEnabled( hwnd );
+
+ GetClientRect( hwnd, &rc );
+ if (disabledState)
+ stateID = PBS_DISABLED;
+ else if (pushedState)
+ stateID = PBS_PRESSED;
+ else if (( get_button_type(style) == BS_DEFPUSHBUTTON )
+ || ( state & BUTTON_HASFOCUS ))
+ stateID = PBS_DEFAULTED;
+ else
+ stateID = PBS_NORMAL;
+
+ DrawThemeBackground( theme, hDC, partID, stateID, &rc, NULL);
+
+ if (( text = get_button_text( hwnd ) ) != NULL )
+ {
+ if ((style & (BS_ICON|BS_BITMAP)) == BS_TEXT)
+ DrawThemeText( theme, hDC, partID, stateID, text, -1,
+ BUTTON_BStoDT(style), 0, &rc );
+ }
+}
+
/**********************************************************************
* Check Box & Radio Button Functions
*/
More information about the wine-patches
mailing list