NassauSky Posted July 10, 2020 Share Posted July 10, 2020 (edited) Hi all, Given font size & font name, how might I find the width of a character with autoit code? There are some example of finding string width's in this forum but I can't find a way to find the character width of a single character. For example if I want to find the width of the letter "M" at font size 700 & using the font "Gill Sans Ultra Bold", with the following VBA script we result in 981 pixel width. 'Option Explicit 'API Declares Private Declare Function CreateDC Lib "gdi32.dll" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData As Long) As Long Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long Private Declare Function CreateFontIndirect Lib "gdi32.dll" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long Private Declare Function GetTextExtentPoint32 Lib "gdi32.dll" Alias "GetTextExtentPoint32A" (ByVal hdc As Long, ByVal lpsz As String, ByVal cbString As Long, lpSize As SIZE) As Long Private Declare Function MulDiv Lib "kernel32.dll" (ByVal nNumber As Long, ByVal nNumerator As Long, ByVal nDenominator As Long) As Long Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long Private Const LOGPIXELSY As Long = 90 Private Type LOGFONT lfHeight As Long lfWidth As Long lfEscapement As Long lfOrientation As Long lfWeight As Long lfItalic As Byte lfUnderline As Byte lfStrikeOut As Byte lfCharSet As Byte lfOutPrecision As Byte lfClipPrecision As Byte lfQuality As Byte lfPitchAndFamily As Byte lfFaceName As String * 32 End Type Private Type SIZE cx As Long cy As Long End Type Public Function getLabelPixel(label As String) As Integer Dim font As New StdFont Dim sz As SIZE font.Name = "Gill Sans Ultra Bold" font.SIZE = 700 sz = GetLabelSize(label, font) getLabelPixel = sz.cx End Function Private Function GetLabelSize(text As String, font As StdFont) As SIZE Dim tempDC As Long Dim tempBMP As Long Dim f As Long Dim lf As LOGFONT Dim textSize As SIZE ' Create a device context and a bitmap that can be used to store a ' temporary font object tempDC = CreateDC("DISPLAY", vbNullString, vbNullString, ByVal 0) tempBMP = CreateCompatibleBitmap(tempDC, 1, 1) ' Assign the bitmap to the device context DeleteObject SelectObject(tempDC, tempBMP) ' Set up the LOGFONT structure and create the font lf.lfFaceName = font.Name & Chr$(0) lf.lfHeight = -MulDiv(font.SIZE, GetDeviceCaps(GetDC(0), 90), 72) 'LOGPIXELSY lf.lfItalic = font.Italic lf.lfStrikeOut = font.StrikeThrough lf.lfUnderline = font.Underline If font.Bold Then lf.lfWeight = 800 Else lf.lfWeight = 400 f = CreateFontIndirect(lf) ' Assign the font to the device context DeleteObject SelectObject(tempDC, f) ' Measure the text, and return it into the textSize SIZE structure GetTextExtentPoint32 tempDC, text, Len(text), textSize ' Clean up (very important to avoid memory leaks!) DeleteObject f DeleteObject tempBMP DeleteDC tempDC ' Return the measurements GetLabelSize = textSize End Function Sub TestMe() Pixels = getLabelPixel("M") MsgBox ("Width Pixels: " & Pixels) MsgBox ("Width Inches: " & (Pixels / 72)) End Sub I'm not looking to create a GUI to measure the character width. I just need the width of a single given character. 🙂 Thanks Edited July 10, 2020 by NassauSky Clarification that I don't want to create a GUI Link to comment Share on other sites More sharing options...
UEZ Posted July 10, 2020 Share Posted July 10, 2020 (edited) Try this: #include <WinAPIGdiDC.au3> Const $LOGPIXELSY = 90 Func getLabelPixel($label, $fontname = "Gill Sans Ultra Bold", $fontsize = 700, $italic = 0, $underline = 0, $bold = 0) Local $tempDC = _WinAPI_CreateCompatibleDC(0) Local $tempBMP = _WinAPI_CreateCompatibleBitmap($tempDC, 1, 1) Local $hOld1 = _WinAPI_SelectObject($tempDC, $tempBMP) Local $lf = DllStructCreate($tagLOGFONT) $lf.FaceName = $fontname $lf.Height = -($fontsize * _WinAPI_GetDeviceCaps($tempDC, $LOGPIXELSY) / 72) $lf.Italic = $italic $lf.Underline = $underline $lf.Weight = ($bold ? 800 : 400) Local $hFont = _WinAPI_CreateFontIndirect($lf) Local $hOld2 = _WinAPI_SelectObject($tempDC, $hFont) Local $textSize = _WinAPI_GetTextExtentPoint32($tempDC, $label) _WinAPI_SelectObject($tempDC, $hOld1) _WinAPI_SelectObject($tempDC, $hOld2) _WinAPI_ReleaseDC(0, $tempDC) _WinAPI_DeleteObject($hFont) _WinAPI_DeleteObject($tempBMP) Return $textSize EndFunc Global $Pixels = getLabelPixel("M") MsgBox(0, "Test", "Width Pixels: " & $Pixels.x) Edited July 10, 2020 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted July 11, 2020 Moderators Share Posted July 11, 2020 NassauSky, You could try my StringSize UDF - the link is in my sig. I do not have that particular font, but the width value returned seems very similar when using other fonts. #include <MsgBoxConstants.au3> #include "StringSize.au3" $aRet = _StringSize("M", 700, Default, Default, "Gill Sans Ultra Bold") MsgBox($MB_SYSTEMMODAL, "Width", $aRet[2]) M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
NassauSky Posted July 14, 2020 Author Share Posted July 14, 2020 That's awesome! @UEZ how did you whip that up so fast :-) @Melba23 sometimes I wish these UDF's jumped up and slapped me in the face before all that searching. Thanks to both of you and they both work! Oh I love options. Thanks again!!! Mike Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now