-->

Pygame: allow clicks to go through the window

2020-07-10 07:27发布

问题:

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.

回答1:

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.