2013-12-20 5 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 : 메시지를 기다리는 더 좋은 방법이 있습니까? 불행히도 저는 파이썬에서 이런 종류의 것들에 대한 많은 정보/예제를 실제로 찾지 못했습니다. – Jacobm001

답변

0

SendMessage은 동기식입니다. WM_COPYDATA을 다른 응용 프로그램에 보내면 회신을받을 때까지 코드는 Windows 내부 메시지 루프에서 대기합니다.

즉, 코드가 대기중인 다른 응용 프로그램의 메시지에 응답 할 수 있습니다. 프로토콜에 메시지 교환이 필요한 경우이 작업이 필요할 수 있습니다.

원치 않는 메시지에 응답하는 경우에만 메시지 루프가 필요합니다.

내가하는 일을 정확하게 알지 못하지만 대부분 win32gui.PumpMessages 번으로 전화를 제거 할 수 있습니다.

+0

이것은 올바르지 않거나 적어도 용어가 해제되어 있습니다. 'SendMessage (..., WM_COPYDATA, ...)'실제로 동기입니다. 그러나'SendMessage'에 대한 호출은 메시지가 처리되었을 때 리턴합니다. 나는 "당신의 답장을 얻을 때까지 * 귀하의 코드는 Windows 내부의 메시지 루프에서 기다릴 것입니다."라고 말하는 것은 현명하지 않다고 생각합니다. 호출 프로세스는 수신 프로세스가 처리를 완료 할 때까지 차단됩니다. 메시지 루프가 아닙니다. –

+1

이제 메시지 루프가 필요합니다. 뭔가 들어오는 동기 메시지를 발송해야합니다. 일반적으로 이는 메시지 루프의 일부로 수행됩니다. 'GetMessage'를 호출 할 때 수행됩니다. –

+0

@DavidHeffernan SendMessage (매우 자주 일어나는 일)에 대한 응답으로 메시지를 받으면 어떻게 전달됩니까? 잊었다. 나는 이것이 메시지 루프가 아니라고 당신이 맞다고 생각합니다. 아마도 메시지가 창 프로 시저에 직접 전달됩니다. 어느 쪽이든, 그것은 * 귀하의 메시지 루프를 통과하지 않습니다. 그가 다른 앱을 운전하고 있다면 그는 원치 않는 메시지를받지 않으므로 왜 메시지 루프가 필요한가요? – arx