如何在没有窗口的情况下显示有背景的文字

问题描述 投票:0回答:1

我的程序每秒生成一个元组列表,该元组包含文本及其坐标。我需要在矩形(背景)上显示文本,在该矩形框架内,所有内容都将是透明的,没有程序窗口,并在第二次重绘所有内容后。另外,绘制的内容应该被鼠标忽略。谢谢。

我发现https://stackoverflow.com/a/22105730/23301946关闭并稍微更改了代码:

import win32api
import win32con
import win32gui
import win32ui

import multiprocessing
import time
import random

def generate_random_coordinates():
    x = random.randint(0, 1920)
    y = random.randint(0, 1080)
    return x, y

def generate_random_text():
    letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    text = ''.join(random.choice(letters) for _ in range(random.randint(1, 8)))
    return text

def main():
    hInstance = win32api.GetModuleHandle()
    className = 'MyWindowClassName'

    wndClass = win32gui.WNDCLASS()
    wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
    wndClass.lpfnWndProc = wndProc
    wndClass.hInstance = hInstance
    wndClass.hCursor = win32gui.LoadCursor(None, win32con.IDC_ARROW)
    wndClass.hbrBackground = win32gui.GetStockObject(win32con.WHITE_BRUSH)
    wndClass.lpszClassName = className
    wndClassAtom = win32gui.RegisterClass(wndClass)

    exStyle = (
        win32con.WS_EX_COMPOSITED |
        win32con.WS_EX_LAYERED |
        win32con.WS_EX_NOACTIVATE |
        win32con.WS_EX_TOPMOST |
        win32con.WS_EX_TRANSPARENT
    )
    
    style = win32con.WS_DISABLED | win32con.WS_POPUP | win32con.WS_VISIBLE

    hWindow = win32gui.CreateWindowEx(
        exStyle,
        wndClassAtom,
        None,
        style,
        0,
        0,
        win32api.GetSystemMetrics(win32con.SM_CXSCREEN),
        win32api.GetSystemMetrics(win32con.SM_CYSCREEN),
        None,
        None,
        hInstance,
        None
    )

    win32gui.SetLayeredWindowAttributes(hWindow, 0x00ffffff, 255, win32con.LWA_COLORKEY | win32con.LWA_ALPHA)

    win32gui.SetWindowPos(hWindow, win32con.HWND_TOPMOST, 0, 0, 0, 0,
        win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)

    win32gui.PumpMessages()

def wndProc(hWnd, message, wParam, lParam):
    if message == win32con.WM_PAINT:
        x, y = generate_random_coordinates()
        text = generate_random_text()

        hdc, paintStruct = win32gui.BeginPaint(hWnd)

        dpiScale = win32ui.GetDeviceCaps(hdc, win32con.LOGPIXELSX) / 60.0
        fontSize = 24

        lf = win32gui.LOGFONT()
        lf.lfFaceName = "Times New Roman"
        lf.lfHeight = int(round(dpiScale * fontSize))
        lf.lfQuality = win32con.NONANTIALIASED_QUALITY
        hf = win32gui.CreateFontIndirect(lf)
        win32gui.SelectObject(hdc, hf)

        text_position = (x, y)

        # Get the size of the text
        text_size = win32gui.GetTextExtentPoint32(hdc, text)

        # Set up the rectangle around the text
        text_rect = (
            text_position[0] - 5,
            text_position[1] - 5,
            text_position[0] + text_size[0] + 5,
            text_position[1] + text_size[1] + 5
        )

        # Create a blue brush for the text background
        gray_brush = win32gui.CreateSolidBrush(win32api.RGB(50, 50, 50))
        win32gui.FillRect(hdc, text_rect, gray_brush)

        # Draw the text with transparency
        win32gui.SetTextColor(hdc, win32api.RGB(220, 220, 220))
        win32gui.DrawText(
            hdc,
            text,
            -1,
            text_rect,
            win32con.DT_CENTER | win32con.DT_NOCLIP | win32con.DT_SINGLELINE | win32con.DT_VCENTER
        )

        # Release resources
        win32gui.DeleteObject(gray_brush)
        win32gui.EndPaint(hWnd, paintStruct)
        return 0

    elif message == win32con.WM_DESTROY:
        print('Closing the window.')
        win32gui.PostQuitMessage(0)
        return 0

    else:
        return win32gui.DefWindowProc(hWnd, message, wParam, lParam)

if __name__ == '__main__':
    p = multiprocessing.Process(target=main, name="Main", args=())
    p.start()

    time.sleep(5)

    p.terminate()
    p.join()

但是后台有问题,也不知道这种情况下如何动态更新信息。也许有更现代的方法。

python python-3.x pywin32
1个回答
0
投票

编程时,你不能只让东西出现在屏幕上。现代计算机有一个称为“Windows 管理器”的模块,它决定屏幕上的位置、顶部的内容等。这些模块非常复杂,并使用非常先进的方法与程序进行通信。

当创建一个想要使用屏幕的程序时,您应该使用一个库来与Windows管理器对话。这些库知道如何与 Windows 管理器对话。

Python 有一个内置库,保证可以在您使用的计算机上运行:

tkinter
。它基于一段名为
tcl/tk
的旧 GUI 代码。这就是为什么用它生成的 GUI 看起来有点奇怪,但在很多情况下它就足够好了,可能包括你的。如果没有,其他选项包括制作一个可以在浏览器中打开的动态网页、
pyqt
pyside
库(它们非常相似)、
kivy
(用于移动平台上的应用程序)或
wxpython
。不过,这些的学习曲线比
tkinter
更陡峭。使用原始的
win32
调用会带来更高的复杂性,而且还会带来一个额外的问题,那就是它会教你糟糕的编码实践。这些调用绝对不符合Python风格。

我建议您完成

tkinter
教程。

© www.soinside.com 2019 - 2024. All rights reserved.