在另一个进程的屏幕上显示文本覆盖

问题描述

我有一个问题,更多的是基于OS的问题。

我正在玩视频游戏,我希望能够在游戏屏幕上放置一个文本计时器,就像它是游戏本身的一部分一样。

现在,我可以用任何一种语言编写程序,在屏幕上显示带有计时器的TextBox,但是如果运行它,则游戏进程(称为game.exe)“失去”了焦点,我得到了文本框由操作系统集中和交互。

是否可以选择显示来自整个不同过程的game.exe的文本“在最上面”?好像屏幕上有“层”。另外,此文字不应太难理解,不可点击或使game.exe进程失去重点。

这是我画的一个非常简单的例子:

enter image description here

非常感谢!

解决方法

使用带有python和tkinter的窗口技巧和一些Windows api解决了该问题。 诀窍是创建一个透明的不可单击的窗口,并将其始终置于顶部。 我基本上将this答案与一堆简单的东西结合在一起,例如删除窗口的边框并设置为自动全屏显示。

from tkinter import *
import time
import win32gui
import win32api

from win32api import GetSystemMetrics
# WIDTH = 500
# HEIGHT = 500

WIDTH = GetSystemMetrics(0)
HEIGHT = GetSystemMetrics(1)
LINEWIDTH = 1
TRANSCOLOUR = 'gray'
title = 'Virtual whiteboard'
global old
old = ()
global HWND_t
HWND_t = 0

tk = Tk()
# tk.title(title)
tk.lift()
tk.wm_attributes("-topmost",True)
tk.wm_attributes("-transparentcolor",TRANSCOLOUR)
tk.attributes('-fullscreen',True)


state_left = win32api.GetKeyState(0x01)  # Left button down = 0 or 1. Button up = -127 or -128

canvas = Canvas(tk,width=WIDTH,height=HEIGHT,highlightthickness=0)
canvas.pack()
canvas.config(cursor='tcross')
canvas.create_rectangle(0,WIDTH,HEIGHT,fill=TRANSCOLOUR,outline=TRANSCOLOUR)
canvas.create_text(WIDTH/2,HEIGHT/2,fill="white",font="Arial 20",text="TEXT GOES HERE")

def putOnTop(event):
    event.widget.unbind('<Visibility>')
    event.widget.update()
    event.widget.lift()
    event.widget.bind('<Visibility>',putOnTop)
def drawline(data):
    global old
    if old !=():
        canvas.create_line(old[0],old[1],data[0],data[1],width=LINEWIDTH)
    old = (data[0],data[1])

def enumHandler(hwnd,lParam):
    global HWND_t
    if win32gui.IsWindowVisible(hwnd):
        if title in win32gui.GetWindowText(hwnd):
            HWND_t = hwnd

win32gui.EnumWindows(enumHandler,None)

tk.bind('<Visibility>',putOnTop)
tk.focus()

running = 1
while running == 1:
    try:
        tk.update()
        time.sleep(0.01)
        if HWND_t != 0:
            windowborder = win32gui.GetWindowRect(HWND_t)
            cur_pos = win32api.GetCursorPos()
            state_left_new = win32api.GetKeyState(0x01)
            if state_left_new != state_left:
                if windowborder[0] < cur_pos[0] and windowborder[2] > cur_pos[0] and windowborder[1] < cur_pos[1] and windowborder[3] > cur_pos[1]:
                    drawline((cur_pos[0] - windowborder[0] - 5,cur_pos[1] - windowborder[1] - 30))
            else:
                old = ()
    except Exception as e:
        running = 0
        print("error %r" % (e))