2013-12-20 2 views
0

Я пишу скрипт, который взаимодействует с программой WM_COPYDATA api, но застрял в функциональности PumpMessage.Никогда не прошел PumpMessages

import win32con, win32api, win32gui 
import ctypes, ctypes.wintypes 

FindWindow = ctypes.windll.user32.FindWindowW 
SendMessage = ctypes.windll.user32.SendMessageW 

class COPYDATASTRUCT(ctypes.Structure): 
    _fields_ = [ 
     ('dwData', ctypes.wintypes.LPARAM), 
     ('cbData', ctypes.wintypes.DWORD), 
     ('lpData', ctypes.c_char_p) 
     #formally lpData is c_void_p, but we do it this way for convenience 
] 

PCOPYDATASTRUCT = ctypes.POINTER(COPYDATASTRUCT) 

class Stickies: 

    def __init__(self): 
     message_map = { 
      win32con.WM_COPYDATA: self.OnCopyData 
     } 
     wc = win32gui.WNDCLASS() 
     wc.lpfnWndProc = message_map 
     wc.lpszClassName = 'MyWindowClass' 
     hinst = wc.hInstance = win32api.GetModuleHandle(None) 
     classAtom = win32gui.RegisterClass(wc) 
     self.hwnd = win32gui.CreateWindow (
      classAtom, 
      "win32gui test", 
      0, 
      0, 
      0, 
      win32con.CW_USEDEFAULT, 
      win32con.CW_USEDEFAULT, 
      0, 
      0, 
      hinst, 
      None 
     ) 
     self.send_message("api do register") 

    def __enter__(self): 
     return self 

    def __exit__(self): 
     self.send_message("api do deregister") 

    def send_message(self, msg): 
     hwnd = FindWindow(None, "ZhornSoftwareStickiesMain") 
     cds = COPYDATASTRUCT() 
     cds.dwData = 0 
     str = msg.encode("ascii") 
     cds.cbData = ctypes.sizeof(ctypes.create_string_buffer(str)) 
     cds.lpData = ctypes.c_char_p(str) 
     SendMessage(hwnd, win32con.WM_COPYDATA, self.hwnd, ctypes.byref(cds)) 

    def OnCopyData(self, hwnd, msg, wparam, lparam): 
     pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT) 
     msg = pCDS.contents.lpData.decode("ascii", "ignore") 

     if msg != None: 
      print(msg) 

     return 1 

s = Stickies() 
win32gui.PumpMessages() 

# Never gets past previous line 
print("Hello, world!") 

В моем коде, я могу успешно отправлять и получать сообщения, но я не уверен, о том, как я могу позволить мои скрипты делать другие вещи. Моя цель - использовать это как базовый класс, а затем включить его в другие скрипты.

Я не уверен, как:

  1. пройти функции PumpMessage()
  2. обрабатывают сообщения за пределами класса.

Любая помощь была бы принята с благодарностью.

+0

PumpMessages реализует стандартный цикл сообщений Windows. Он обрабатывает и обрабатывает сообщения. Вы не ожидали, что он вернется, пока поток не получит сообщение WM_QUIT (обычно, когда главное окно закрывается в GUI-приложении). – arx

+0

@arx: Есть ли лучший способ ждать сообщений? К сожалению, я действительно не нахожу много информации/примеров онлайн для этого типа вещей в Python. – Jacobm001

ответ

0

SendMessage является синхронным. Отправьте WM_COPYDATA в другое приложение, и ваш код будет ждать в цикле сообщений Windows, пока вы не получите ответ.

Это означает, что ваш код может отвечать на сообщения от другого приложения во время ожидания. Это может потребоваться, если протокол включает обмен сообщениями.

Если вы отвечаете на нежелательные сообщения, вам нужен только цикл сообщений.

Я не знаю точно, что вы делаете, но, скорее всего, вы можете полностью удалить звонок на win32gui.PumpMessages.

+0

Это неправильно, или, по крайней мере, терминология отключена. 'SendMessage (..., WM_COPYDATA, ...)' действительно синхронно. Но вызов «SendMessage» возвращается, когда сообщение было обработано. Я не думаю, что было бы разумно сказать, что «* ваш код будет ждать в цикле сообщений Windows, пока вы не получите ответ *». Случается, что процесс вызова блокируется до тех пор, пока процесс получения не завершит обработку. Это не цикл сообщений. –

+1

Теперь, вероятно, должен быть цикл сообщений. Что-то должно отправлять входящие синхронные сообщения. Обычно это делается как часть цикла сообщений. Это делается в вызове 'GetMessage'. –

+0

@DavidHeffernan Если вы получили сообщение в ответ на SendMessage (что-то, что происходит очень часто), то как оно доставляется? Я забыл. Я думаю, вы правы, что это не цикл сообщений. Возможно, сообщение доставляется непосредственно к процедуре окна. В любом случае, он не проходит * ваш * цикл сообщений. Если он управляет другим приложением, он не получит никаких незапрашиваемых сообщений, так зачем ему нужен цикл сообщений? – arx