2017-03-13 76 views
2

我試圖編寫一些python代碼來檢測Windows中的監視器更改事件;我使用pywin32,主要基於pywin32 example的代碼。看來PumpWaitingMessages的位置有所不同;下面的代碼檢測到監視器變化(即OnDeviceChange得到運行),但lp參數爲0,所以我無法從它獲得任何有用的信息(即監視器標識符)。pywin32 win32gui.PumpWaitingMessages()placement

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循環會有所作爲?

+0

嗯;查看PumpWaitingMessages的文檔,它似乎適用於當前線程;我猜測這是問題出在哪裏。 – askvictor

+0

我不知道問題是什麼,但是我確實看到[您正在全局註冊窗口類](https://blogs.msdn.microsoft.com/oldnewthing/20050418-59/?p=35873),這可能不是你想要做的。您也可能想要創建窗口消息 - 僅通過將'HWND_MESSAGE'作爲父窗口參數傳遞給'CreateWindow()',但我不確定是否會使您的窗口不適用於設備通知。 – andlabs

+0

我看到'Foo'擴展了'QObject'。你是否也在使用_PyQt_?如果是,由於_Qt_有它自己的窗口處理機制,可以將它與純_WinAPI_混合嗎? – CristiFati

回答

1

雖然它是借來的代碼的一部分,但我會開始建議將變量filter重命名爲其他內容,因爲它是隱藏的[Python]: filter(function, iterable)(由於我無法發佈而無法修改自己的帖子一個評論,說明我爲什麼這樣做)。此外,您可能要添加缺失的部分有一個工作代碼片段:進口,定義(例如GUID_DEVINTERFACE_MONITOR,我瀏覽Ioevent.h,我找不到既不USB也沒有顯示相關GUID S)

我懷疑2周的事情,可能會爲這種行爲承擔責任:

  • 混合PyQt的(它有自己的窗口處理)用普通WinAPI的(正如我在評論中寫道),和該可能性2的一個可能在其他腳趾步驟
  • 的Python範圍([Python]: Execution model

我不想安裝PyQt的,所以我就開始探索其他可能性。我能夠用原始代碼(從開始)重現相同的行爲。問題是,在TestDeviceNotificationshdev(由RegisterDeviceNotification返回)結束時,超出了範圍。

同樣的事情發生在這裏:在退出__init__(當消息將開始發送到窗口)hdev將是一個無效的句柄。爲了解決這個問題,使之全球

  • 在模塊級(Foo之前)像其聲明:hdev = None
  • 請示__init__對全局變量操作創建一個新的本地一個具有相同的名稱,而不是。某處在__init__以前hdev = win32gui.RegisterDeviceNotification添加global hdev,這將是持久的

說明(S)

  • 通常情況下,所有創建的資源應時,他們不再需要釋放。這是你應該用wchwnd來做的事情。關於hdev[MSDN]: RegisterDeviceNotification function沒有提及調用CloseHandle(或不服類似)在任何東西,所以我認爲,這是很好的
+0

這是否回答你的問題? – CristiFati