使用 SetWindowPos() 将 Python 应用程序窗口移动到第二个显示器时,我需要单击第一个显示器来控制应用程序

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

我有一个适用于 Windows 的 Python 小型 OpenGL 应用程序。应用程序窗口是无边框窗口;它不是全屏的。当使用 SetWindowPos() 将应用程序窗口移动到第二个显示器时,我需要单击第一个显示器以使应用程序处理鼠标输入;即,当我单击第一个监视器时,应用程序仅捕获鼠标单击。单击应用程序窗口会将其转到后台,就像单击桌面一样。看起来 Windows (11) 对应用程序窗口的位置有错误的认识。

两台显示器均在 Windows 中正确配置。

我不知道为什么会发生这种情况。我的意思是,当我使用 ctypes.windll.user32.SetWindowPos() 移动窗口时,Windows 应该跟踪它,不是吗?

打电话

    windll.user32.SetCapture(globals.displayHandler.windowHandle)

    pygame.event.set_grab(True)

没有帮助。

我该如何解决这个问题?

最小可重现示例(Python 3.11.4,因为它带有预构建的 pyopengl 和 pyopengl-accelerate):

import pygame
from screeninfo import get_monitors
from ctypes import windll, Structure, c_long, byref

class WindowRect(Structure):
    _fields_ = [
        ('left',    c_long),
        ('top',     c_long),
        ('right',   c_long),
        ('bottom',  c_long),
        ]
    def width(self):  return self.right  - self.left
    def height(self): return self.bottom - self.top

class DisplayHandler:
    def __init__ (self):
        monitorInfo = get_monitors()
        numDisplays = len(monitorInfo)
        if numDisplays == 1:
            self.appDisplay = 0
            self.xOffset = 0
        else:
            self.appDisplay = 1
            self.xOffset = monitorInfo[self.appDisplay].width
        self.maxWidth = monitorInfo[self.appDisplay].width
        self.maxHeight = monitorInfo[self.appDisplay].height
        self.screenType = pygame.DOUBLEBUF | pygame.OPENGL | pygame.NOFRAME
        try:
            pygame.display.set_mode (size = (self.maxWidth, self.maxHeight), flags = self.screenType, vsync = 1)
        except pygame.error:
            print ("Couldn't set display mode ({0})".format (pygame.get_error()))
            exit()
        self.windowHandle = pygame.display.get_wm_info()['window']
        self.FixWindowPos()

    def FixWindowPos(self):
        if self.appDisplay > 0:
            rc = WindowRect()
            windll.user32.GetWindowRect(self.windowHandle, byref(rc))
            if (rc.left != self.xOffset):
                print ("fixing window position")
                windll.user32.SetWindowLongPtrW(self.windowHandle, -20, windll.user32.GetWindowLongPtrW(self.windowHandle, -20) | 0x08000000)
                windll.user32.SetForegroundWindow (self.windowHandle)
                windll.user32.SetActiveWindow (self.windowHandle)
                windll.user32.SetFocus (self.windowHandle)
                windll.user32.SetWindowPos(self.windowHandle, -1, self.xOffset, 0, 0, 0, 0x0215)


class Application:
    def __init__(self):
        self.displayHandler = DisplayHandler ()
    
    def HandleEvents (self) -> bool:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT):
                return False
            elif (event.type == pygame.KEYDOWN):
                if (event.key == pygame.K_ESCAPE):
                    return False
        return True
    
    def Run(self):
        print ("press ESC to quit ...")
        while self.HandleEvents():
            self.displayHandler.FixWindowPos()
        
app = Application()
app.Run()
python-3.x pygame setwindowpos
1个回答
0
投票

我自己设法找到了解决方案,但我把这个问题和我的解决方案一起提出来,供将来可能遇到这个问题的人使用。

通过在 pygame.display.set_mode 的调用中添加参数“display = self.appDisplay”,可以轻松解决该问题:

    try:
        pygame.display.set_mode (size = (self.maxWidth, self.maxHeight), flags = self.screenType, vsync = 1, display = self.appDisplay)
    except pygame.error:
        print ("Couldn't set display mode ({0})".format (pygame.get_error()))
        exit()
© www.soinside.com 2019 - 2024. All rights reserved.