高水平的Tkinter定制 [英] Tkinter customization on high level

查看:20
本文介绍了高水平的Tkinter定制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想完全定制我的应用程序,所以我创建了一个标题栏,并想出了一种拖动它的方法,但现在我的问题是它缺乏一些功能,比如调整大小和各种动画,我在想,是否有可能通过一些库来摆脱标题栏?或者可以恢复部分功能,使我不必在每次想要隐藏窗口时使用OverridereDirect?

第一个选项更好,但我确实使用了ctypes.windll将窗口放回任务栏,但它似乎也不是最实用的解决方案。

到目前为止,代码如下所示:

import tkinter as tk
from ctypes import windll


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


class Application(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.overrideredirect(True)
        self.after(10, self.setup_window)

        self.geometry('1000x500+500+250')

        self.app_hidden = False
        self.bind('<Expose>', self.show_app)


    # for full customization im using different widgets as buttons
    # lets assume its on the custom title bar

        text = tk.Label(self, width=10, height=2,
                    bg='blue', text='close', foreground='white')
        text.pack()
        text.bind('<ButtonPress-1>', self.hide_app)

    # taken from another post
    def setup_window(self, t: int = 10):
        hwnd = windll.user32.GetParent(self.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)
        self.wm_withdraw()
        self.after(t, self.wm_deiconify)

    def hide_app(self):
        if not self.app_hidden:
            self.overrideredirect(False)
            self.iconify()
            self.app_hidden = True

    def show_app(self, event):
        if self.app_hidden:
            self.overrideredirect(True)
            self.setup_window()
            self.app_hidden = False


if __name__ == '__main__':

    app = Application()
    app.mainloop()

我想要的是能够返回边界,IV‘e尝试通过添加

WS_BORDER = 0x00800000
...
def setup_window(self):
    ...
    style = style | WS_BORDER
    ...

但它不起作用,我也希望不存在已经存在的不必要的绑定,所以主要问题是,如果有一些库能够在高级上与默认的Windows管理器交互,那么是否有可能在没有overrideredirect的情况下overrideredirect

推荐答案

正如我在我的评论中所说,据我所知,这项工作对你有什么好处是没有延期的。您必须自己进行窗口管理。不管怎样,你可能想要这样的东西:

import win32con
import win32api
import win32gui
import tkinter as tk

def override(event):
    hwnd = win32gui.GetParent(root.winfo_id())
    style= win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
    style&= ~win32con.WS_MINIMIZEBOX
    style&= ~win32con.WS_MAXIMIZEBOX
    style&= ~win32con.WS_SYSMENU
    style&= ~win32con.WS_CAPTION
    #style&= ~win32con.WS_SIZEBOX
    valid= win32api.SetWindowLong(hwnd, win32con.GWL_STYLE, style)
    root.bind('<Map>', None)
    

root = tk.Tk()
root.bind('<Map>', override)
root.mainloop()

如果使用这些选项,您可以获得各种窗口样式,如下所示。

WS_MINIMIZEBOX:

WS_MAXIMIZEBOX:

WS_MINIMIZEBOX&;WS_MAXIMIZEBOX:

WS_SYSMENU:

WS_CAPTION:

WS_Caption&;SIZEBOX:

CTYPE解决方案

import tkinter as tk
from ctypes import windll, wintypes

GWL_STYLE = -16
WS_SYSMENU = 0x00080000

SWP_FRAMECHANGED = 0x0020
SWP_NOACTIVATE = 0x0010
SWP_NOMOVE = 0x0002
SWP_NOSIZE = 0x0001

GetWindowLong = windll.user32.GetWindowLongW
SetWindowLong = windll.user32.SetWindowLongW
SetWindowPos = windll.user32.SetWindowPos

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.hwnd = int(self.wm_frame(), 16)
        tk.Button(self, text="Remove buttons", command=self.remove_buttons).pack()
        tk.Button(self, text="Add buttons", command=self.add_buttons).pack()

    def remove_buttons(self):
        old_style = GetWindowLong(self.hwnd, GWL_STYLE)
        new_style = old_style & ~WS_SYSMENU
        SetWindowLong(self.hwnd, GWL_STYLE, new_style)
        SetWindowPos(self.hwnd, 0, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE)

    def add_buttons(self):
        old_style = GetWindowLong(self.hwnd, GWL_STYLE)
        new_style = old_style | WS_SYSMENU
        res = SetWindowLong(self.hwnd, GWL_STYLE, new_style)
        res = SetWindowPos(self.hwnd, 0, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE)

if __name__ == "__main__":
    app = App()
    app.mainloop()

这篇关于高水平的Tkinter定制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆