Introduction

Martijn wrote:

I was unable to create good native flat buttons on windows. If it is possible , I would love to know how.

This example subclasses some buttons in wx.lib.buttons to create native looking flat buttons on win32.

Eric O added: Try ThemedGenButton (as of wxPython 2.8.4.0)

from wx.lib.buttons import ThemedGenButton

button = ThemedGenButton(self, id=-1, label="foo", style=wx.NO_BORDER)

(either wx.NO_BORDER or wx.BORDER_NONE... both appear to work, creating a native flat button. What I found not to work is wx.BU_EXACTFIT...)

What Objects are Involved

Subclassed from wx.lib.buttons:

New classes:

Process Overview

Emulates a win32 flat button

Default-state:border=0

hover:border=1

down:do not change colour

Special Concerns

Todo:

Code

import wx
from wx.lib.buttons import *
import wx.lib.colourdb
class _WinFlatMixin:
    """
    Emulates a win32 flat button
    Default-state:border=0
    hover:border=1
    down:do not change colour
    """
    def __init__(self):
        self.useFocusInd = False
        self.bezelWidth = 0
        self.Bind(wx.EVT_ENTER_WINDOW ,self.OnMouseEnter)
        self.Bind(wx.EVT_LEAVE_WINDOW ,self.OnMouseLeave)
    def OnMouseEnter(self,event):
        self.bezelWidth = 1
        self.Refresh()
    def OnMouseLeave(self,event):
        self.bezelWidth = 0
        self.Refresh()
    def OnPaint(self, event):
        """
        copy&paste from GenButton with 1 minor change(colour on down)
        """
        (width, height) = self.GetClientSizeTuple()
        x1 = y1 = 0
        x2 = width-1
        y2 = height-1
        dc = wx.BufferedPaintDC(self)
        brush = None
        if True: #was:if self.up
            colBg = self.GetBackgroundColour()
            brush = wx.Brush(colBg, wx.SOLID)
            if self.style & wx.BORDER_NONE:
                myAttr = self.GetDefaultAttributes()
                parAttr = self.GetParent().GetDefaultAttributes()
                myDef = colBg == myAttr.colBg
                parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
                if myDef and parDef:
                    if wx.Platform == "__WXMAC__":
                        brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
                    elif wx.Platform == "__WXMSW__":
                        if self.DoEraseBackground(dc):
                            brush = None
                elif myDef and not parDef:
                    colBg = self.GetParent().GetBackgroundColour()
                    brush = wx.Brush(colBg, wx.SOLID)
        else:
            brush = wx.Brush(self.faceDnClr, wx.SOLID)
        if brush is not None:
            dc.SetBackground(brush)
            dc.Clear()
        self.DrawBezel(dc, x1, y1, x2, y2)
        self.DrawLabel(dc, width, height)
        if self.hasFocus and self.useFocusInd:
            self.DrawFocusIndicator(dc, width, height)
class GenWinFlatButton(_WinFlatMixin,GenButton):
    def __init__(self,*arg,**kwarg):
        GenButton.__init__(self,*arg,**kwarg)
        _WinFlatMixin.__init__(self)
class GenWinFlatBitmapButton(_WinFlatMixin,GenBitmapButton):
    def __init__(self,*arg,**kwarg):
        GenBitmapButton.__init__(self,*arg,**kwarg)
        _WinFlatMixin.__init__(self)
class GenWinFlatBitmapTextButton(_WinFlatMixin,GenBitmapTextButton):
    def __init__(self,*arg,**kwarg):
        GenBitmapTextButton.__init__(self,*arg,**kwarg)
        _WinFlatMixin.__init__(self)
class MyFrame(wx.Panel):
    def __init__(self, parent, ID):
        wx.Panel.__init__(self, parent, ID, wx.DefaultPosition)
        bmp = wx.ArtProvider.GetBitmap(wx.ART_HELP) #need an image..
        self.btn1 = GenWinFlatButton(self, -1, "GenWinFlatButton", pos = (20,20), size=(-1, -1))
        self.btn2 = GenWinFlatBitmapButton(self, -1, bmp,pos = (20,50))
        self.btn3 = GenWinFlatBitmapTextButton(self, -1, bmp,"GenWinFlatBitmapTextButton"
                    ,pos = (20,100),size=(200,40))
if __name__ == '__main__':
    class MyApp(wx.App):
        def OnInit(self):
            wx.lib.colourdb.updateColourDB()
            frame = wx.Frame(None, -1, "InteractiveButton", wx.DefaultPosition, wx.Size(300,300))
            myframe = MyFrame(frame, -1)
            frame.Centre()
            frame.Show(True)
            self.SetTopWindow(frame)
            return True
    app = MyApp(0)
    app.MainLoop()

Comments

Catching of enter/leave was taken,learned from InteractiveButton.

GenWinFlatButton (last edited 2008-03-11 10:50:24 by localhost)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.