Python pywin32 win32gui.PumpWaitingMessages()位置

Python pywin32 win32gui.PumpWaitingMessages()位置,python,winapi,pywin32,Python,Winapi,Pywin32,我试图编写一些python代码来检测Windows中的监视器更改事件;我使用的是pywin32,主要基于。似乎PumpWaitingMessages的位置会有所不同;下面的代码确实检测到监视器更改(即运行OnDeviceChange),但lp参数为0,因此我无法从中获取任何有用的信息(即监视器标识符) 但是,如果我将while True循环从代码的最末端移动到\uuuu init\uuuu方法的末端,那么lp参数将被填充,并且我可以获得所需的信息 你知道为什么while循环的位置会有所不同吗?虽

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

但是,如果我将
while True
循环从代码的最末端移动到
\uuuu init\uuuu
方法的末端,那么
lp
参数将被填充,并且我可以获得所需的信息


你知道为什么while循环的位置会有所不同吗?

虽然它是借用的代码的一部分,但我还是建议将变量
filter
重命名为其他名称,因为它是阴影(我编辑帖子时没有改变自己,因为我无法发布说明我为什么这么做的评论)。此外,您可能希望添加缺少的部分以获得一个工作代码段:导入、定义(例如,
GUID\u deviceinterface\u MONITOR
,我浏览了Ioevent.h,并且我既找不到USB也找不到与显示相关的GUID)

我怀疑这一行为有两个原因:

  • 将PyQt(它有自己的windows处理)与普通WinAPI(正如我在评论中所写的)混合使用,以及其中一个可能会踩到另一个的脚
  • Python作用域()
我不想安装PyQt,所以我开始探索另一种可能性。我能够用原始代码(您从中开始)复制相同的行为。问题是在
TestDeviceNotifications
结束时,
hdev
(由
RegisterDeviceNotification
返回)超出了范围

这里也会发生同样的情况:退出
\uuuu init\uuuu
后,(当消息开始发送到窗口时)
hdev
将是一个无效的句柄。要更正此问题,请将其设为全局句柄:

  • 在模块级声明它(在
    Foo
    之前),例如:
    hdev=None
  • 指示
    \uuuu init\uuuu
    对全局变量进行操作,而不是创建具有相同名称的新局部变量。在
    \uuuuuu init\uuuu
    的某个地方,在
    之前
    hdev=win32gui。RegisterDeviceNotification
    添加
    全局hdev
    ,它将是持久的
注意事项

  • 通常,所有创建的资源都应该在不再需要时释放。这是使用
    wc
    hwnd
    应该做的。关于
    hdev
    ,没有提到任何关于调用
    CloseHandle
    (或类似的smth)的内容,所以我认为,这很好

Hmm;查看PumpWaitingMessages的文档,它似乎在当前线程上工作;我猜这就是问题所在。我不知道问题出在哪里,但我确实看到了这一点,这可能不是您想要做的。您可能还希望仅通过将
HWND\u message
作为父线程传递来生成窗口消息dow参数到
CreateWindow()
,但我不确定这是否会使您的窗口不符合设备通知的条件。我看到
Foo
扩展了
QObject
。您也在使用PyQt吗?如果是,因为Qt有自己的windows处理机制,可以将其与普通的WinAPI混合使用吗?我同时使用PyQt和pywin32;设备更改事件不是ex这是否回答了你的问题?
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)