I'm trying to use GDI+ (via ctypes) to draw text.
It works for some fonts but messes up with others.
Using Times, for example, it seems to be using the
glyphs for one character earlier in the code sequence,
so that "Times" comes out as "Shldr" -- except that it
uses the widths of the original characters for positioning.
Can someone please run the attached code and tell me
whether it works for them or not? And any ideas on what
I could be doing wrong to cause this?
--
Greg
import os, traceback
from ctypes import *
from ctypes.wintypes import *
gdiplus = windll.gdiplus
SW_HIDE = 0
SW_SHOW = 5
GWL_WNDPROC = -4
GWL_STYLE = -16
CS_VREDRAW = 0x0001
CS_HREDRAW = 0x0002
CS_GLOBALCLASS = 0x4000
WS_OVERLAPPEDWINDOW = 13565952
WS_VISIBLE = 0x1000
WS_SYSMENU = 0x0008
WM_QUIT = 0x0012
WM_PAINT = 0x000f
WM_CLOSE = 0x0010
LF_FACESIZE = 32
WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)
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 PAINTSTRUCT(Structure):
_fields_ = [
('hdc', c_int),
('fErase', c_int),
('rcPaint', RECT),
('fRestore', c_int),
('fIncUpdate', c_int),
('rgbReserved', c_char * 32),
]
lo_byte = lambda x : x & 0xff
hi_byte = lambda x : x >> 8 & 0xff
lo_word = lambda x : x & 0x
hi_word = lambda x : x >> 16 & 0x
class RectF(Structure):
_fields_ = [
('x', c_float),
('y', c_float),
('w', c_float),
('h',c_float),
]
class LOGFONT(Structure):
_fields_ = [
('lfHeight', c_long),
('lfWidth', c_long),
('lfEscapement', c_long),
('lfOrientation', c_long),
('lfWeight', c_long),
('lfItalic', c_byte),
('lfUnderline', c_byte),
('lfStrikeOut', c_byte),
('lfCharSet', c_byte),
('lfOutPrecision', c_byte),
('lfClipPrecision', c_byte),
('lfQuality', c_byte),
('lfPitchAndFamily', c_byte),
('lfFaceName', c_char * LF_FACESIZE),
]
def __init__(self):
self.lfHeight, self.lfWidth = 10, 10
self.lfEscapement = 10
self.lfOrientation = 0
self.lfUnderline = 0
self.lfStrikeOut = 0
self.lfCharSet = 0 # ANSI_CHARSET
self.lfPitchAndFamily = 0
self.lfOutPrecision = 0
self.lfClipPrecision = 0
self.lfQuality = 0
self.lfPitchAndFamily = 2
class GdiplusStartupInput(Structure):
_fields_ = [
('GdiplusVersion', c_uint),
('DebugEventCallback', c_void_p),
('SuppressBackgroundThread', BOOL),
('SuppressExternalCodecs', BOOL),
]
def __init__(self):
Structure.__init__(self)
self.GdiplusVersion = 1
self.DebugEventCallback = None
self.SuppressBackgroundThread = 0
self.SuppressExternalCodecs = 0
StartupInput = GdiplusStartupInput()
token = c_ulong()
gdiplus.GdiplusStartup(pointer(token), pointer(StartupInput), None)
class Font(object):
def __init__(self, family, size = 12, style = []):
logfont = LOGFONT()
logfont.lfFaceName = family
logfont.lfHeight = -size
logfont.lfWidth = 0
if 'italic' in style:
logfont.lfItalic = 1
else:
logfont.lfItalic = 0
if 'bold' in style:
logfont.lfWeight = 10
else:
logfont.lfWeight = 0
self._size = size
self._win32_object =
windll.gdi32.CreateFontIndirectA(byref(logfont))
self._free_object = True
self._family = family # should came elsewhere
class Canvas(object):
def __init__(self, hdc):
self._hdc = hdc
self._GpGraphics = c_void_p()
gdiplus.GdipCreateFromHDC(hdc, byref(self._GpGraphics))
self._GpFont = c_void_p()
self._GpBrush = c_void_p()
gdiplus.GdipCreateSolidFill(0xff00, byref(self._GpBrush))
print "Canvas: brush =", self._GpBrush.value ###
self._GpPen = c_void_p()