0

How to disable title bar transparency for my own application (to create a solid title bar) in Windows 7 with Python Tkinter?

I'm not talking about changing the theme of Windows 7. I'm asking if I'm using the default windows 7 theme, which show title bar with some level of transparency, allowing to see a fuzzy image of the background. Now I'm creating a Python GUI application with Python Tkinter, for this particular application I don't want such transparency. I want a totally solid title bar. What shall I do in my Python code? I know that there are some applications which are able to do that.

The attached image show two applications. The above one is an application I installed on my computer. It has a solid title bar (I didn't change the theme) which is what I want. The second one is the application I created with Python Tkinter with transparent title bar under the same theme, which behaves similar to most of the applications, but is not what I want .

enter image description here

Vespene Gas
  • 3,210
  • 2
  • 16
  • 27

1 Answers1

1

It's impossible with tkinter alone.

Sure, tkinter provides some options like an icon, a title, a child-toplevel, a tool window, etc, but don't be fooled by these options!
While he has an interface to communicate with window manager, he's mainly a tool for the client area of the window, and window managment/decoration isn't his purpose.

Operating with the Aero stuff is more complicated thing, than a trivial window styling, and it handled by the DWM, which can be controlled via the DWM composition API(1, 2).

For all that interaction we need the ctypes library (comes with python) and a set of the WinAPI functions:

  • DwmIsCompositionEnabled - to check if the Aero is enabled (system-wide).
  • DwmSetWindowAttribute - to specify (enable/disable) the non-client area rendering policy (and therefore revert to the Basic/Aero frame).
  • GetParent - to get a hwnd of the owner window, because we're trying to make changes in the non-client area.

Try to run this piece of code:

import ctypes as ct
import tkinter as tk


class App(tk.Tk):
    is_composition_enabled = ct.windll.dwmapi.DwmIsCompositionEnabled
    set_window_attribute = ct.windll.dwmapi.DwmSetWindowAttribute
    get_parent = ct.windll.user32.GetParent

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.state = True
        self.minsize(width=250, height=100)

        self.frame = tk.Frame(self)
        self.frame.pack(expand=True, fill='both')

        self.status_label = tk.Label(self.frame)
        self.status_label.pack(expand=True, fill='both')
        self.populate_status_label()

        self.toggle_button = tk.Button(self.frame, text='Toggle glass', command=self.toggle_glass)
        self.toggle_button.pack(fill='x')

    def populate_status_label(self):
        status = 'en' if self.state else 'dis'
        self.status_label.configure(text='Glass border %sabled!' % status)

    def toggle_glass(self):
        response = self.handle_glass()

        if response:
            self.state = not self.state
            self.populate_status_label()
        else:
            print('Something bad happened!')

    def handle_glass(self):
        try:
            composition_enabled = ct.c_bool()
            response = not bool(self.is_composition_enabled(ct.byref(composition_enabled)))

            if response and composition_enabled.value:
                hwnd = self.get_parent(self.winfo_id())
                switch_to_disable, switch_to_enable, rendering_policy = 1, 2, 2

                dwma_ncrendering_switch = ct.c_int(switch_to_disable if self.state else switch_to_enable)

                return not bool(self.set_window_attribute(hwnd, rendering_policy, ct.byref(dwma_ncrendering_switch),
                                                          ct.sizeof(dwma_ncrendering_switch)))

        except AttributeError:
            return False

app = App()
app.mainloop()

As a result, you should get something similar to this:

result

However, if your goal is to only disable a border transparency, while maintaining a same aero-like style, there's not much you can do about it.

Community
  • 1
  • 1
CommonSense
  • 4,232
  • 2
  • 14
  • 38
  • You code seems doesn't work in Python 2.7.14. It shows 'Python version 2.7 does not support this syntax. super() should have arguments in Python 2.' The error is at the line "super().__init__(*args, **kwargs)". – Vespene Gas Jan 30 '18 at 02:30
  • @Columbia Rover , change `super().__init__(*args, **kwargs)` to `tk.Tk.__init__(self, *args, **kwargs)` then. – CommonSense Mar 20 '18 at 11:42
  • Awesome answer, code still works on Python 3.11.2. – bers Apr 01 '23 at 19:44