Code: Select all
;* Startup:
DllCall("Kernel32\LoadLibrary", "Str", "Gdiplus")
VarSetCapacity(input, 8 + A_PtrSize*2)
, NumPut(0x1, &input + 0, "UInt")
if (status := DllCall("Gdiplus\GdiplusStartup", "Ptr*", pToken := 0, "Ptr", &input, "Ptr", 0, "Int")) {
throw (Exception(FormatStatus(status)))
}
;* Create a Graphics object:
if (status := DllCall("Gdiplus\GdipCreateBitmapFromScan0", "UInt", 50, "UInt", 50, "UInt", 0, "UInt", 0x26200A, "Ptr", 0, "Ptr*", pBitmap := 0, "Int")) {
throw (Exception(FormatStatus(status)))
}
if (status := DllCall("Gdiplus\GdipGetImageGraphicsContext", "Ptr", pBitmap, "Ptr*", pGraphics := 0, "Int")) {
throw (Exception(FormatStatus(status)))
}
;* Create a Font object:
fontName := "Fira Code Retina"
if (status := DllCall("Gdiplus\GdipCreateFontFamilyFromName", "Ptr", &fontName, "Ptr", 0, "Ptr*", pFontFamily := 0, "Int")) {
throw (Exception(FormatStatus(status)))
}
;* Create a StringFormat object:
if (status := DllCall("Gdiplus\GdipCreateStringFormat", "UInt", 0, "UInt", 0, "Ptr*", pStringFormat := 0, "Int")) {
throw (Exception(FormatStatus(status)))
}
/*
;* enum FontStyle ;: https://docs.microsoft.com/en-us/windows/win32/api/gdiplusenums/ne-gdiplusenums-fontstyle
0 = FontStyleRegular
1 = FontStyleBold
2 = FontStyleItalic
3 = FontStyleBoldItalic
4 = FontStyleUnderline
8 = FontStyleStrikeout
*/
fontStyle := 1
, string := "String"
lineWidth := 500, lineHeight := 16
VarSetCapacity(layoutRect, 16), NumPut(0, &layoutRect + 0, "Float"), NumPut(0, &layoutRect + 4, "Float"), NumPut(lineWidth, &layoutRect + 8, "Float"), NumPut(lineHeight, &layoutRect + 12, "Float")
VarSetCapacity(boundingBox, 16)
loop {
fontSize := A_Index
if (status := DllCall("Gdiplus\GdipCreateFont", "Ptr", pFontFamily, "Float", fontSize, "Int", fontStyle, "UInt", 2, "Ptr*", pFont := 0, "Int")) {
throw (Exception(FormatStatus(status)))
}
DllCall("Gdiplus\GdipMeasureString", "Ptr", pGraphics, "Str", string, "Int", -1, "Ptr", pFont, "Ptr", &layoutRect, "Ptr", pStringFormat, "Ptr", &boundingBox, "UInt*", chars := 0, "UInt*", lines := 0)
DllCall("Gdiplus\GdipDeleteFont", "Ptr", pFont)
} until (NumGet(&boundingBox + 8, "Float") >= lineWidth || NumGet(&boundingBox + 12, "Float") >= lineHeight)
;* Clean up objects:
DllCall("Gdiplus\GdipDeleteStringFormat", "Ptr", pStringFormat)
DllCall("Gdiplus\GdipDeleteFontFamily", "Ptr", pFontFamily)
DllCall("Gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
DllCall("Gdiplus\GdipDisposeImage", "Ptr", pBitmap)
;* Shutdown:
DllCall("Gdiplus\GdiplusShutdown", "Ptr", pToken)
DllCall("Kernel32\FreeLibrary", "Ptr", DllCall("Kernel32\GetModuleHandle", "Str", "Gdiplus", "Ptr"), "UInt")
MsgBox, % "Limit = " . fontSize - 1 . " (" . NumGet(&boundingBox + 0, "Float") . ", " . NumGet(&boundingBox + 4, "Float") . ", " . NumGet(&boundingBox + 8, "Float") . ", " NumGet(&boundingBox + 12, "Float") . ")"
exit
;* FormatStatus(status)
FormatStatus(status) {
Local
Static statusLookup := {"1": "GenericError", "2": "InvalidParameter", "3": "OutOfMemory", "4": "ObjectBusy", "5": "InsufficientBuffer", "6": "NotImplemented", "7": "Win32Error", "8": "WrongState", "9": "Aborted", "10": "FileNotFound", "11": "ValueOverflow", "12": "AccessDenied", "13": "UnknownImageFormat", "14": "FontFamilyNotFound", "15": "FontStyleNotFound", "16": "NotTrueTypeFont", "17": "UnsupportedGdiplusVersion", "18": "GdiplusNotInitialized", "19": "PropertyNotFound", "20": "PropertyNotSupported", "21": "ProfileNotFound"} ;: https://docs.microsoft.com/en-us/windows/win32/api/gdiplustypes/ne-gdiplustypes-status
return (statusLookup[status])
}