我试图编写一些python代码来检测Windows中的监视器更改事件;我正在使用pywin32,主要基于pywin32 example中的代码。看来PumpWaitingMessages的位置有所不同;下面的代码确实检测到监视器更改(即OnDeviceChange被运行),但是lp参数为0,所以我无法从中获取任何有用的信息(即监视器标识符)。

class Foo(QObject):
    def OnDeviceChange(self, hwnd, msg, wp, lp):
        info = win32gui_struct.UnpackDEV_BROADCAST(lp)
        print("Device change notification:", wp, str(info))  #
        return True

    def __init__(self):
        wc = win32gui.WNDCLASS()
        wc.lpszClassName = 'test_devicenotify'
        wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW
        wc.hbrBackground = win32con.COLOR_WINDOW + 1
        wc.lpfnWndProc = {win32con.WM_DEVICECHANGE: self.OnDeviceChange}
        class_atom = win32gui.RegisterClass(wc)
        hwnd = win32gui.CreateWindow(wc.lpszClassName,
            'Waiting for Monitor Change',
            # no need for it to be visible.
            win32con.WS_CAPTION,
            100, 100, 900, 900, 0, 0, 0, None)
        filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE(
                                            GUID_DEVINTERFACE_MONITOR)
        hdev = win32gui.RegisterDeviceNotification(hwnd, filter,
                                                   win32con.DEVICE_NOTIFY_WINDOW_HANDLE)


f = Foo()
while True:
    win32gui.PumpWaitingMessages()
    time.sleep(0.01)


但是,如果将while True循环从代码的最后移到__init__方法的末尾,则会填充lp参数,并且可以获得所需的信息。

有什么想法为什么while循环的位置会有所作为?

最佳答案

尽管它是借来的代码的一部分,但我还是会建议将变量filter重命名为其他名称,因为它会掩盖[Python]: filter(function, iterable)(编辑帖子时我不会改变自己,因为我无法发布说明我为什么这样做的评论)。另外,您可能想添加缺少的部分以使用有效的代码段:导入,定义(例如GUID_DEVINTERFACE_MONITOR,我浏览了Ioevent.h,但找不到USB或显示相关的GUID)

我怀疑有2件事可能为此行为负责:


将PyQt(具有自己的Windows处理功能)与普通的WinAPI混合(正如我在评论中所写),并且这两种可能之一踩在另一只脚上
Python作用域([Python]:Execution model


我不想安装PyQt,因此我开始探索另一种可能性。我能够使用原始代码(从此开始)重现相同的行为。问题是在TestDeviceNotifications的末尾,hdev(由RegisterDeviceNotification返回)超出范围。

此处发生相同的事情:退出__init__后,(当消息开始发送到窗口时)hdev将是无效的句柄。要更正此问题,请将其全局化:


在模块级别(在Foo之前)声明它,例如:hdev = None
指示__init__对全局变量进行操作,而不要创建具有相同名称的新本地变量。在__init__中的某个位置,在hdev = win32gui.RegisterDeviceNotification之前添加global hdev,它将保持不变


笔记):


通常,所有不再需要的资源都应释放。这是您应该对wchwnd进行的操作。关于hdev[MSDN]: RegisterDeviceNotification function没有提及在其上调用CloseHandle(或类似的东西),所以我认为这很好

关于python - pywin32 win32gui.PumpWaitingMessages()位置,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42762309/

10-12 22:43