Python 桌面程序开发 解决 win32gui 获取的位置不准的问题

问题背景

在 Python 桌面程序开发过程中,有时我们需要获取窗口的位置信息,例如鼠标点击的位置、窗口的坐标等。通常我们会使用 win32gui 模块来实现这个功能,但有时候我们会遇到获取的位置信息不准确的问题。比如,在一些高分辨率的屏幕下,通过 win32gui.GetCursorPos() 获取的鼠标位置可能偏离实际位置较大,或者通过 win32gui.GetWindowRect() 获取的窗口位置与预期不符。

问题原因分析

这个问题的原因是由于 win32gui 模块在获取位置信息时,使用的是设备无关单位(Device Independent Pixels,简称DIP)来表示位置。而在高分辨率屏幕下,1个 DIP 可能对应多个物理像素,这就导致了位置信息的不准确。

解决方案介绍

方案一:使用 ctypes 获取物理像素

为了解决位置信息不准确的问题,一种常见的方法是使用 ctypes 库来调用 Windows API 获取物理像素。通过获取物理像素,就可以解决由于设备无关单位引起的误差。

下面是一个获取鼠标位置的示例:

import ctypes

def get_physical_pixel():

user32 = ctypes.windll.user32

user32.SetProcessDPIAware()

scale_factor = user32.GetDeviceCaps(user32.GetDC(None), 88)

point = ctypes.wintypes.POINT()

user32.GetCursorPos(ctypes.byref(point))

physical_x = point.x * scale_factor / 96

physical_y = point.y * scale_factor / 96

return physical_x, physical_y

# 获取鼠标位置

x, y = get_physical_pixel()

print(f"鼠标位置:({x}, {y})")

通过调用 GetDeviceCaps 方法获取缩放因子,然后根据缩放因子对位置进行调整,就可以得到准确的物理像素位置。

方案二:使用 pywinauto 获取准确位置

除了使用 ctypes 来获取准确位置之外,还可以使用 pywinauto 这个第三方库来解决这个问题。

pywinauto 是一个用于自动化 Windows 桌面应用程序的库,它可以方便地获取窗口的位置信息。

下面是一个使用 pywinauto 获取窗口位置的示例:

from pywinauto import Desktop

def get_window_position(window_title):

app = Desktop(backend="uia").window(title=window_title)

return app.rectangle().left, app.rectangle().top

# 获取窗口位置

x, y = get_window_position("Notepad")

print(f"窗口位置:({x}, {y})")

通过调用 pywinauto 的 Desktop 类的 window 方法,传入窗口的标题,就可以获取到窗口的位置信息。

总结

通过以上两种方法,我们可以解决使用 win32gui 获取窗口位置不准确的问题。第一种方法使用 ctypes 调用 Windows API 直接获取物理像素,第二种方法使用 pywinauto 来获取准确的窗口位置信息。根据实际需求选择合适的解决方案。

后端开发标签