Search code examples
pythontkinterwindowtransparentclick-through

Click-through tkinter windows


The function is copied from Tying to set non-interactable (click-through) overlay with TkInter

Not only is the window not click through, the png is also not transparent. PNG is here: https://drive.google.com/file/d/1tlLl2hjPq38mc_c_PpMhkKDlP1HqvDY5/view

This is what the window looks like:

screenshot of window

What am I missing?

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()

Solution

  • I have took the code of the linked question and made it work. See code below:

    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()
    

    The important difference between your try and the working example seems to be that there was in use the hwnd of a canvas instead of a window.


    I'm not abel to do exactly what you wish for but I have provided some code that outputs me this and hopefully sadisfy your needs. The extra code just removes the decoration (overrideredirect(1)) and resizes the window to the img size, also it places it in the middle of the screen.:

    enter image description here

    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()