Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pygame: allow clicks to go through the window

I'm making a pseudo transparent window in pygame with the intent of displaying varied info like a "HUD"

The script uses PIL to grab an image of the desktop and use it as the background of the window.

A simple version:

import pygame as py
from ctypes import windll
import ImageGrab, Image

SetWindowPos = windll.user32.SetWindowPos

py.init()

def get_image():
    im = ImageGrab.grab((0,0,window_x,window_y))
    mode = im.mode
    size = im.size
    data = im.tobytes()
    im = py.image.fromstring(data,size,mode)
    return im

window_x = 1920
window_y = 100

background = py.Surface((window_x,window_y))
background.blit(get_image(),(0,0))

window_pos = (0,0)


screen = py.display.set_mode((window_x,window_y),py.HWSURFACE|py.NOFRAME)

SetWindowPos(py.display.get_wm_info()['window'],-1,0,0,0,0,0x0001)

clock = py.time.Clock()

done = False

while not done:
    for event in py.event.get():
        if event.type == py.QUIT:
            done = True
    screen.blit(background,(0,0))
    py.display.flip()
    clock.tick(30)

py.quit()

This creates a Pygame window at the top of the screen.

My problem is that the Pygame window blocks any mouse interaction with anything beneath it.

Is there a way to allow mouse events to be ignored and go 'through' the window, like for example clicking on a desktop icon, underneath a Pygame window.

like image 650
DCA- Avatar asked May 11 '16 14:05

DCA-


2 Answers

You will need to do a bit of an extra hacking which is outside what PyGame gives you. It should be possible to render the PyGame canvas into another windowing framework in Python and try to use advanced features of that library to achieve this.

In Windows

One example is wxWidgets. As described in this thread, which sounds quite similar to what you are trying to achieve, the user has setup a window which can be clicked through and is transparent.

Also see this another Stackoverflow Post which mentions how to handle the Hit Testing in C#. Posting code from that post here:

protected override void WndProc(ref Message m)
{
    if (m.Msg == (int)WM_NCHITTEST)
        m.Result = (IntPtr)HTTRANSPARENT;
    else
        base.WndProc(ref m);
}

It is possible to do similar testing in Python using win32 APIs. This is a piece of Python code that does exactly this. Locate the part where the programmer sets up the callback for the event (something like win32con.WM_NCHITTEST: self.onChi, where self.onChi is the callback).

I hope this gives you a starting point. I doubt there is anything readymade that you will find out of the box but these should give you some pointers on what to look for.

like image 57
Nandeep Mali Avatar answered Oct 05 '22 15:10

Nandeep Mali


This is an old question, but I have ran into it quite a few times and only now got it to work right. Here is the relevant bit.

import win32api
import win32con
import win32gui

fuchsia = (255, 0, 128)  # Transparency color
hwnd = pygame.display.get_wm_info()["window"] # Handle
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, win32api.RGB(*fuchsia), 0, win32con.LWA_COLORKEY)
like image 21
BunnyMerz Avatar answered Oct 05 '22 14:10

BunnyMerz