Wednesday, July 27, 2016

Sending WM_COPYDATA in Python with ctypes

Putting together pieces from a few online sources, here is example code that:
  • Supports 32-bit and 64-bit Python
  • Uses only standard libraries (for Python 2.5+)
  • Can be used to send commands to the SciTE code editor

In particular, there is no win32gui dependency.

import sys
import ctypes
from ctypes import wintypes


context64bit = sys.maxsize > 2**32
if context64bit:
  class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [('dwData', ctypes.c_ulonglong),
      ('cbData', ctypes.wintypes.DWORD),
      ('lpData', ctypes.c_void_p)]
  class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [('dwData', ctypes.wintypes.DWORD),
      ('cbData', ctypes.wintypes.DWORD),
      ('lpData', ctypes.c_void_p)]

def findWindow(windowClass):
  receiver = None
  hwnd = ctypes.windll.user32.FindWindowA(
    windowClass, receiver)
  return hwnd or None

def sendMessage(message, hwnd, dwData=0):
  assert isinstance(message, str)
  sender_hwnd = 0
  buf = ctypes.create_string_buffer(message)
  copydata = COPYDATASTRUCT()
  copydata.dwData = dwData
  copydata.cbData = buf._length_
  copydata.lpData = ctypes.cast(buf, ctypes.c_void_p)
  return ctypes.windll.user32.SendMessageA(
    hwnd, WM_COPYDATA, sender_hwnd,

In Python 3, the parameter would presumably be a bytes object and not a str object.

No comments: