Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tkinter, Windows: How to view window in windows task bar which has no title bar?

I created a window:

root = Tk()

and removed the titlebar:

root.overrideredirect(True)

Now the window is not on the task bar in windows. How can i show it in the task bar? (I only want to bring my window to the front if other windows are on top of mine)

like image 229
Faminator Avatar asked Jun 11 '15 16:06

Faminator


People also ask

How to remove the title bar of a window in Tkinter?

To create a tkinter window without title bar, we can use overrideredirect(boolean) property which disables the navigation panel from the top of the tkinter window.

Is task bar and title bar same?

The title bar as the name suggests is the top bar of every Window you see. It contains the name of the application and it has 3 buttons that allow you to close, maximise and minimise the window. The task bar is where all the open tasks sit on, where the Start button is and it's at the bottom of your screen.

How to remove the window frame in Tkinter?

Build A Paint Program With TKinter and Python If we want to clear the frame content or delete all the widgets inside the frame, we can use the destroy() method. This method can be invoked by targeting the children of the frame using winfo_children().


2 Answers

Tk does not provide a way to have a toplevel window that has overrideredirect set to appear on the taskbar. To do this the window needs to have the WS_EX_APPWINDOW extended style applied and this type of Tk window has WS_EX_TOOLWINDOW set instead. We can use the python ctypes extension to reset this but we need to note that Tk toplevel windows on Windows are not directly managed by the window manager. We have therefore to apply this new style to the parent of the windows returned by the winfo_id method.

The following example shows such a window.

import tkinter as tk
import tkinter.ttk as ttk
from ctypes import windll

GWL_EXSTYLE = -20
WS_EX_APPWINDOW = 0x00040000
WS_EX_TOOLWINDOW = 0x00000080

def set_appwindow(root):
    hwnd = windll.user32.GetParent(root.winfo_id())
    style = windll.user32.GetWindowLongPtrW(hwnd, GWL_EXSTYLE)
    style = style & ~WS_EX_TOOLWINDOW
    style = style | WS_EX_APPWINDOW
    res = windll.user32.SetWindowLongPtrW(hwnd, GWL_EXSTYLE, style)
    # re-assert the new window style
    root.withdraw()
    root.after(10, root.deiconify)

def main():
    root = tk.Tk()
    root.wm_title("AppWindow Test")
    button = ttk.Button(root, text='Exit', command=root.destroy)
    button.place(x=10, y=10)
    root.overrideredirect(True)
    root.after(10, set_appwindow, root)
    root.mainloop()

if __name__ == '__main__':
    main()
like image 81
patthoyts Avatar answered Sep 21 '22 15:09

patthoyts


A simplification of @patthoyts's answer:

# Partially taken from: https://stackoverflow.com/a/2400467/11106801
from ctypes.wintypes import BOOL, HWND, LONG
import tkinter as tk
import ctypes

# Defining functions
GetWindowLongPtrW = ctypes.windll.user32.GetWindowLongPtrW
SetWindowLongPtrW = ctypes.windll.user32.SetWindowLongPtrW

def get_handle(root) -> int:
    root.update_idletasks()
    # This gets the window's parent same as `ctypes.windll.user32.GetParent`
    return GetWindowLongPtrW(root.winfo_id(), GWLP_HWNDPARENT)

# Constants
GWL_STYLE = -16
GWLP_HWNDPARENT = -8
WS_CAPTION = 0x00C00000
WS_THICKFRAME = 0x00040000


if __name__ == "__main__":
    root = tk.Tk()

    hwnd:int = get_handle(root)
    style:int = GetWindowLongPtrW(hwnd, GWL_STYLE)
    style &= ~(WS_CAPTION | WS_THICKFRAME)
    SetWindowLongPtrW(hwnd, GWL_STYLE, style)

The style &= ~(WS_CAPTION | WS_THICKFRAME) just removes the title bar of the window. For more info read Microsoft's documentation.


Not really needed but to make it safer use this to define the functions:

# Defining types
INT = ctypes.c_int
LONG_PTR = ctypes.c_long

def _errcheck_not_zero(value, func, args):
    if value == 0:
        raise ctypes.WinError()
    return args

# Defining functions
GetWindowLongPtrW = ctypes.windll.user32.GetWindowLongPtrW
GetWindowLongPtrW.argtypes = (HWND, INT)
GetWindowLongPtrW.restype = LONG_PTR
GetWindowLongPtrW.errcheck = _errcheck_not_zero

SetWindowLongPtrW = ctypes.windll.user32.SetWindowLongPtrW
SetWindowLongPtrW.argtypes = (HWND, INT, LONG_PTR)
SetWindowLongPtrW.restype = LONG_PTR
SetWindowLongPtrW.errcheck = _errcheck_not_zero

I know the question specifically says it's about Windows but for Linux, this should work.

like image 24
TheLizzard Avatar answered Sep 17 '22 15:09

TheLizzard