Monday, March 28, 2011

Simple Win32 python and ctypes sample converted to python 3.x

In my previous post I was playing with ctypes and Win32 API and created hello world application. I wanted to check how easy is to use underling os native libraries from python with help of ctypes module. It was easy and I stated thinking how long it would take for me to convert it into working python 3.x example... It took me few minutes and here it is code of my sample written in python 3...

from sys import platform, exit
from ctypes import *
from ctypes.wintypes import DWORD, HWND, HANDLE, LPCWSTR, WPARAM, LPARAM, RECT, POINT, MSG

WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)

WS_EX_APPWINDOW = 0x40000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_CAPTION = 0xc00000

SW_SHOWNORMAL = 1
SW_SHOW = 5

CS_HREDRAW = 2
CS_VREDRAW = 1

CW_USEDEFAULT = 0x80000000

WM_DESTROY = 2

WHITE_BRUSH = 0

class WNDCLASSEX(Structure):
    _fields_ = [("cbSize", c_uint),
                ("style", c_uint),
                ("lpfnWndProc", WNDPROCTYPE),
                ("cbClsExtra", c_int),
                ("cbWndExtra", c_int),
                ("hInstance", HANDLE),
                ("hIcon", HANDLE),
                ("hCursor", HANDLE),
                ("hBrush", HANDLE),
                ("lpszMenuName", LPCWSTR),
                ("lpszClassName", LPCWSTR),
                ("hIconSm", HANDLE)]

def PyWndProcedure(hWnd, Msg, wParam, lParam):
 if Msg == WM_DESTROY:
  windll.user32.PostQuitMessage(0)
 else:
  return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)
 return 0

WndProc = WNDPROCTYPE(PyWndProcedure)

hInst = windll.kernel32.GetModuleHandleW(0)
print(hInst)

wclassName = 'My Python Win32 Class'

wndClass = WNDCLASSEX()
wndClass.cbSize = sizeof(WNDCLASSEX)
wndClass.style = CS_HREDRAW | CS_VREDRAW
wndClass.lpfnWndProc = WndProc
wndClass.cbClsExtra = 0
wndClass.cbWndExtra = 0
wndClass.hInstance = hInst
wndClass.hIcon = 0
wndClass.hCursor = 0
wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH)
wndClass.lpszMenuName = 0
wndClass.lpszClassName = wclassName
wndClass.hIconSm = 0
print(wndClass)

regRes = windll.user32.RegisterClassExW(byref(wndClass))
print(regRes)

wname = 'My test window'

hWnd = windll.user32.CreateWindowExW(
 0,
 wclassName,
 wname,
 WS_OVERLAPPEDWINDOW | WS_CAPTION,
 CW_USEDEFAULT,
 CW_USEDEFAULT,
 300,
 300,
 0,
 0,
 hInst,
 0)
print('hWnd', hWnd)
if not hWnd:
 print('Failed to create window')
 exit(0)

print('ShowWindow', windll.user32.ShowWindow(hWnd, SW_SHOW))
print('UpdateWindow', windll.user32.UpdateWindow(hWnd))

msg = MSG()
lpmsg = pointer(msg)

print('Entering message loop')
while windll.user32.GetMessageW(lpmsg, 0, 0, 0) != 0:
 windll.user32.TranslateMessage(lpmsg)
 windll.user32.DispatchMessageW(lpmsg)

print('done.')

I just had to change string assignment from
wname = u'My test window'
to
wname = 'My test window'
since in python 3 strings are unicode by default.

Have a nice hacking :)