Jump to content

get the size of a string in pixels?


Recommended Posts

Is there a way to get the size of a string in pixels? I want to put a string into a label, but I want to know if it will fit. If not, I want to trim it and add "..." to the end of it.

I know this depends on the font settings, but I know I had a way to do it in VB5/VB6, I just don't remember how I coded it, and I can't find my code.

Link to comment
Share on other sites

Might wish to look up GetTextExtentPoint32() on MSDN. I think it may be useful in determing this sort of thing. I've not tested it yet, but I think the general flow of how it works would be:

  • Create the control.
  • Get the controls HWND.
  • Use (API) function GetDC() to get the device context for the control.
  • Use GetTextExtentPoint32() on the HDC obtained.
  • Release the DC.
There's a small structure involved as well as several DllCall()'s.

I mostly see this function used with DrawText() and TextOut() but I see no reason why it won't work for calculating label sizes, too.

Link to comment
Share on other sites

  • 9 months later...

Has anybody found an easy answer to this? I'm trying to create a gui based on the size of a string and this is whats stopping me.

Mine just doesn't cut it each time.

#include <GUIConstants.au3>
#Include <GuiListView.au3>

Dim $List = '', $item[100],$intPrinters = 1,$OldStringlength = 1,$StringNumber = ''

GUICreate("Select Printers:",200,250, 0,0)

$objWMIService = ObjGet("winmgmts:\\" & @ComputerName & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery ('SELECT * FROM Win32_Printer')

Dim $String[100]
;~ $intPrinters = 1
For $objItem In $colItems
    $String[$intPrinters] = $objItem.DeviceID & ' on ' & $objItem.PortName
    $StringLength = Stringlen($String[$intPrinters])
    If $StringLength > $OldStringlength Then 
        $OldStringlength = $StringLength
        $StringNumber = $intPrinters
    EndIf
;~  If $intPrinters = 1 Then; Setup Controls
;~      $item[$intPrinters]=GUICtrlCreateCheckbox($String,10,10,$OldStringlength * 5,20)
;~  Else
;~      $item[$intPrinters]=GUICtrlCreateCheckbox($String,10,$intPrinters*20 - 10,$OldStringlength * 5,20)
;~  EndIf
    $intPrinters = $intPrinters + 1
Next
$intPrinters = $intPrinters - 1
For $i = 1 To $intPrinters
    $font="Courier"
    $item[$i]=GUICtrlCreateCheckbox($String[$i],10,$i*20 - 10,$OldStringlength * 9,20)
    GUICtrlSetFont (-1,9, 400, 0, $font) 
Next

$Current_Window_Pos = WinGetPos("Select Printers:",'')
$Cont_Pos = ControlGetPos("Select Printers:",'',$item[$StringNumber])

WinMove("Select Printers:",'',$Current_Window_Pos[0],$Current_Window_Pos[1],$Cont_Pos[2],$intPrinters * 25)
GUISetState()
Do
    $msg = GUIGetMsg ()
    Sleep(25)
Until $msg = $GUI_EVENT_CLOSE

EDIT: Would GUICtrlSetLimit be adaptable to this? Also is it possible to darken the text in a disabled Input control?

Edited by strate
INI TreeViewA bus station is where a bus stops, a train station is where a train stops. Onmy desk I have a work station...
Link to comment
Share on other sites

  • 1 month later...

I'm having a problem getting anything to return from this:

$DC = DllCall('user32.dll','hwnd','GetDC','Hwnd',$ControlHwnd)
;~  $DC = DllCall('user32.dll','hwnd','GetDC','Hwnd',$WinHwnd)
    MsgBox(0,$DC,"Good so far")
The rest of the script will follow, please do not mind some of the trash i used for debuggin it lol.
#include <GuiConstants.au3>

$Text = 'Victory!'
$Label_1 = ''
$stDIM = ''

Func GetTextDimensions()
    $ControlHwnd = ControlGetHandle ( "Test", "", $Label_1 )
;~  $WinHwnd = WinGetHandle ( "Test", "")
;~  MsgBox(0,$ControlHwnd,"Good so far");
;~  MsgBox(0,$WinHwnd,"Good so far");
    
    $DC = DllCall('user32.dll','hwnd','GetDC','Hwnd',$ControlHwnd)
;~  $DC = DllCall('user32.dll','hwnd','GetDC','Hwnd',$WinHwnd)
    MsgBox(0,$DC,"Good so far");
    
    $stDIM = DllStructCreate("int;int")
    if @error Then
        MsgBox(0,"","Error in DllStructCreate " & @error);
        exit
    endif
    
    DllCall('gdi32.dll','ptr','GetTextExtentPoint32','HWnd',$DC,'str',$Text,'int',StringLen($Text),'ptr',DllStructGetPtr($stDIM))
    if @error = 1 Or @error = 2 Or @error = 3 Then
        MsgBox(0,"","Error in DllCall " & @error);
        exit
    endif
EndFunc

$Hwnd = GuiCreate("Test", 392, 316,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))
$Label_1 = GuiCtrlCreateLabel($Text, 100, 120, 120, 20)
GuiSetState()
While 1
    $msg = GuiGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
        ExitLoop
    EndSelect
WEnd



GetTextDimensions()

$W = DllStructGetData($stDIM,1)
$H = DllStructGetData($stDIM,2)

$stDIM = 0;free the struct

msgbox(0,"","Major: " & $W & @CRLF & "Minor: " & $H)

Exit
It's a bunch of code from the help file smashed together. I'm trying to learn dll's but so far no luck.....

INI TreeViewA bus station is where a bus stops, a train station is where a train stops. Onmy desk I have a work station...
Link to comment
Share on other sites

Wouldn't it be easier to just use a fixed width font?

An example of a fixed pitch font is Courier 12 pitch, which is a 10 point font that will print at exactly 12 characters per inch.

72 DPI (Dots Per Inch) Monitor = 72 Pixels per inch
:D

Note: There are many fixed width fonts - some are even pretty! (see here for examples)

Regards,

Link to comment
Share on other sites

Wouldn't it be easier to just use a fixed width font?

72 DPI (Dots Per Inch) Monitor = 72 Pixels per inch
:D

Note: There are many fixed width fonts - some are even pretty! (see here for examples)

Regards,

Yes, it would be easier, I'm already using fixed width. To be quite honest though they look retarded. And would like to use some thing like this instead.
INI TreeViewA bus station is where a bus stops, a train station is where a train stops. Onmy desk I have a work station...
Link to comment
Share on other sites

I wrote this UDF myself. It might help.

Func _GetTextLabelWidth($s_WinText, $s_TextFont, $i_FontSize, $i_FontWeight = -1)
    Local Const $DEFAULT_CHARSET = 0 ; ANSI character set
    Local Const $OUT_CHARACTER_PRECIS = 2
    Local Const $CLIP_DEFAULT_PRECIS = 0
    Local Const $PROOF_QUALITY = 2
    Local Const $FIXED_PITCH = 1
    Local Const $RGN_XOR = 3
    Local Const $LOGPIXELSY = 90


    $h_WinTitle = "Get Label Width"
    If $i_FontWeight = "" Or $i_FontWeight = -1 Then $i_FontWeight = 600 ; default Font weight
    Local $h_GUI = GUICreate($h_WinTitle, 10, 10, -100, -100, $WS_POPUPWINDOW, $WS_EX_TOOLWINDOW)
    Local $hDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $h_GUI)

    Local $intDeviceCap = DllCall("gdi32.dll", "long", "GetDeviceCaps", "int", $hDC[0], "long", $LOGPIXELSY)
    $intDeviceCap = $intDeviceCap[0]

    Local $intFontHeight = DllCall("kernel32.dll", "long", "MulDiv", "long", $i_FontSize, "long", $intDeviceCap, "long", 72)
    $intFontHeight = -$intFontHeight[0]

    Local $hMyFont = DllCall("gdi32.dll", "hwnd", "CreateFont", "int", $intFontHeight, _
            "int", 0, "int", 0, "int", 0, "int", $i_FontWeight, "int", 0, _
            "int", 0, "int", 0, "int", $DEFAULT_CHARSET, _
            "int", $OUT_CHARACTER_PRECIS, "int", $CLIP_DEFAULT_PRECIS, _
            "int", $PROOF_QUALITY, "int", $FIXED_PITCH, "str", $s_TextFont)
    DllCall("gdi32.dll", "hwnd", "SelectObject", "int", $hDC[0], "hwnd", $hMyFont[0])

    Local $res = DllStructCreate("int;int")

    Local $ret = DllCall("gdi32.dll", "int", "GetTextExtentPoint32", "int", $hDC[0], "str", $s_WinText, "long", StringLen($s_WinText), "ptr", DllStructGetPtr($res))

    Local $intLabelWidth = DllStructGetData($res,1)

    GUIDelete($h_GUI)
    Return $intLabelWidth
EndFunc
Link to comment
Share on other sites

I wrote this UDF myself. It might help.

Wow, nice work! I'm trying to see how it functions...

#include <GUIConstants.au3>

$int = _GetTextLabelWidth("hello this is a slightly long caption", "Courier", 10)

$form1 = GUICreate("test", $int, 50, -1, -1)
$lbl = GuiCtrlCreateLabel("hello this is a slightly long caption", 0,0,$int, 48, -1, -1)
GuiCtrlSetFont($lbl, 10, -1, -1, "Courier")
GuiSetState(@SW_SHOW)
While 1
    $msg=GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            Exitloop
    EndSelect
WEnd
Exit

The code does not seem to produce a well-sized label, and the $int value seems to be the culprit. I did a rough manual measurement of the text using the AutoIt Window info tool, and $int was about 50 pixels > than the pixel length of the text.

Perhaps I'm misunderstanding the function.

Anyways, this deserves to go in Scripts and Scraps when completed.

Link to comment
Share on other sites

  • 10 months later...

The problem might be with the font weight. Try explicitly setting it to 600 in both _GetTextLabelWidth and GuiCtrlSetFont.

I made some changes to this code and I am now getting some near perfect results. My changes are simple based on what I learned here http://allapi.mentalis.org/apilist/CreateFont.shtml. I changed the default font weight to normal and I am now using default character set and default out precision with these drop-in changes to _GetTextLabelWidth:

Local Const $ANSI_CHARSET = 0

Local Const $DEFAULT_CHARSET = 1

Local Const $OUT_CHARACTER_PRECIS = 2

Local Const $OUT_DEFAULT_PRECIS = 0

If $i_FontWeight = "" Or $i_FontWeight = -1 Then $i_FontWeight = 400 ; default Font weight

Local $hMyFont = DllCall("gdi32.dll", "hwnd", "CreateFont", "int", $intFontHeight, _

"int", 0, "int", 0, "int", 0, "int", $i_FontWeight, "int", 0, _

"int", 0, "int", 0, "int", $DEFAULT_CHARSET, _

"int", $OUT_DEFAULT_PRECIS, "int", $CLIP_DEFAULT_PRECIS, _

"int", $PROOF_QUALITY, "int", $FIXED_PITCH, "str", $s_TextFont)

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...