Skip to content

Instantly share code, notes, and snippets.

@ousttrue
Created December 27, 2011 18:32
Show Gist options
  • Save ousttrue/1524707 to your computer and use it in GitHub Desktop.
Save ousttrue/1524707 to your computer and use it in GitHub Desktop.
ctypes SetWindowLongPtr/GetWindowLongPtr sample
#!/usr/bin/env python
# coding: utf-8
import win32con
from ctypes import *
##############################################################################
# Windows types
##############################################################################
def ErrorIfZero(handle):
if handle == 0:
raise WinError
else:
return handle
WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)
CreateWindowEx = windll.user32.CreateWindowExA
CreateWindowEx.argtypes = [
c_int, c_char_p, c_char_p,
c_int, c_int, c_int, c_int,
c_int, c_int, c_int, c_int,
py_object
]
CreateWindowEx.restype = ErrorIfZero
SetWindowLongPtr = windll.user32.SetWindowLongA
SetWindowLongPtr.argtypes = [
c_int, c_int, c_void_p
]
SetWindowLongPtr.restype = c_void_p
GetWindowLongPtr = windll.user32.GetWindowLongA
GetWindowLongPtr.argtypes = [
c_int, c_int
]
GetWindowLongPtr.restype = c_void_p
class WNDCLASS(Structure):
_fields_ = [('style', c_uint),
('lpfnWndProc', WNDPROC),
('cbClsExtra', c_int),
('cbWndExtra', c_int),
('hInstance', c_int),
('hIcon', c_int),
('hCursor', c_int),
('hbrBackground', c_int),
('lpszMenuName', c_char_p),
('lpszClassName', c_char_p)]
class CREATESTRUCT(Structure):
_fields_ = [('lpCreateParams', c_void_p),
('hInstance', c_int),
('hMenu', c_int),
('hwndParent', c_int),
('cy', c_int),
('cx', c_int),
('y', c_int),
('x', c_int),
('style', c_int),
('lpszName', c_char_p),
('lpszClass', c_char_p),
('dwExStyle', c_int)]
class RECT(Structure):
_fields_ = [('left', c_long),
('top', c_long),
('right', c_long),
('bottom', c_long)]
class PAINTSTRUCT(Structure):
_fields_ = [('hdc', c_int),
('fErase', c_int),
('rcPaint', RECT),
('fRestore', c_int),
('fIncUpdate', c_int),
('rgbReserved', c_char * 32)]
class POINT(Structure):
_fields_ = [('x', c_long),
('y', c_long)]
class MSG(Structure):
_fields_ = [('hwnd', c_int),
('message', c_uint),
('wParam', c_int),
('lParam', c_int),
('time', c_int),
('pt', POINT)]
##############################################################################
# api class
##############################################################################
class Window(object):
def __init__(self):
self.hwnd=None
def finalize(self):
print 'finalize', self.__class__
def show(self):
windll.user32.ShowWindow(c_int(self.hwnd),
c_int(win32con.SW_SHOWNORMAL))
windll.user32.UpdateWindow(c_int(self.hwnd))
def WndProc(self, hwnd, message, wParam, lParam):
ps = PAINTSTRUCT()
rect = RECT()
if message == win32con.WM_PAINT:
hdc = windll.user32.BeginPaint(c_int(hwnd), byref(ps))
windll.user32.GetClientRect(c_int(hwnd), byref(rect))
windll.user32.DrawTextA(c_int(hdc),
"Python Powered Windows" ,
c_int(-1), byref(rect),
win32con.DT_SINGLELINE|
win32con.DT_CENTER|win32con.DT_VCENTER)
windll.user32.EndPaint(c_int(hwnd), byref(ps))
return 0
elif message == win32con.WM_DESTROY:
windll.user32.PostQuitMessage(0)
return 0
return windll.user32.DefWindowProcA(
c_int(hwnd), c_int(message), c_int(wParam), c_int(lParam))
@staticmethod
def WndProcProxy(hwnd, message, wParam, lParam):
p=GetWindowLongPtr(hwnd, win32con.GWL_USERDATA)
window=cast(p, py_object)
return window.value.WndProc(hwnd, message, wParam, lParam)
class WindowFactory(object):
def __init__(self):
self.classes=[]
self.windows=[]
def __del__(self):
self.finalize()
def finalize(self):
for w in self.windows:
w.finalize()
print 'finalize', self.__class__
def register_class(self, className):
"""
RegisterClassA
"""
# Define Window Class
wndclass = WNDCLASS()
wndclass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wndclass.lpfnWndProc = WNDPROC(WindowFactory.WndProc)
wndclass.cbClsExtra = wndclass.cbWndExtra = 0
wndclass.hInstance = windll.kernel32.GetModuleHandleA(
c_int(win32con.NULL))
wndclass.hIcon = windll.user32.LoadIconA(
c_int(win32con.NULL), c_int(win32con.IDI_APPLICATION))
wndclass.hCursor = windll.user32.LoadCursorA(
c_int(win32con.NULL), c_int(win32con.IDC_ARROW))
wndclass.hbrBackground = windll.gdi32.GetStockObject(
c_int(win32con.WHITE_BRUSH))
wndclass.lpszMenuName = None
wndclass.lpszClassName = className
# Register Window Class
if not windll.user32.RegisterClassA(byref(wndclass)):
raise WinError()
self.classes.append(wndclass)
return wndclass
def create(self, title, wndclass):
window=Window()
pywindow=py_object(window)
hwnd=CreateWindowEx(0,
wndclass.lpszClassName,
title,
win32con.WS_OVERLAPPEDWINDOW,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.NULL,
win32con.NULL,
wndclass.hInstance,
pywindow)
window.hwnd=hwnd
self.windows.append(window)
return window
def loop(self):
msg = MSG()
pMsg = pointer(msg)
NULL = c_int(win32con.NULL)
while windll.user32.GetMessageA( pMsg, NULL, 0, 0) != 0:
windll.user32.TranslateMessage(pMsg)
windll.user32.DispatchMessageA(pMsg)
return msg.wParam
@staticmethod
def WndProc(hwnd, message, wParam, lParam):
if message == win32con.WM_CREATE:
print 'WndProc', message, 'WM_CREATE'
lpcreatestruct=cast(lParam, POINTER(CREATESTRUCT))
createstruct = lpcreatestruct.contents;
SetWindowLongPtr(c_int(hwnd), win32con.GWL_USERDATA,
createstruct.lpCreateParams);
SetWindowLongPtr(c_int(hwnd), win32con.GWL_WNDPROC,
cast(WNDPROC(Window.WndProcProxy), c_void_p));
window=cast(createstruct.lpCreateParams, py_object).value
return window.WndProc(hwnd, message, wParam, lParam)
elif message == win32con.WM_DESTROY:
windll.user32.PostQuitMessage(0)
return 0
return windll.user32.DefWindowProcA(
c_int(hwnd), c_int(message), c_int(wParam), c_int(lParam))
if __name__=="__main__":
import os
if os.name!='nt':
print "this script is windows only: "+os.name
sys.exit()
factory=WindowFactory()
wndclass=factory.register_class("MainWin")
window=factory.create("Python Window", wndclass)
window.show()
import sys
sys.exit(factory.loop())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment