Tkinter透明窗口不受鼠标点击影响。

5
我目前正在使用Python发送鼠标和按键命令来控制游戏。我想要做的是在游戏上方放置一个透明的Tkinter窗口,以提供一些信息,如鼠标位置和像素颜色等。
我熟悉更改窗口的alpha属性以使其透明,但不知道如何始终将该窗口保持在前面并使鼠标点击穿过它。
我目前控制游戏的方法涉及在特定位置截取屏幕截图并分析颜色内容。我还需要一种方法来在没有Tkinter窗口干扰的情况下进行此操作。
Pyscreenshot用于屏幕截图 win32api用于点击
谢谢, Alec
1个回答

4

您可以使用win32gui模块的SetWindowLong函数。如果您想要一个透明的点击透过窗口,您需要在您的窗口上应用GWL_EXSTYLE。因此您需要知道您窗口的句柄。

hwnd = win32gui.FindWindow(None, "Your window title") # Getting window handle
# hwnd = root.winfo_id() getting hwnd with Tkinter windows
# hwnd = root.GetHandle() getting hwnd with wx windows
lExStyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
lExStyle |=  win32con.WS_EX_TRANSPARENT | win32con.WS_EX_LAYERED
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE , lExStyle )

如果您想通过winapi更改窗口的透明度,请使用SetLayeredWindowAttributes

编辑:示例代码用于创建一个始终置顶透明窗口,该窗口可以通过点击穿透。它获取当前桌面图像并创建一个透明覆盖层,以便您可以享受桌面背景图像。

from win32api import GetSystemMetrics
import win32con
import win32gui
import wx


def scale_bitmap(bitmap, width, height):
    image = wx.ImageFromBitmap(bitmap)
    image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
    result = wx.BitmapFromImage(image)
    return result

app = wx.App()
trans = 50
# create a window/frame, no parent, -1 is default ID
# change the size of the frame to fit the backgound images
frame1 = wx.Frame(None, -1, "KEA", style=wx.CLIP_CHILDREN | wx.STAY_ON_TOP)
# create the class instance
frame1.ShowFullScreen(True)
image_file = win32gui.SystemParametersInfo(win32con.SPI_GETDESKWALLPAPER,0,0)
bmp1 = wx.Image(image_file, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
bmp1 = scale_bitmap(bmp1,GetSystemMetrics(1)*1.5,GetSystemMetrics(1))
bitmap1 = wx.StaticBitmap(frame1, -1, bmp1, (-100, 0))
hwnd = frame1.GetHandle()
 
extendedStyleSettings = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, extendedStyleSettings  | win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT)
win32gui.SetLayeredWindowAttributes(hwnd, 0, 255, win32con.LWA_ALPHA)
 
frame1.SetTransparent(trans)


def onKeyDown(e):
    global trans
    key = e.GetKeyCode()
    if  key==wx.WXK_UP:
        print trans
        trans+=10
        if trans >255:
            trans = 255
    elif key==wx.WXK_DOWN:
        print trans
        trans-=10
        if trans < 0:
            trans = 0
    try:
        win32gui.SetLayeredWindowAttributes(hwnd, 0, trans, win32con.LWA_ALPHA)
    except:
        pass
frame1.Bind(wx.EVT_KEY_DOWN, onKeyDown)

app.MainLoop()

你可以通过上下箭头动态改变透明度。 注意,窗口框架是使用“wx”创建的,但也应该适用于tkinter。
随意使用代码。

这应该是有效的。我已经编写了一个小脚本,将我的桌面背景图像作为透明的最顶层窗口放置在所有其他窗口之上。这按预期工作,所有点击和拖放也都可以正常使用。 - VRage
但是你也可以尝试处理 WM_NCHITTEST 并返回 HTNOWHERE - VRage
2
如果我不知道你的代码,很难给出有用的帮助... 我建议您使用可复现的代码创建一个问题。 - VRage
1
@PSSolanki,我已经很久没有接触Python了,但我编写了一个小应用程序,可以满足您的需求。请注意,它是wxPython和Python 2.7编写的。我想我使用wx是因为tk在处理图像方面存在一些问题...但这太久远了,记不清楚了。 - VRage
非常感谢您的大力帮助!在执行 pip install wxpython 后,第一次尝试就成功了 :)。 - Eric Carmichael
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接