2017-03-13 1 views
2

Windowsでモニター変更イベントを検出するためのPythonコードをいくつか記述しようとしています。私は主にpywin32 exampleのコードを中心にpywin32を使用しています。 PumpWaitingMessagesを配置すると違いがあるようです。下記のコードはモニターの変更を検出します(つまりOnDeviceChangeが実行されます)。lpの引数は0なので、そこから有用な情報(モニターID)を取得することはできません。私は__init__方法の最後に、コードの最後からwhile Trueループを移動した場合pywin32 win32gui.PumpWaitingMessages()配置

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) 

しかし、その後、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_には独自のウィンドウ処理機構があるので、それをplain _WinAPI_と混在させても問題ありませんか? – CristiFati

答えて

1

これは借用したコードの一部ですが、filterという変数の名前を変更することをお勧めします。[Python]: filter(function, iterable)はシャドーイングされています(ポストできなかったので自分自身を変更しませんでしたなぜ私がそれをしたのかを指定するコメント)。また、あなたは作業コードスニペットを持つように欠けている部分を追加したい場合があります:輸入、定義(例えばGUID_DEVINTERFACE_MONITORは、私がIoevent.hを閲覧し、私はUSBも表示GUIDの関連どちらを見つけることができませんでした)

私は、この動作のために責任を負うかもしれない2つのことが疑わ:

  • 平野WinAPIの(私は私のコメントで書いたように)と(独自のWindowsの取り扱いを持っている)PyQtはをミキシングして、その2の1は、相手のつま先を踏むかもしれないという可能性
  • パイソンスコープ([Python]: Execution model

私はPyQtはをインストールしたくなかったので、私は他の可能性を模索し始めました。私は元のコード(あなたが始めたもの)で同じ振る舞いを再現することができました。問題は、TestDeviceNotificationsの最後に、hdevRegisterDeviceNotificationが返されました)が範囲外になることでした。 を終了した後(メッセージがウィンドウに送信されるとき)、hdevは無効なハンドルになります。代わりに、同じ名前で新しいローカル1を作成するグローバル変数を操作するhdev = None

  • 指示し__init__

    • のような(Foo前)モジュールレベルでそれを宣言します。これを修正するには、それはグローバル作ります。どこか__init__で、hdev = win32gui.RegisterDeviceNotificationglobal hdevを追加し、永続的

    注(S)次のようになります。彼らはもはや必要だとき

    • は一般的に、作成されたすべてのリソースが解放されるべきではありません。これはあなたがwchwndとすべきことです。 hdevについて、[MSDN]: RegisterDeviceNotification functionは、それに応じCloseHandle(または類似なめらか)を呼び出すことについては何も言及していないので、私は、それは良いことだと思う
  • +0

    これはあなたの質問に答えますか? – CristiFati