How to make a pygame window transparent while still receiving and blocking mouse clicks?

Question:

I’m trying to make a program where the user can draw on the screen, I don’t want to make it so the program just takes a screenshot of the screen and draws on that, because this way the screen will freeze while drawing. So I decided to use pygame to make a transparent window which only shows the pen strokes. This way the screen will not freeze while drawing. So I searched "how to make a pygame window transparent" and I found this on stackoverflow: Fully transparent windows in Pygame?. So I installed pywin32 and copied the two lines of code:

hwnd = pygame.display.get_wm_info()["window"]
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE,
                       win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
# Set window transparency color
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*fuchsia), 0, win32con.LWA_COLORKEY)

I can’t understand this code at all, by the way, but it works. I open a pygame window in fullscreen using pygame.FULLSCREEN and use this code to make it transparent. Then I thought I could just program a paint editor and that’s it, but there is a big problem. The window can detect and block mouse clicks on places where there is something drawn, but in the transparent places the mouse clicks just go to the window behind. This is not what I want.

So I did more research and found a page that said fully transparent windows can’t detect mouse clicks, so a fix is to set the window to 99% transparent. Then the window will still be transparent but can detect mouse clicks (I can’t remember where I found this page). So I started trying to find out how to make a pygame window partly transparent. The transparent pygame window answer said the win32gui.SetLayeredWindowAttributes function is calling a win32api function (I don’t know win32api is), so I did more researching and found this page on microsoft about the SetLayeredWindowAttributes function: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setlayeredwindowattributes. The page said the third parameter of the function is the opacity of the window. So I changed the third parameter in the win32gui.SetLayeredWindowAttributes function in my python code from 0 to a bigger number, but when I ran the code, the window was still fully transparent and still wouldn’t receive mouse clicks. Changing the number didn’t seem to make any difference.

Then I had another idea, I thought if I fill the window with a semi-transparent color on the pygame window, it will remain (mostly) transparent, but will receive mouse clicks. So I tried this, but it didn’t work. If I fill the screen with any other color then the color that is set in the win32gui.SetLayeredWindowAttributes function, the window will no longer be transparent.

Now I really don’t know what to do. I’ve been Google searching for a really long time, but I can’t seem to find anything useful. So what I need to know is: how do I make the pygame window transparent while still detecting and blocking mouse clicks from just going through to the window behind?

This is a bit of my code, if it helps:

...
temp = pygame.display.Info()
self.screen_res = (temp.current_w, temp.current_h)
pygame.display.set_caption("Main")
screen = pygame.display.set_mode((self.screen_res[0], self.screen_res[1]), pygame.FULLSCREEN)
hwnd = pygame.display.get_wm_info()["window"]
win32gui.SetWindowLong(hwnd,
                       win32con.GWL_EXSTYLE,
                       win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*(0, 0, 0)), 0, win32con.LWA_COLORKEY)
gameRun = True
while gameRun:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameRun = False
    screen.fill((0, 0, 0))
    pygame.display.update()
pygame.display.quit()
...

By the way, I just created my stackoverflow account, and this is my first question 🙂

Asked By: I Like Python

||

Answers:

You need to also change the second to last parameter of SetLayeredWindowAttributes from win32con.LWA_COLORKEY to win32con.LWA_ALPHA, otherwise SetLayeredWindowAttributes ignores the alpha value. (LWA stands for LayeredWindowAttributes)

But I don’t think this really does what you want. It changes the alpha value of the whole window, meaning that also everything you draw will be partly transparent. I don’t think there is a way for just some parts of the window to be transparent in a way that they still receive events.

Answered By: MegaIng

I have done this myself and it works but another thing i dont want my mouse click through its just annoying mostly because it makes my frame ”clickable” through

Answered By: PCB
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.