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