How to place menu bar on frame's title bar and keep "minimize, maximize and close" buttons & and dragging?

Hi,

Yet another titlebar.
It may be necessary to adjust the position and size depending on the OS.

import wx

class TitleBar(wx.Frame):
    def __init__(self, parent, menubar, **kwargs):
        super().__init__(parent,
            style=wx.FRAME_FLOAT_ON_PARENT|wx.NO_BORDER,
            size=(80,18), **kwargs)
        
        self.SetMenuBar(menubar)
        self.max_width = self.Size[0]
        self.min_pos = 32
        
        self.Parent.Bind(wx.EVT_MOVE, self.OnResize)
        self.Parent.Bind(wx.EVT_SIZE, self.OnResize)
    
    def OnResize(self, evt):
        x = self.Size[0]
        w = self.Parent.Size[0]
        p = w-x-150
        if p < self.min_pos:
            self.SetSize(self.max_width + p - self.min_pos, -1)
            p = self.min_pos
        self.Move(self.Parent.ScreenPosition + (p, 13))
        evt.Skip()

class TestFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        menubar = wx.MenuBar()
        menu = wx.Menu()
        exit = menu.Append(wx.ID_EXIT, 'Exit\tCtrl-w')
        self.Bind(wx.EVT_MENU, lambda v: self.Close(), exit)
        menubar.Append(menu, 'File')
        
        self.tb = TitleBar(self, menubar)
        self.tb.Show()
        
        self.Bind(wx.EVT_CHAR_HOOK, self.OnHookChar)
    
    def OnHookChar(self, evt):
        if evt.EventObject is self:
            self.tb.SetFocus()
            evt.EventObject = self.tb
            wx.PostEvent(self.tb.MenuBar, evt) # transfer the event to tb menu
        else:
            evt.Skip()

if __name__ == '__main__':
    app = wx.App()
    frm = TestFrame(None, title="A poor man's title-bar")
    frm.Show()
    app.MainLoop()
1 Like