tkinter最大化 的一些小BUG(五)

上一篇有点小BUG,就是最大化时把状态栏给遮挡了,所以在最大化时调整一下窗体大小。

鼠标在按钮上移动时窗体也跟着移动,要过滤一下事件。

from tkinter import Tk, Frame, Label, Button, Canvas
from ctypes import Structure, c_long, windll, byref
from PIL import Image, ImageTk


class RECT(Structure):
    _fields_ = [("left", c_long), ("top", c_long), ("right", c_long), ("bottom", c_long)]


SPI_GETWORKAREA = 48
GWL_STYLE = -16  # 用于获取窗口样式
WS_CAPTION = 12582912  # 窗口标题栏样式
WS_THICKFRAME = 262144  # 窗口可调整边框样式

WM_SYSCOMMAND = 274
SC_SIZE = 61440
SC_MOVE = 61456
HTCAPTION = 2
WMSZ_LEFT = 1
WMSZ_RIGHT = 2
WMSZ_TOP = 3
WMSZ_TOPLEFT = 4
WMSZ_TOPRIGHT = 5
WMSZ_BOTTOM = 6
WMSZ_BOTTOMLEFT = 7
WMSZ_BOTTOMRIGHT = 8


class WindowTk(Tk):
    def __init__(self, icon='logo.ico', name='TK窗体', width=1000, height=600, min_w=600, min_h=400):
        super().__init__()
        self.margin = 10
        self.bg_color = 'white'
        self.head_height = 30
        '''居中显示'''
        work_rect = RECT()
        windll.user32.SystemParametersInfoW(SPI_GETWORKAREA, 0, byref(work_rect), 0)
        self.ww = work_rect.right - work_rect.left
        self.wh = work_rect.bottom - work_rect.top
        size = '%dx%d+%d+%d' % (width, height, (self.ww - width) / 2, (self.wh - height) / 2)
        self.geometry(size)
        self.iconbitmap(icon)
        self.title(name)
        self.minsize(min_w, min_h)
        self.configure(bg=self.bg_color)
        '''无边框'''
        self.update_idletasks()  # 刷新窗口状态
        self.hwnd = windll.user32.GetParent(self.winfo_id())  # 获取窗口句柄
        style = windll.user32.GetWindowLongPtrW(self.hwnd, GWL_STYLE)
        style &= ~(WS_CAPTION | WS_THICKFRAME)
        windll.user32.SetWindowLongPtrW(self.hwnd, GWL_STYLE, style)
        '''标题栏'''
        title_bar = Frame(self, name='title_bar', bg=self.bg_color, height=self.head_height)
        title_bar.pack(fill='x', padx=self.margin, pady=5)
        icon_canvas = Canvas(title_bar, name='icon_canvas_bar', highlightthickness=0, bg=self.bg_color,
                             width=self.head_height, height=self.head_height)
        icon_canvas.pack(side='left', fill='y')
        title_label = Label(title_bar, bg=self.bg_color, name='name_bar', text=name, font=("Microsoft YaHei", 10))
        title_label.pack(side='left', fill='y')
        button = Button(title_bar, text="关闭", command=self.destroy)
        button.pack(side='right')
        button = Button(title_bar, text="最大化", command=self.max_win)
        button.pack(side='right')
        button = Button(title_bar, text="最小化", command=self.min_win)
        button.pack(side='right')
        ico_h = 24
        ico = Image.open(icon).resize((ico_h, ico_h))
        ico = ImageTk.PhotoImage(ico)
        icon_canvas.create_image((self.head_height - ico_h) / 2, (self.head_height - ico_h) / 2, anchor="nw", image=ico)
        icon_canvas.image = ico

        '''窗体事件'''
        self.action = None
        self.direction = None
        self.bind("<Motion>", self.move)
        self.bind("<B1-Motion>", self.on_motion)

    def move(self, e):
        if str(e.widget).endswith('.') or str(e.widget).endswith('bar'):
            x = e.x_root - self.winfo_x()
            y = e.y_root - self.winfo_y()
            if x <= self.margin and y <= self.margin:
                self.set_cursor('@C:/Windows/Cursors/aero_nwse.cur', SC_SIZE, WMSZ_TOPLEFT)
            elif self.winfo_width() - 1 - self.margin > x > self.margin > y:
                self.set_cursor('sb_v_double_arrow', SC_SIZE, WMSZ_TOP)
            elif self.winfo_width() - 1 - self.margin <= x and y <= self.margin:
                self.set_cursor('@C:/Windows/Cursors/aero_nesw.cur', SC_SIZE, WMSZ_TOPRIGHT)
            elif self.winfo_width() - 1 - self.margin < x and self.margin < y < self.winfo_height() - 1 - self.margin:
                self.set_cursor('sb_h_double_arrow', SC_SIZE, WMSZ_RIGHT)
            elif self.winfo_width() - 1 - self.margin <= x and self.winfo_height() - 1 - self.margin <= y:
                self.set_cursor('@C:/Windows/Cursors/aero_nwse.cur', SC_SIZE, WMSZ_BOTTOMRIGHT)
            elif self.margin < x < self.winfo_width() - 1 - self.margin and self.winfo_height() - 1 - self.margin < y:
                self.set_cursor('sb_v_double_arrow', SC_SIZE, WMSZ_BOTTOM)
            elif x <= self.margin and self.winfo_height() - 1 - self.margin <= y:
                self.set_cursor('@C:/Windows/Cursors/aero_nesw.cur', SC_SIZE, WMSZ_BOTTOMLEFT)
            elif x < self.margin < y < self.winfo_height() - 1 - self.margin:
                self.set_cursor('sb_h_double_arrow', SC_SIZE, WMSZ_LEFT)
            else:
                self.set_cursor('arrow', SC_MOVE, HTCAPTION)
        else:
            self.configure(cursor='arrow')

    def set_cursor(self, cursor, action, direction):
        self.configure(cursor=cursor)
        self.action = action
        self.direction = direction

    def on_motion(self, e):
        if str(e.widget).endswith('.') or str(e.widget).endswith('bar'):
            windll.user32.ReleaseCapture()
            windll.user32.SendMessageW(self.hwnd, WM_SYSCOMMAND, self.action | self.direction, 0)

    def min_win(self):
        self.state("icon")

    def max_win(self):
        if self.wm_state() == 'zoomed':
            self.state('normal')
            return
        self.state('zoomed')
        windll.user32.MoveWindow(self.hwnd, 0, 0, self.ww + 1, self.wh + 1, True)


if __name__ == '__main__':
    root = WindowTk()
    root.mainloop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值