如何在Tkinter中制作完全点击的水印窗口?

问题描述 投票:0回答:1

我正在尝试使用 Tkinter 创建透明水印叠加层,在所有显示器上显示系统信息(主机名、用户名、IP 和时间)。水印每秒更新一次,根本不应该干扰用户交互。

我面临的问题: 该窗口捕获鼠标点击,阻止与其下方的应用程序交互。 文本有时会干扰交互,这意味着它并不总是完全透明。

import socket
import psutil
import tkinter as tk
from datetime import datetime
from screeninfo import get_monitors

def get_system_info():
    hostname = socket.gethostname()
    user = psutil.users()[0].name
    ip = socket.gethostbyname(hostname)
    current_time = datetime.now().strftime("%y-%m-%d %H:%M")
    return f"{hostname},{current_time}, {user} "



def display_watermark(text):
    windows = []
    for monitor in get_monitors():
        root = tk.Tk()
        root.overrideredirect(True)
        root.attributes("-topmost", True)
        root.attributes("-alpha", 0.3)
        root.geometry(f"{monitor.width}x{monitor.height}+{monitor.x}+{monitor.y}")
        root.config(bg="black")
        root.wm_attributes("-transparentcolor", "#000000")

        root.protocol("WM_DELETE_WINDOW", lambda: None)
        canvas = tk.Canvas(root, width=monitor.width, height=monitor.height, bg="black", highlightthickness=0)
        canvas.pack(fill="both", expand=True)

        for y in range(-50, monitor.height + 100, 400):
            for x in range(-100, monitor.width + 200, 800):
                canvas.create_text(x, y, text=text, font=("Arial", 28), fill="gray", angle=45)

        windows.append((root, canvas, monitor))

    def update_text():
        new_text = get_system_info()
        for window, canvas, monitor in windows:
            canvas.delete("all")
            for y in range(-50, monitor.height + 100, 400):
                for x in range(-100, monitor.width + 200, 800):
                    canvas.create_text(x, y, text=new_text, font=("Arial", 28), fill="gray", angle=45)
        root.after(1000, update_text)

    update_text()
    for window, _, _ in windows:
        window.mainloop()

system_info_text = get_system_info()
display_watermark(system_info_text)

我尝试通过以下方式解决它

root.attributes("-alpha", 0.3) – 使窗口半透明,但仍然阻止点击。 root.wm_attributes("-transparentcolor", "#000000") – 使背景透明,但文本仍然捕获点击。 root.attributes("-disabled", True) – 禁用窗口,但也阻止更新水印文本。 使用 root.lower() 和 root.attributes("-topmost", False),但水印会隐藏在其他窗口后面。

import socket
import psutil
import tkinter as tk
from datetime import datetime
from screeninfo import get_monitors
import win32gui
import win32con

def setClickthrough(hwnd):
    print("setting window properties")
    try:
        styles = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
        styles = win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
        win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, styles)
        win32gui.SetLayeredWindowAttributes(hwnd, 0, 255, win32con.LWA_ALPHA)
    except Exception as e:
        print(e)

def get_system_info():

    hostname = socket.gethostname()
    user = psutil.users()[0].name
    current_time = datetime.now().strftime("%y-%m-%d %H:%M")
    return f"{hostname}, {current_time}, {user}"


def display_watermark():

    monitors = get_monitors()


    min_x = min(m.x for m in monitors)
    min_y = min(m.y for m in monitors)
    max_width = sum(m.width for m in monitors)
    max_height = max(m.y + m.height for m in monitors) - min_y


    root = tk.Tk()
    root.overrideredirect(True)
    root.attributes("-topmost", True)
    root.attributes("-alpha", 0.3)
    root.geometry(f"{max_width}x{max_height}+{min_x}+{min_y}")
    root.config(bg="black")
    root.wm_attributes("-transparentcolor", "#000000")

    canvas = tk.Canvas(root, width=max_width, height=max_height, bg="black", highlightthickness=0)

    setClickthrough(canvas)
    canvas.pack(fill="both", expand=True)

    def update_text():
        new_text = get_system_info()
        canvas.delete("all")


        for y in range(-50, max_height + 100, 400):
            for x in range(-100, max_width + 200, 800):
                canvas.create_text(x, y, text=new_text, font=("Arial", 28), fill="gray", angle=45)

        root.after(1000, update_text)

    update_text()
    root.mainloop()


display_watermark()

水印应该完全点击通过(无交互阻塞)。 文本也应该是透明的并且不会干扰鼠标点击。 如何确保整个窗口,包括文字,完全可以点击通过?

python tkinter mouseevent transparent watermark
1个回答
0
投票

您可以使用内置的

ctypes.windll
代替
win32con
win32gui
,并将
GetWindowLongW()
SetWindowLongW()
应用在窗口上,而不是画布上。

您也可以简单地创建一个覆盖所有显示器的窗口。

以下是根据您的修改后的示例:

from ctypes import windll
from datetime import datetime
import os
import socket
import tkinter as tk
from screeninfo import get_monitors

# required constants
WS_EX_LAYERED = 0x00080000
WS_EX_TRANSPARENT = 0x00000020
GWL_EXSTYLE = -20

# transparent color
COLOR = '#000000'

def set_click_through(win):
    hwnd = windll.user32.GetParent(win.winfo_id())
    ex_style = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
    ex_style |= WS_EX_TRANSPARENT | WS_EX_LAYERED
    windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, ex_style)

def get_system_info():
    hostname = socket.gethostname()
    user = os.getlogin()
    now = datetime.now().strftime('%F %H:%M')
    return f'{hostname}, {now}, {user}'

def update_text(canvas):
    new_text = get_system_info()
    canvas.itemconfig('text', text=new_text)
    canvas.after(1000, update_text, canvas)

def display_watermark():
    # get the actual size including all monitors
    monitors = get_monitors()
    max_width = max(m.x+m.width for m in monitors)
    max_height = max(m.y+m.height for m in monitors)
    print(f'{max_width=} {max_height=}')

    root = tk.Tk()
    root.geometry(f'{max_width}x{max_height}+0+0')
    root.overrideredirect(True)
    root.attributes('-transparentcolor', COLOR, '-topmost', 1, '-alpha', 0.3)

    canvas = tk.Canvas(root, bg=COLOR, highlightthickness=0)
    canvas.pack(fill='both', expand=1)

    for y in range(-50, max_height+100, 400):
        for x in range(-100, max_width+200, 800):
            canvas.create_text(x, y, font=('Arial', 28, 'bold'), fill='gray', angle=45, tags=('text',))

    # call set_click_through after window is updated and ready
    root.after(10, set_click_through, root)
    root.after(20, update_text, canvas)
    root.mainloop()

if __name__ == '__main__':
    display_watermark()
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.