Jump to content

[SOLVED] Measure String Size


Recommended Posts

I'm using Prospeed to do some on-screen rendering. In order to center text, I need to know the rendered width/height of the text, so have been looking at the _WinAPI_GetTextExtentPoint32 function, but I'm not getting it to work. What am I doing wrong?

#include <WinAPI.au3>
#include <FontConstants.au3>

$hDC = _WinAPI_GetDC(0)
ConsoleWrite("hdc: " & $hDC & @CRLF)

$hFont = _WinAPI_CreateFont(42, 800, 0, 0, $FW_NORMAL, False, False, False, _
        $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Arial')
_WinAPI_SetFont($hDC, $hFont)
ConsoleWrite("fonth: " & $hFont & @CRLF)

$sText = "This is a string"
$foo = _WinAPI_GetTextExtentPoint32($hDC, $sText)
If Not IsArray($foo) Then
    ConsoleWrite($foo & @CRLF)
Else
    ConsoleWrite($foo[0] & @TAB & $foo[1] & @CRLF)
EndIf
Edited by mlowery
Link to comment
Share on other sites

  • Moderators

mlowery,

This is how I do it (with a lot of help from trancexx :P ).

I prefer to use DllCall rather than the WinAPI UDF so you can replace quite a few of the calls if you so wish: :blink:

$aSize = Sizer("This is a string", 42, 800, 0, "Arial")
MsgBox(0, "Size", "Width = " & $aSize[0] & @CRLF & "Height = " & $aSize[1])

Func Sizer($sText, $iSize = 8.5, $iWeight = 400, $iAttrib = 0, $sName = "")

    ; Get default DC
    $aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", 0)
    If @error Or $aRet[0] = 0 Then Return SetError(1, 1, 0)
    $hDC = $aRet[0]
    ; Create required font
    $aRet = DllCall("gdi32.dll", "int", "GetDeviceCaps", "handle", $hDC, "int", 90) ; $LOGPIXELSY
    If @error Or $aRet[0] = 0 Then
        DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
        Return SetError(1, 2, 0)
    EndIf
    Local $iInfo = $aRet[0]
    $aRet = DllCall("gdi32.dll", "handle", "CreateFontW", "int", -$iInfo * $iSize / 72, "int", 0, "int", 0, "int", 0, _
            "int", $iWeight, "dword", BitAND($iAttrib, 2), "dword", BitAND($iAttrib, 4), "dword", BitAND($iAttrib, 8), "dword", 0, "dword", 0, _
            "dword", 0, "dword", 5, "dword", 0, "wstr", $sName)
    If @error Or $aRet[0] = 0 Then
        DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
        Return SetError(1, 3, 0)
    EndIf
    $hFont = $aRet[0]

    ; Select font and store previous font
    $aRet = DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hFont)
    If @error Or $aRet[0] = 0 Then Return SetError(1, 4, 0)
    Local $hPrevFont = $aRet[0]

    ; Declare and fill Size structure
    Local $tSize = DllStructCreate("int X;int Y"), $aSize[2]
    DllStructSetData($tSize, "X", 0)
    DllStructSetData($tSize, "Y", 0)

    ; Size line
    $iLine_Length = StringLen($sText)
    DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sText, "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
    If @error Then
        DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont)
        DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
        Return SetError(1, 5, 0)
    EndIf
    $aSize[0] = DllStructGetData($tSize, "X")
    $aSize[1] = DllStructGetData($tSize, "Y")

    ; Clean up
    DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hPrevFont)
    DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont)
    DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)

    Return $aSize

EndFunc

I hope it helps. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thanks heaps!

You put me on the right track with the DllStruct* items. Apparently, it's necessary to read the result from the example I posted by using DllStructGetData. It's really not documented or shown in the help or examples.

I needed:

$foo = _WinAPI_GetTextExtentPoint32($hDC, $sText)
$x = DllStructGetData($foo,"X")
$y = DllStructGetData($foo,"Y")
ConsoleWrite($x & @TAB & $y & @CRLF)

I also had to use _WinAPI_SelectObject($hDC, $hFont) instead of _WinAPI_SetFont($hDC, $hFont), but it looks like things are working now!

Edited by mlowery
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...