Created
January 31, 2012 21:50
-
-
Save jasonbot/1713202 to your computer and use it in GitHub Desktop.
Get the width and height (in inches) of a string using the Win32 CTypes APIs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ctypes | |
import ctypes.wintypes | |
class Constants(object): | |
"Container for constants found in win32 headers" | |
WS_OVERLAPPED = 0x00000000L | |
WS_POPUP = 0x80000000L | |
WS_CHILD = 0x40000000L | |
WS_MINIMIZE = 0x20000000L | |
WS_VISIBLE = 0x10000000L | |
WS_DISABLED = 0x08000000L | |
WS_CLIPSIBLINGS = 0x04000000L | |
WS_CLIPCHILDREN = 0x02000000L | |
WS_MAXIMIZE = 0x01000000L | |
WS_CAPTION = 0x00C00000L | |
WS_BORDER = 0x00800000L | |
WS_DLGFRAME = 0x00400000L | |
WS_VSCROLL = 0x00200000L | |
WS_HSCROLL = 0x00100000L | |
WS_SYSMENU = 0x00080000L | |
WS_THICKFRAME = 0x00040000L | |
WS_GROUP = 0x00020000L | |
WS_TABSTOP = 0x00010000L | |
WS_MINIMIZEBOX = 0x00020000L | |
WS_MAXIMIZEBOX = 0x00010000L | |
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | | |
WS_CAPTION | | |
WS_SYSMENU | | |
WS_THICKFRAME | | |
WS_MINIMIZEBOX | | |
WS_MAXIMIZEBOX) | |
SM_XVIRTUALSCREEN = 76 | |
SM_YVIRTUALSCREEN = 77 | |
SM_CXVIRTUALSCREEN = 78 | |
SM_CYVIRTUALSCREEN = 79 | |
SM_CMONITORS = 80 | |
SM_SAMEDISPLAYFORMAT = 81 | |
ANSI_CHARSET = 0 | |
DEFAULT_CHARSET = 1 | |
OUT_DEFAULT_PRECIS = 0x00000000 | |
OUT_STRING_PRECIS = 0x00000001 | |
OUT_STROKE_PRECIS = 0x00000003 | |
OUT_TT_PRECIS = 0x00000004 | |
OUT_DEVICE_PRECIS = 0x00000005 | |
OUT_RASTER_PRECIS = 0x00000006 | |
OUT_TT_ONLY_PRECIS = 0x00000007 | |
OUT_OUTLINE_PRECIS = 0x00000008 | |
OUT_SCREEN_OUTLINE_PRECIS = 0x00000009 | |
OUT_PS_ONLY_PRECIS = 0x0000000A | |
LOGPIXELSX = 88 | |
LOGPIXELSY = 90 | |
class SIZE(ctypes.Structure): | |
_fields_ = [("cx", ctypes.c_long), | |
("cy", ctypes.c_long)] | |
ctypes.windll.user32.CreateWindowExA.restype = ctypes.wintypes.HWND | |
ctypes.windll.user32.GetDC.restype = ctypes.wintypes.HDC | |
ctypes.windll.gdi32.CreateFontA.argtypes = [ctypes.c_int, | |
ctypes.c_int, | |
ctypes.c_int, | |
ctypes.c_int, | |
ctypes.c_int, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.DWORD, | |
ctypes.wintypes.LPCSTR] | |
ctypes.windll.gdi32.CreateFontA.restype = ctypes.wintypes.HFONT | |
ctypes.windll.gdi32.SelectObject.argtypes = [ctypes.wintypes.HDC, ctypes.wintypes.HANDLE] | |
class FontMetrics(object): | |
def __init__(self): | |
self.hwnd = ctypes.windll.user32.CreateWindowExA(0, | |
"STATIC", | |
"", | |
Constants.WS_OVERLAPPEDWINDOW, | |
ctypes.windll.user32.GetSystemMetrics(Constants.SM_CXVIRTUALSCREEN), | |
ctypes.windll.user32.GetSystemMetrics(Constants.SM_CYVIRTUALSCREEN), | |
640, 480, 0, 0, 0, 0) | |
def __del__(self): | |
if ctypes: | |
ctypes.windll.user32.DestroyWindow(self.hwnd) | |
def get_dimensions(self, text, fontname, fontsize): | |
hdc = ctypes.windll.user32.GetDC(self.hwnd) | |
#print "HDC:", hdc | |
fontheight = -ctypes.windll.kernel32.MulDiv(fontsize, | |
ctypes.windll.gdi32.GetDeviceCaps(hdc, | |
Constants.LOGPIXELSY), | |
72) | |
#print "Size:", fontsize, "Height:", fontheight | |
fontheight = fontsize | |
hfont = ctypes.windll.gdi32.CreateFontA(fontheight, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
fontname) | |
#print "FONT", hfont | |
ctypes.windll.gdi32.SelectObject(hdc, hfont) | |
size = Constants.SIZE(0, 0) | |
ctypes.windll.gdi32.GetTextExtentPoint32A(hdc, text, len(text), ctypes.byref(size)) | |
dpix = ctypes.windll.gdi32.GetDeviceCaps(hdc, Constants.LOGPIXELSX) | |
dpiy = ctypes.windll.gdi32.GetDeviceCaps(hdc, Constants.LOGPIXELSY) | |
ctypes.windll.gdi32.DeleteObject(hfont) | |
ctypes.windll.user32.ReleaseDC(self.hwnd, hdc) | |
return (float(size.cx) / dpix, float(size.cy) / dpiy) | |
if __name__ == "__main__": | |
fm = FontMetrics() | |
for size in range(10, 40): | |
for text in ("Helol", "wghsg", "245 245245245 245 245 245"): | |
print "String", repr(text), "at", size, "pt" | |
for font in ("Arial", "Consolas", "Calibri", "Fixedsys"): | |
print "In", font, "dimensions are", fm.get_dimensions(text, font, size) | |
print '--' | |
del fm |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment