2

I been trying to create Win32 Application by using python (2.7) and ctypes module. Window is created and shown but title of window gets truncated. I got 'M' instead of 'My test window'. What I am doing wrong?

Thanks in advance

P.S. Here follows the code and screenshot:

enter image description here

# -*- coding: utf-8 -*-
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.DefWindowProcA(hWnd, Msg, wParam, lParam)
    return 0

WndProc = WNDPROCTYPE(PyWndProcedure)

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

wclassName = u'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 = u'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.GetMessageA(lpmsg, 0, 0, 0) != 0:
    windll.user32.TranslateMessage(lpmsg)
    windll.user32.DispatchMessageA(lpmsg)

print('done.')
Darius Kucinskas
  • 10,193
  • 12
  • 57
  • 79
  • Maybe this working example using win32gui.CreateWindow can give you a hint: http://stackoverflow.com/questions/5353883/python3-ctype-createwindowex-simple-example/5355663#5355663 – alexandrul Mar 22 '11 at 09:33

2 Answers2

5

It is because you are creating a Unicode window with CreateWindowExW but then calling the ANSI DefWindowProcA. You are passing Unicode strings which typically have zero for every other byte since your text is in the ASCII range which explains what you observe.

The solution? Call DefWindowProcW instead.

Actually, a better solution would be to use win32gui instead which wraps this up a bit more for you.

cdonts
  • 9,304
  • 4
  • 46
  • 72
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

If you provide a regular string rather than an unicode string, the text is displayed properly.

wname = 'My test window'

It looks strange to me because you are using the Unicode API (CreateWindowExW). Maybe the root cause is somewhere else.

I hope it helps

luc
  • 41,928
  • 25
  • 127
  • 172