【问题标题】:Click-through tkinter windows点击 tkinter 窗口
【发布时间】:2021-05-15 07:04:09
【问题描述】:

函数复制自Tying to set non-interactable (click-through) overlay with TkInter

不仅窗口不能点击,png也不透明。 PNG在这里:https://drive.google.com/file/d/1tlLl2hjPq38mc_c_PpMhkKDlP1HqvDY5/view

这是窗口的样子:

我错过了什么?

from tkinter import*
import win32gui

from win32gui import GetForegroundWindow, ShowWindow, FindWindow, SetWindowLong, GetWindowLong, SetLayeredWindowAttributes
from win32con import SW_MINIMIZE, WS_EX_LAYERED, WS_EX_TRANSPARENT, GWL_EXSTYLE

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

root = Tk()
root.geometry("100x100")


root.overrideredirect(1)

root.attributes('-topmost', 1)
pic = PhotoImage(file=r'on2.png')
root.wm_attributes("-transparentcolor", 'white')

boardbutton = Label(root, image=pic, bd=0,
                    bg='white')
boardbutton.pack()
setClickthrough(root.winfo_id())
root.mainloop()

【问题讨论】:

    标签: python tkinter window transparent click-through


    【解决方案1】:

    我已经获取了linked question 的代码并使其工作。见以下代码:

    from tkinter import *
    from PIL import Image, ImageTk
    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)
    
    # Dimensions
    width = 1920 #self.winfo_screenwidth()
    height = 1080 #self.winfo_screenheight()
    
    root = Tk()
    root.geometry('%dx%d' % (width, height))
    root.title("Applepie")
    root.attributes('-transparentcolor', 'white', '-topmost', 1)
    root.config(bg='white') 
    root.attributes("-alpha", 0.25)
    root.wm_attributes("-topmost", 1)
    bg = Canvas(root, width=width, height=height, bg='white')
    
    setClickthrough(bg.winfo_id())
    
    frame = ImageTk.PhotoImage(file="example.png")
    bg.create_image(1920/2, 1080/2, image=frame)
    bg.pack()
    root.mainloop()
    

    您的尝试和工作示例之间的重要区别似乎是使用了画布而不是窗口的hwnd


    我不能完全按照你的意愿去做,但我提供了一些代码来输出这个结果,希望能满足你的需求。额外的代码只是删除了装饰(overrideredirect(1))并将窗口大小调整为 img 大小,并将其放置在屏幕中间。:

    from tkinter import *
    from PIL import Image, ImageTk
    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 size_position_for_picture():
        bbox = bg.bbox(img_id)
        w,h = bbox[2]-bbox[0],bbox[3]-bbox[1]
        x,y = sw/2-w/2,sh/2-h/2
        root.geometry('%dx%d+%d+%d' % (w,h, x,y))
        bg.configure(width=w,height=h)
        
    
    root = Tk()
    
    sw = root.winfo_screenwidth()
    sh = root.winfo_screenheight()
    
    root.overrideredirect(1)
    root.attributes("-alpha", 0.75)
    root.attributes('-transparentcolor', 'white', '-topmost', 1)
    bg = Canvas(root,bg='white',highlightthickness=0)
    root.config(bg='white')
    
    setClickthrough(bg.winfo_id())
    
    frame = ImageTk.PhotoImage(file="example.png")
    img_id = bg.create_image(0,0, image=frame,anchor='nw')
    bg.pack()
    
    size_position_for_picture()
    setClickthrough(bg.winfo_id())
    
    
    root.mainloop()
    

    【讨论】:

    • @martineau 我真的没有在脚本中复制和粘贴链接问题的问答做任何事情。我认为它们之间的重要区别似乎是在链接的答案中正在使用 Canvas,而这篇文章的 OP 正在尝试使用根窗口来执行此操作。我会将这个想法添加到我的答案中。
    • 所有有用的信息都应该在 IMO 的答案中。
    • 感谢您帮助我解决点击问题。当您运行它时,它会隔离 png 图像吗?对我来说,它仍然会在图像周围创建一个透明的白色屏幕。再说一次,我可能又把一些琐碎的事情搞砸了
    【解决方案2】:

    我的应用程序也有一个函数,代码看起来与你的非常相似,只是做了一些小的调整。你可以试试看:

    def set_clickthrough(hwnd, root):
        # Get window style and perform a 'bitwise or' operation to make the style layered and transparent, achieving
        # the clickthrough property
        l_ex_style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
        l_ex_style |= win32con.WS_EX_TRANSPARENT | win32con.WS_EX_LAYERED
        win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, l_ex_style)
    
        # Set the window to be transparent and appear always on top
        win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(0, 0, 0), 190, win32con.LWA_ALPHA)  # transparent
        win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, root.winfo_x(), root.winfo_y(), 0, 0, 0)
    

    还有,以下功能可以再次禁用点击

    def disable_clickthrough(hwnd, root):
        # Calling the function again sets the extended style of the window to zero, reverting to a standard window
        win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, 0)
        # Remove the always on top property again, in case always on top was set to false in options
        win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, root.winfo_x(), root.winfo_y(), 0, 0, 0)
    

    您可以通过调用win32gui.FindWindow(None, root.title())获取窗口句柄(hwnd)。

    【讨论】:

    • 谢谢!尽管我没有要求禁用点击功能,但它确实对我的项目有帮助
    猜你喜欢
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 2020-08-12
    • 2013-10-21
    相关资源
    最近更新 更多