Jump to content

[Resolved] @Melba23, need help with StringSize()


Recommended Posts

Honored Melba23, I once again beseech you for your assistance, please!

I'm trying to use your wondrous StringSize() sorta in reverse: Given a font, size, weight, etc, what's the max # of characters that will fit in a given pixel width?  Of course I realize that except for mono-spaced fonts, the result will depend on a specific string itself. but I've tried to compromize by submitting a string consisting of a number of the widest character I can think of, the capital "M" (at least for ANSI Latin alphabets).

Here's a simple app I wrote to try it..

#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <Constants.au3>
#include <StaticConstants.au3>
#include <Misc.au3>
#include <String.au3>
#include <StringConstants.au3>
#include <GDIPlus.au3>
#include <GDIPlusConstants.au3>
#include <StructureConstants.au3>
#include <FontConstants.au3>
#include <WinAPI.au3>
#include "StringSize.au3"

Opt("MustDeclareVars", 0)

Const $Cmy_DefaultPathFontName="Franklin Gothic Medium Cond", $Cmy_DefaultPathFontSize="9", $Cmy_DefaultPathFontWeight="400"
Const $Cmy_DefaultPathFontAttrib="0"
Const $Cmy_NicknameFontName="Lucida Console", $Cmy_NicknameFontSize="11", $Cmy_NicknameFontWeight="400"
Const $Cmy_NicknameFontAttrib="2"
Const $Cmy_SlotPathFontCode = 1, $Cmy_SlotNicknameFontCode = 2, $Cmy_MaxBtnPathTxtLen = 90, $Cmy_MaxBtnNickTxtLen = 38

Local $ResultAra[4], $MaxLenResults[4], $ErrFound
Local $FontInfo[4][6] = [ [ "Pathnames in Nickname Slots",  9, 400, 0, "Franklin Gothic Medium Cond", 305], _
                          [ "Nicknames in Nickname Slots", 11, 400, 2, "Lucida Console", 305], _
                          [ "Pathname under Picture",      11, 400, 0, "Gentium Book Basic", 730], _
                          [ "Notify String",               11, 700, 0, "High Tower Text", 500] ]
$ErrFound = False
;
For $i = 0 To 3
    $MaxPixelLenSoFar = 0
    $MaxCharLenSoFar = 1
    $TestStrSoFar = "M"
    $GotMaxChars = False

    While (Not $GotMaxChars) And (Not $ErrFound)
        $ResultAra = _StringSize($TestStrSoFar, $FontInfo[$i][1], $FontInfo[$i][2], $FontInfo[$i][3], $FontInfo[$i][4], $FontInfo[$i][5])
        If @error = 0 Then
            $RequiredPixelWidth = $ResultAra[2]
            If $RequiredPixelWidth < $FontInfo[$i][5] Then          ; If we've still got room...
                $TestStrSoFar &= "M"
                $MaxCharLenSoFar += 1
            Else
                $ResultAra[$i] = $MaxCharLenSoFar
                $GotMaxChars = True
            EndIf
        Else
            MsgBox($MB_OK, "StringSizeMaxTest Error", "Error: _StringSize() @error Returned: " & @error)
            $ErrFound = True
            Exit
        EndIf
    WEnd
Next
;
For $i = 0 To 3
    MsgBox($MB_OK, "StringSizeMaxTest Results", "Max # chars for " & $FontInfo[$i][0] & " == " & $ResultAra[$i] )
Next
;
MsgBox($MB_OK, "StringSizeMaxTest Results", "Press OK when ready")
Exit

What happens is the app always reports error 3: "GetDeviceCaps failure", from StringSize(). What's that all about?

Thanks!

Edited by Mbee
Link to comment
Share on other sites

  • Moderators

Mbee,

Error 3 is not "GetDeviceCaps failure" but something quite different:

Quote

Failure - Returns 0 and sets @error:

3 - Font too large for chosen max width - a word will not fit

which is exactly the error I would expect to see once the string become too long to fit in the defined width.

Let me take a look at the code - although I doubt I have some of those fonts.

M23

Edited by Melba23
Expanded comments

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

  • Moderators

Mbee,

If you get the checking logic correct in the loop the UDF seems to provide sensible results:

#include <Array.au3>
#include "StringSize.au3"

Opt("MustDeclareVars", 0)

Local $ResultAra[4]
Local $FontInfo[4][6] = [["Pathnames in Nickname Slots", 9, 400, 0, "Arial", 305], _
                        ["Nicknames in Nickname Slots", 11, 400, 2, "Lucida Console", 305], _
                        ["Pathname under Picture", 11, 400, 0, "Consolas", 730], _
                        ["Notify String", 11, 700, 0, "Times New Roman", 500]]

For $i = 0 To 3
    $TestStrSoFar = ""
    Do
        $TestStrSoFar &= "M"
        _StringSize($TestStrSoFar, $FontInfo[$i][1], $FontInfo[$i][2], $FontInfo[$i][3], $FontInfo[$i][4], $FontInfo[$i][5])
    Until @error
    $ResultAra[$i] = StringLen($TestStrSoFar) - 1

Next

_ArrayDisplay($ResultAra, "", Default, 8)

The suggested values for max character counts seem perfectly reasonable to me.

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

  • Moderators

Mbee,

Glad I could help.

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

Revised, working code if someone else wants this info...

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

Opt("MustDeclareVars", 0)

Const $Cmy_DefaultPathFontName="Franklin Gothic Medium Cond", $Cmy_DefaultPathFontSize="9", $Cmy_DefaultPathFontWeight="400"
Const $Cmy_DefaultPathFontAttrib="0"
Const $Cmy_NicknameFontName="Lucida Console", $Cmy_NicknameFontSize="11", $Cmy_NicknameFontWeight="400"
Const $Cmy_NicknameFontAttrib="2"
Const $Cmy_SlotPathFontCode = 1, $Cmy_SlotNicknameFontCode = 2, $Cmy_MaxBtnPathTxtLen = 90, $Cmy_MaxBtnNickTxtLen = 38

Local $ResultAra[4], $MaxLenResults[4], $ErrFound
Local $FontInfo[4][6] = [ [ "Pathnames in Nickname Slots",  9, 400, 0, "Franklin Gothic Medium Cond", 305], _
                          [ "Nicknames in Nickname Slots", 11, 400, 2, "Lucida Console", 305], _
                          [ "Pathname under Picture",      11, 400, 0, "Gentium Book Basic", 730], _
                          [ "Notify String",               11, 700, 0, "High Tower Text", 500] ]
$ErrFound = False
;
For $i = 0 To 3
    $MaxPixelLenSoFar = 0
    $MaxCharLenSoFar = 1
    $TestStrSoFar = "M"
    $GotMaxChars = False

    While (Not $GotMaxChars) And (Not $ErrFound)
        $ResultAra = _StringSize($TestStrSoFar, $FontInfo[$i][1], $FontInfo[$i][2], $FontInfo[$i][3], $FontInfo[$i][4], $FontInfo[$i][5])
        If @error = 0 Then
            $RequiredPixelWidth = $ResultAra[2]
            If $RequiredPixelWidth < $FontInfo[$i][5] Then          ; If we've still got room...
                $TestStrSoFar &= "M"
                $MaxCharLenSoFar += 1
            Else
                $MaxLenResults[$i] = $MaxCharLenSoFar
                $GotMaxChars = True
            EndIf
        Else
            If @error = 3 Then
                $MaxLenResults[$i] = $MaxCharLenSoFar
                $GotMaxChars = True
            Else
                MsgBox($MB_OK, "StringSizeMaxTest Error", "Error: _StringSize() @error Returned: " & @error)
                $ErrFound = True
                Exit
            EndIf
        EndIf
    WEnd
Next
;
For $i = 0 To 3
    MsgBox($MB_OK, "StringSizeMaxTest Results", "Max # chars for " & $FontInfo[$i][0] & " = " & $MaxLenResults[$i] )
Next
;
MsgBox($MB_OK, "StringSizeMaxTest Results", "Press OK when ready")
Exit

 

Link to comment
Share on other sites

  • Moderators

Mbee,

Why are you using an even more convoluted mess when I posted a much simpler script which produced exactly the same results?

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

Sorry! The thing is, I personally hate _ArrayDisplay() (just a personal thing, if you will).  How's this?

#include <Array.au3>
#include "StringSize.au3"

Opt("MustDeclareVars", 0)

Const $CMy_NumFontsToTest = 5

Local $ResultAra[$CMy_NumFontsToTest], $DispStr
Local $FontInfo[$CMy_NumFontsToTest][6] = [ _
    ["Pathnames in Nickname Slots", 9, 400, 0, "Franklin Gothic Medium Cond", 305], _
    ["Nicknames in Nickname Slots", 11, 400, 2, "Lucida Console", 305], _
    ["Pathname under Picture", 11, 400, 0, "Gentium Book Basic", 780], _
    ["Notify String", 11, 700, 0, "High Tower Text", 780], _
    ["Profile ID String", 12, 700, 0, "Calibri", 601] ]

For $i = 0 To $CMy_NumFontsToTest -1
    $TestStrSoFar = ""
    Do
        $TestStrSoFar &= "M"
        _StringSize($TestStrSoFar, $FontInfo[$i][1], $FontInfo[$i][2], $FontInfo[$i][3], $FontInfo[$i][4], $FontInfo[$i][5])
    Until @error
    $ResultAra[$i] = StringLen($TestStrSoFar) - 1

Next
;
$DispStr = ""
For $i = 0 To $CMy_NumFontsToTest -1
    $DispStr &= "Max Chars for: " & $FontInfo[$i][0] & " = " & $ResultAra[$i] & @CRLF
Next
;
ClipPut( $DispStr )
MsgBox($MB_SYSTEMMODAL, "StringSizeMaxTest Results", $DispStr )
Exit

 

The last value in each row of the $FontInfo array is set to the width in pixels of the label or other text control I'll be setting whatever text into.  I set those values up and then run this trivial little tool (which saves the results in the clipboard for saving in a text file if wanted) so that I can know the values to pre-set for use in a function that uses your StringSize() func to adjust whatever string I want to put into a given text control to fit into the allotted pixel width.

I use those calculated values to pass as the fourth parameter in that function, which I call _AdjStringToFit(), which follows (the version below is stripped of some basic optimizing code which avoided the loop if AdjStringToFit is called consecutively with the same first arguement):

#include-once
#include "StringSize.au3"

; #INDEX# ============================================================================================================
; Title .........: _AdjStringToFit
; AutoIt Version : v3.2.12.1 or higher
; Language ......: English
; Description ...: Returns a string representing the input string that's adjusted in order to fit into a specified
;                   text field, given the specific width (in pixels) of the desired text field.
; Remarks .......:  If the input string is too long for that given width, it can be prefixed with a string which would indicate
;                   that it has been truncated.  Common options for this prefix are either a drive letter (with initial
;                   backslash) followed by an elipsis (or three period characters) for truncated path strings, or just an elipsis
;                   (or three period characters) for a general purpose truncated string.
; Note ..........:
; Author(s) .....:  MBee - Huge thanks to Melba23 for the StringSize function
; ====================================================================================================================


; #FUNCTION# =========================================================================================================
; Name...........:  _AdjStringToFit
;
; Description ...:  Returns a string representing the input string that's adjusted in order to fit into a specified
;                   text field, given the specific width (in pixels) of the desired text field.
;
; Syntax ........:  _AdjStringToFit($sText, $sPrefix, $iWidth, $iAlwaysFitCCount, $iSize, $iWeight, $iAttrib, $sName )
;
; Parameters ....:  $sText   - Desired string to be optionally adjusted
;                   $sPrefix - Prefix string to insert to indicate the string has been adjusted
;                   $iWidth  - The width in pixels of the intended text field
;                   $iAlwaysFitCCount - The max number of characters that will always fit in the specified field
;                                       i.e., any string with this # chars or fewer will never have to be adjusted
;                   $iSize   - [optional] Font size in points - (default = 8.5)
;                   $iWeight - [optional] Font weight - (default = 400 = normal)
;                   $iAttrib - [optional] Font attribute (0-Normal (default), 2-Italic, 4-Underline, 8 Strike)
;                   $sName   - [optional] Font name - (default = Tahoma)
;
; Requirement(s) :  v3.2.12.1 or higher
;
; Return values .:  Success - The possibly adjusted input string with optional prefix inserted that will fit in the field
;                               @error will be set to 0
;
;                   Failure - Returns null string ("") & @error and @extended from error return from StringSize
;
; Author ........: MBee - Thanks to Melba23 for the StringSize function
; Modified ......:
; Remarks .......:
; Related .......: StringSize()
; Link ..........:
; Example .......: No


Func _AdjStringToFit($arg_TestStr, $arg_Prefix, $arg_FieldSize, $arg_NoAdjCharCount, $arg_FSize=8.5, $arg_FWeight=400, _
                        $arg_FAttrib=0, $arg_FName="Tahoma")

    Local $Lf_ResAra[4], $Lf_WorkStr, $Lf_AdjustedStr, $Lf_WillFit, $Lf_FirstPass, $Lf_TestStrLen=StringLen($arg_TestStr)
;
    $Lf_WorkStr = $arg_TestStr
    $Lf_AdjustedStr = $arg_TestStr
    $Lf_FirstPass = True
    $Lf_WillFit = False                                     ; Assume string is too long to display
    Do
        $Lf_ResAra = _StringSize( $Lf_WorkStr, $arg_FSize, $arg_FWeight, $arg_FAttrib, $arg_FName, $arg_FieldSize )
        If @error = 0 Then
            If StringInStr( $Lf_ResAra[0], @CR ) = 0 Then   ; It'll fit
                $Lf_WillFit = True
                ExitLoop
            EndIf
        Else
            If @error <> 3 Then                             ; If an error other than "string won't fit in field" then
                Return ""                                   ; Pass back Melba23's @error
            EndIf
        EndIf
;
        If $Lf_FirstPass Then
            $Lf_AdjustedStr = StringRight( $Lf_AdjustedStr, StringLen($Lf_AdjustedStr) - (StringLen($arg_Prefix) -1) )
            $Lf_FirstPass = False
        Else
            $Lf_AdjustedStr = StringRight( $Lf_AdjustedStr, StringLen($Lf_AdjustedStr) -1 )
        EndIf
;
        $Lf_WorkStr = $arg_Prefix & $Lf_AdjustedStr
        If $Lf_WorkStr = $arg_Prefix Then               ; Once we've stripped down to nothing but the prefix, give up
            SetError(2, 0)
            Return ""
        EndIf
    Until $Lf_WillFit
;
    SetError(0, 0)
    Return $Lf_WorkStr
EndFunc

I followed the traditional naming conventions in the function headers, but followed my own preferred naming conventions in the actual code (Inot to criticize the traditional AutoIt standards, but I've been using my naming conventions for a very long time, and since AutoIt is wonderfully not a strongly-typed programming language, prefixing variable names with the variable type seems a bit needless when this can be as well accomplished in the later parts of the variable names... Just one man's personal opinion...)

As always, I am willing to accept criticism and/or suggestions for improvements.

Edited by Mbee
Re-inserted critical missing code line
Link to comment
Share on other sites

  • Moderators

Mbee,

That looks a lot cleaner.

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

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

×
×
  • Create New...