Attempt to make buttons themed (resend)

res resqu at gmx.ch
Tue Mar 22 07:07:56 CST 2005


[Resend; content same as last time, but the patch is now inline.]

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.

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