New:
New method to get the required font into the Display Context for sizing via GetTextExtentPoint32W. Default code (by trancexx
) or you can add the handle of your GUI to use that font directly.
The UDF did not correctly recognise TAB characters and so undersized lines containing them. Adding 1 to the $iAttrib paramter will expand tabs to "XXXXXXXX" before sizing the text. This might mean that the returned size is slightly too wide, but at least the line will fit! See the ExtMsgBox thread for an example showing this. ![]()
One or two minor code changes (improvements I hope!).
Note that that these are non-scriptbreaking changes - unless you need to expand tabs you use StringSize just as before. I realise the use of $iAttrib to pass the "expand tab" is less that ideal, but it does prevent using another parameter.New UDF and new examples below and in zip.
19 Jun 10: Minor code change. Thanks Mat
Amended version posted 20 May 2010: - Error returns now correct
I just realised that although I have posted versions of this UDF many times in Help topics, I had never actually posted a "final" version here in Example scripts - better late than never, I suppose!
StringSize takes a text string and calculates the size of label required to hold it as well as formatting the string to fit.
Now AutoIt will, of course, size a label automatically to fit a text string, but it will not format the string in any way - what you use as the string is what you get in the label. If you do set any label sizes the text will be wrapped, but you can only determine the correct size of the label by trial and error.
StringSize will, however, reformat the string to fit in a given width and tell you the required height so that you can read it all - whatever the font type or size - and you do not have to do the formatting beforehand.
Here is a simple example to show what I mean (you need the UDF in the same folder for all the examples):
Spoiler
AutoIt
#include <GUIConstantsEx.au3> #include "StringSize.au3" $sText = " I am a very long line and I am not formatted in any way so that I will not fit within the width of the GUI that surrounds me!" $hGUI = GUICreate("Test", 500, 500) ; A label with no width or height set GUICtrlCreateLabel($sText, 10, 10) GUICtrlSetBkColor(-1, 0xFF8080) ; A label with no height set GUICtrlCreateLabel($sText, 10, 50, 200) GUICtrlSetBkColor(-1, 0xC0C0FF) ; A label sized by StringSize $aSize = _StringSize($sText, Default, Default, Default, "", 200) GUICtrlCreateLabel($aSize[0], 10, 90, $aSize[2], $aSize[3]) GUICtrlSetBkColor(-1, 0x80FF80) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd
And here is an example showing how StringSize can deal with different fonts and text sizes:
Spoiler
AutoIt
#include <GUIConstantsEx.au3> #include "StringSize.au3" Global $aFont[4] = ["Arial", "Tahoma", "Courier New", "Comic Sans MS"] Global $aSize[4] = [9, 12, 10, 15] Global $aWeight[4] = [200, 400, 600, 800] Global $aAttrib[4] = [0, 2, 4, 0] Global $aMaxWidth[4] = [250, 300, 400, 500] Global $aColour[4] = [0xFFFF88, 0xBBFF88, 0xBB88FF, 0xFF88FF] Global $aButMsg[4] = ["Press for next example", "Click here", "Please push", "And the next one please..."] $sLabelMsg = "This is a message with very long lines which are unlikely to fit within a GUI of a specified maximum width. " & _ "This UDF will return the size of rectangle needed to display the message in a selected font and size." & @CRLF & @CRLF & _ "The GUI can then be sized to fit and accurately placed on screen. Other controls, such as the automatically " & _ "sized button under this label, can also be accurately positioned relative to the text." $hGUI = GUICreate("String Sizing Test", 500, 500) $hLabel = GUICtrlCreateLabel("", 10, 10, -1, -1, 1) $hNext = GUICtrlCreateButton("", 210, 460, 80, 30) GUISetState(@SW_HIDE) While 1 $sFont = $aFont[Random(0, 3, 1)] $iSize = $aSize[Random(0, 3, 1)] $iWeight = $aWeight[Random(0, 3, 1)] $iAttrib = $aAttrib[Random(0, 3, 1)] $iMaxWidth = Random(200, 850, 1) $iColour = $aColour[Random(0, 3, 1)] $sButMsg = $aButMsg[Random(0, 3, 1)] $aButReturn = _StringSize($sButMsg) $aMsgReturn = _StringSize($sLabelMsg, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth) $iError = @error If IsArray($aMsgReturn) = 1 Then WinMove("String Sizing Test", "", (@DesktopWidth - ($aMsgReturn[2] + 25)) / 2, (@DesktopHeight - ($aMsgReturn[3] + 85)) / 2, $aMsgReturn[2] + 25, $aMsgReturn[3] + 85 ) GUISetState(@SW_SHOW, $hGUI) ControlMove($hGUI, "", $hLabel, 10, 10, $aMsgReturn[2], $aMsgReturn[3]) GUICtrlSetData($hLabel, $aMsgReturn[0]) GUICtrlSetFont($hLabel, $iSize, $iWeight, $iAttrib, $sFont) GUICtrlSetBkColor($hLabel, $iColour) ControlMove($hGUI, "", $hNext, ($aMsgReturn[2] - $aButReturn[2]) / 2, $aMsgReturn[3] + 20, $aButReturn[2] + 20, 30) GUICtrlSetData($hNext, $aButReturn[0]) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $hNext ExitLoop EndSwitch WEnd Else MsgBox(0, "Error", "Code = " & $iError) EndIf WEnd
You can see that the GUI is perfectly sized each time and that the button is always the right size and in the right place. StringSize returns an array which contains the formatted text to display and the size of the label needed to display it. All you need to do is to use the array elements when you create your label. Try changing the values in $aFont and $aSize if you want to try you own favourites - but beware, StringSize will return an error if you make the size so large that it cannot fit a word into the label width.
NEW A more complex example showing how formatted and unformatted text can be sized correctly. The width of GUI holding the unformatted text varies randomly in width (the current value is displayed at top right):
Spoiler
AutoIt
; SizeString Test New ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include <GUIConstantsEx.au3> #Include <GuiStatusBar.au3> #include "StringSize.au3" ; Declare arrays to hold parameters Global $aFont[4] = ["Arial", "Tahoma", "Courier New", "Comic Sans MS"] Global $aSize[4] = [9, 12, 10, 15] Global $aWeight[4] = [200, 400, 600, 800] Global $aAttrib[4] = [0, 2, 4, 0] Global $aMaxWidth[4] = [250, 300, 400, 500] Global $aColour[4] = [0xFFFFD0, 0xD0FFD0, 0xD0D0FF, 0xFFD0FF] Global $aButMsg[4] = ["Press for next example", "Click here", "Please push", "And the next one please..."] ; Declare preformatted and unformatted strings $FormatMsg = _ "This is a pre-formatted message with lines of pre-set " & @CRLF & _ "lengths which will not be wrapped. The UDF will " & @CRLF & _ "return the size of rectangle needed to display it " & @CRLF & _ "in a selected font and size." & @CRLF & @CRLF & _ "The GUI can then be sized to fit and accurately placed " & @CRLF & _ "on screen. Other controls, such as the automatically " & @CRLF & _ "sized button under this label, can also be accurately " & @CRLF & _ "positioned relative to the text." $UnformatMsg = _ "This is an unformatted message with 2 very long lines which are unlikely to fit within the maximum width specified. The UDF will return the size of rectangle needed to display it in a selected font and size." & @CRLF & @CRLF & _ "The GUI can then be sized to fit and accurately placed on screen. Other controls, such as the automatically sized button under this label, can also be accurately positioned relative to the text." ; Create GUI $hGUI = GUICreate("SizeString Test", 500, 500) ; Create radios to select mode of UDF GUIStartGroup() $hRadio_Pre = GUICtrlCreateRadio(" Preformatted", 10, 5, 85, 20) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlSetResizing(-1, $GUI_DOCKALL) $hRadio_Un = GUICtrlCreateRadio(" Unformatted", 95, 5, 85, 20) GUICtrlSetResizing(-1, $GUI_DOCKALL) GUIStartGroup() $hWidth_Label = GUICtrlCreateLabel("W:900", 460, 8, 40, 20) GUICtrlSetResizing(-1, $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKHEIGHT + $GUI_DOCKWIDTH) ; Create and hide status bar Local $aStatus_Parts[4] = [20, 50, 120, -1] Global $hStatus_Bar = _GUICtrlStatusBar_Create($hGUI, $aStatus_Parts) Global $iStatus_Depth = _GUICtrlStatusBar_GetHeight($hStatus_Bar) + 5 _GUICtrlStatusBar_ShowHide($hStatus_Bar, @SW_SHOW) GUISetState() While 1 ; Choose parameter values $sFont = $aFont[Random(0, 3, 1)] $iSize = $aSize[Random(0, 3, 1)] $iWeight = $aWeight[Random(0, 3, 1)] $iAttrib = $aAttrib[Random(0, 3, 1)] $iMaxWidth = 10 * Random(20, 85, 1) $iColour = $aColour[Random(0, 3, 1)] $sButMsg = $aButMsg[Random(0, 3, 1)] ; Run UDF, $aButReturn = _StringSize($sButMsg) If GUICtrlRead($hRadio_Pre) = 1 Then $aMsgReturn = _StringSize($FormatMsg, $iSize, $iWeight, $iAttrib, $sFont) Else $aMsgReturn = _StringSize($UnformatMsg, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth) EndIf $iError = @error ; If no error If IsArray($aMsgReturn) = 1 Then ; Size GUI as required WinMove($hGUI, "", (@DesktopWidth - ($aMsgReturn[2] + 25)) / 2, (@DesktopHeight - ($aMsgReturn[3] + 105)) / 2, $aMsgReturn[2] + 25, $aMsgReturn[3] + 105 + $iStatus_Depth) ; Resize and fill status bar _GUICtrlStatusBar_Resize ($hStatus_Bar) _GUICtrlStatusBar_SetText($hStatus_Bar, $iSize, 0) _GUICtrlStatusBar_SetText($hStatus_Bar, $iWeight, 1) $sAttrib = "Normal" Switch $iAttrib Case 2 $sAttrib = "Italic" Case 4 $sAttrib = "Underline" EndSwitch _GUICtrlStatusBar_SetText($hStatus_Bar, $sAttrib, 2) _GUICtrlStatusBar_SetText($hStatus_Bar, $sFont, 3) If GUICtrlRead($hRadio_Un) = 1 Then GUICtrlSetData($hWidth_Label, "W:" & $iMaxWidth); _GUICtrlStatusBar_SetText($hStatus_Bar, $iMaxWidth & " wide", 4) Else GUICtrlSetData($hWidth_Label, "");_GUICtrlStatusBar_SetText($hStatus_Bar, "", 4) EndIf ; Create correctly sized label to fit text $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 10, 30, $aMsgReturn[2], $aMsgReturn[3], 1) GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont) GUICtrlSetBkColor(-1, $iColour) ; Create correctly sized and positioned button $hNext = GUICtrlCreateButton($sButMsg, ($aMsgReturn[2] - $aButReturn[2]) / 2, $aMsgReturn[3] + 40, $aButReturn[2] + 20, 30) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $hNext, $hRadio_Pre, $hRadio_Un ExitLoop EndSwitch WEnd ; Delete label and button GUICtrlDelete($hNext) GUICtrlDelete($hLabel) Else MsgBox(0, "Error", "Code = " & $iError) EndIf WEnd
NEW And a final example showing how you can get your text in the largest possible font to fit in a given space:
Spoiler
AutoIt
#include <GUIConstantsEx.au3> #include "StringSize.au3" ; Declare arrays to hold parameters Global $aFont[4] = ["Arial", "Tahoma", "Courier New", "Comic Sans MS"] Global $aWeight[4] = [200, 400, 600, 800] Global $aAttrib[4] = [0, 2, 4, 0] Global $aColour[4] = [0xFFFFD0, 0xD0FFD0, 0xD0D0FF, 0xFFD0FF] $sText = "The UDF will calculate the largest possible font size which will allow this text to fit in the randomly sized label. " & _ "Pressing the 'Increase' button will use the next size up so you can see how successful it was. " & @CRLF & _ "Note that the UDF is pessimistic and will leave small borders to the right and at the bottom of the text, so you might " & _ "be able to go one size up in a few cases, although this risks clipping the trailing edges of italic letters or the tails of letters such as 'g'." $hGUI = GUICreate("Test", 500, 500, 100, 100) $hButton_Next = GUICtrlCreateButton("Next", 10, 10, 80, 30) GUICtrlSetResizing(-1, $GUI_DOCKALL) $hLabel_Size = GUICtrlCreateLabel("", 100, 10, 40, 30) GUICtrlSetResizing(-1, $GUI_DOCKALL) GUICtrlSetFont(-1, 24) $hButton_Increase = GUICtrlCreateButton("Increase", 150, 10, 80, 30) GUICtrlSetResizing(-1, $GUI_DOCKALL) GUISetState() While 1 ; Choose parameter values $iX = 10 * Random(25, 50, 1) $iY = 10 * Random(10, 40, 1) $sFont = $aFont[Random(0, 3, 1)] $iWeight = $aWeight[Random(0, 3, 1)] $iAttrib = $aAttrib[Random(0, 3, 1)] $iColour = $aColour[Random(0, 3, 1)] WinMove($hGUI, "", 100, 100, $iX + 26, $iY + 85) $hLabel = GUICtrlCreateLabel("", 10, 50, $iX, $iY) GUICtrlSetBkColor(-1, $iColour) For $iSize = 5 To 50 $aSize = _StringSize($sText, $iSize, $iWeight, $iAttrib, $sFont, $iX) If $aSize[3] > $iY Then $iSize -= 1 ExitLoop EndIf Next GUICtrlSetData($hLabel_Size, $iSize) GUICtrlSetFont($hLabel, $iSize, $iWeight, $iAttrib, $sFont) $aSize = _StringSize($sText, $iSize, $iWeight, $iAttrib, $sFont, $iX) GUICtrlSetData($hLabel, $aSize[0]) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $hButton_Next GUICtrlDelete($hLabel) GUICtrlSetData($hLabel_Size, "") ExitLoop Case $hButton_Increase GUICtrlSetData($hLabel, "") $iSize += 1 GUICtrlSetData($hLabel_Size, $iSize) GUICtrlSetFont($hLabel, $iSize, $iWeight, $iAttrib, $sFont) $aSize = _StringSize($sText, $iSize, $iWeight, $iAttrib, $sFont, $iX) GUICtrlSetData($hLabel, $aSize[0]) EndSwitch WEnd WEnd
NEW Finally here is the UDF itself:
Spoiler
AutoIt
#include-once ; #INDEX# ============================================================================================================ ; Title .........: _StringSize ; AutoIt Version : v3.2.12.1 or higher ; Language ......: English ; Description ...: Returns size of rectangle required to display string - maximum width can be chosen ; Remarks .......: ; Note ..........: ; Author(s) .....: Melba23 - thanks to trancexx for the default DC code ; ==================================================================================================================== ;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 ; #CURRENT# ========================================================================================================== ; _StringSize: Returns size of rectangle required to display string - maximum width can be chosen ; ==================================================================================================================== ; #INTERNAL_USE_ONLY#================================================================================================= ; _StringSize_Error_Close: Releases DC and deletes font object after error ; _StringSize_DefaultFontName: Determines Windows default font ; ==================================================================================================================== ; #FUNCTION# ========================================================================================================= ; Name...........: _StringSize ; Description ...: Returns size of rectangle required to display string - maximum permitted width can be chosen ; Syntax ........: _StringSize($sText[, $iSize[, $iWeight[, $iAttrib[, $sName[, $iWidth[, $hWnd]]]]]]) ; Parameters ....: $sText - String to display ; $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) ; + 1 if tabs are to be expanded before sizing ; $sName - [optional] Font name - (default = Tahoma) ; $iWidth - [optional] Max width for rectangle - (default = 0 => width of original string) ; $hWnd - [optional] GUI in which string will be displayed - (default 0 => normally not required) ; Requirement(s) : v3.2.12.1 or higher ; Return values .: Success - Returns 4-element array: ($iWidth set // $iWidth not set) ; |$array[0] = String reformatted with additonal @CRLF // Original string ; |$array[1] = Height of single line in selected font // idem ; |$array[2] = Width of rectangle required for reformatted // original string ; |$array[3] = Height of rectangle required for reformatted // original string ; Failure - Returns 0 and sets @error: ; |1 - Incorrect parameter type (@extended = parameter index) ; |2 - DLL call error - extended set as follows: ; |1 - GetDC failure ; |2 - SendMessage failure ; |3 - GetDeviceCaps failure ; |4 - CreateFont failure ; |5 - SelectObject failure ; |6 - GetTextExtentPoint32 failure ; |3 - Font too large for chosen max width - a word will not fit ; Author ........: Melba23 - thanks to trancexx for the default DC code ; Modified ......: ; Remarks .......: The use of the $hWnd parameter is not normally necessary - it is only required if the UDF does not ; return correct dimensions without it. ; Related .......: ; Link ..........: ; Example .......: Yes ;===================================================================================================================== Func _StringSize($sText, $iSize = 8.5, $iWeight = 400, $iAttrib = 0, $sName = "", $iMaxWidth = 0, $hWnd = 0) ; Set parameters passed as Default If $iSize = Default Then $iSize = 8.5 If $iWeight = Default Then $iWeight = 400 If $iAttrib = Default Then $iAttrib = 0 If $sName = "" Or $sName = Default Then $sName = _StringSize_DefaultFontName() ; Check parameters are correct type If Not IsString($sText) Then Return SetError(1, 1, 0) If Not IsNumber($iSize) Then Return SetError(1, 2, 0) If Not IsInt($iWeight) Then Return SetError(1, 3, 0) If Not IsInt($iAttrib) Then Return SetError(1, 4, 0) If Not IsString($sName) Then Return SetError(1, 5, 0) If Not IsNumber($iMaxWidth) Then Return SetError(1, 6, 0) If Not IsHwnd($hWnd) And $hWnd <> 0 Then Return SetError(1, 7, 0) Local $aRet, $hDC, $hFont, $hLabel = 0, $hLabel_Handle ; Check for tab expansion flag Local $iExpTab = BitAnd($iAttrib, 1) ; Remove possible tab expansion flag from font attribute value $iAttrib = BitAnd($iAttrib, BitNot(1)) ; If GUI handle was passed If IsHWnd($hWnd) Then ; Create label outside GUI borders $hLabel = GUICtrlCreateLabel("", -10, -10, 10, 10) $hLabel_Handle = GUICtrlGetHandle(-1) GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sName) ; Create DC $aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hLabel_Handle) If @error Or $aRet[0] = 0 Then GUICtrlDelete($hLabel) Return SetError(2, 1, 0) EndIf $hDC = $aRet[0] $aRet = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hLabel_Handle, "int", 0x0031, "wparam", 0, "lparam", 0) ; $WM_GetFont If @error Or $aRet[0] = 0 Then GUICtrlDelete($hLabel) Return SetError(2, _StringSize_Error_Close(2, $hDC), 0) EndIf $hFont = $aRet[0] Else ; Get default DC $aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hWnd) If @error Or $aRet[0] = 0 Then Return SetError(2, 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 Return SetError(2, _StringSize_Error_Close(3, $hDC), 0) 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 Return SetError(2, _StringSize_Error_Close(4, $hDC), 0) $hFont = $aRet[0] EndIf ; 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(2, _StringSize_Error_Close(5, $hDC, $hFont, $hLabel), 0) Local $hPrevFont = $aRet[0] ; Declare variables Local $avSize_Info[4], $iLine_Length, $iLine_Height = 0, $iLine_Count = 0, $iLine_Width = 0, $iWrap_Count, $iLast_Word, $sTest_Line ; Declare and fill Size structure Local $tSize = DllStructCreate("int X;int Y") DllStructSetData($tSize, "X", 0) DllStructSetData($tSize, "Y", 0) ; Ensure EoL is @CRLF and break text into lines $sText = StringRegExpReplace($sText, "((?<!\x0d)\x0a|\x0d(?!\x0a))", @CRLF) Local $asLines = StringSplit($sText, @CRLF, 1) ; For each line For $i = 1 To $asLines[0] ; Expand tabs if required If $iExpTab Then $asLines[$i] = StringReplace($asLines[$i], @TAB, " XXXXXXXX") EndIf ; Size line $iLine_Length = StringLen($asLines[$i]) DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $asLines[$i], "int", $iLine_Length, "ptr", DllStructGetPtr($tSize)) If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0) If DllStructGetData($tSize, "X") > $iLine_Width Then $iLine_Width = DllStructGetData($tSize, "X") If DllStructGetData($tSize, "Y") > $iLine_Height Then $iLine_Height = DllStructGetData($tSize, "Y") Next ; Check if $iMaxWidth has been both set and exceeded If $iMaxWidth <> 0 And $iLine_Width > $iMaxWidth Then ; Wrapping required ; For each Line For $j = 1 To $asLines[0] ; Size line unwrapped $iLine_Length = StringLen($asLines[$j]) DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $asLines[$j], "int", $iLine_Length, "ptr", DllStructGetPtr($tSize)) If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0) ; Check wrap status If DllStructGetData($tSize, "X") < $iMaxWidth - 4 Then ; No wrap needed so count line and store $iLine_Count += 1 $avSize_Info[0] &= $asLines[$j] & @CRLF Else ; Wrap needed so zero counter for wrapped lines $iWrap_Count = 0 ; Build line to max width While 1 ; Zero line width $iLine_Width = 0 ; Initialise pointer for end of word $iLast_Word = 0 ; Add characters until EOL or maximum width reached For $i = 1 To StringLen($asLines[$j]) ; Is this just past a word ending? If StringMid($asLines[$j], $i, 1) = " " Then $iLast_Word = $i - 1 ; Increase line by one character $sTest_Line = StringMid($asLines[$j], 1, $i) ; Get line length $iLine_Length = StringLen($sTest_Line) DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sTest_Line, "int", $iLine_Length, "ptr", DllStructGetPtr($tSize)) If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0) $iLine_Width = DllStructGetData($tSize, "X") ; If too long exit the loop If $iLine_Width >= $iMaxWidth - 4 Then ExitLoop Next ; End of the line of text? If $i > StringLen($asLines[$j]) Then ; Yes, so add final line to count $iWrap_Count += 1 ; Store line $avSize_Info[0] &= $sTest_Line & @CRLF ExitLoop Else ; No, but add line just completed to count $iWrap_Count += 1 ; Check at least 1 word completed or return error If $iLast_Word = 0 Then Return SetError(3, _StringSize_Error_Close(0, $hDC, $hFont, $hLabel), 0) ; Store line up to end of last word $avSize_Info[0] &= StringLeft($sTest_Line, $iLast_Word) & @CRLF ; Strip string to point reached $asLines[$j] = StringTrimLeft($asLines[$j], $iLast_Word) ; Trim leading whitespace $asLines[$j] = StringStripWS($asLines[$j], 1) ; Repeat with remaining characters in line EndIf WEnd ; Add the number of wrapped lines to the count $iLine_Count += $iWrap_Count EndIf Next ; Reset any tab expansions If $iExpTab Then $avSize_Info[0] = StringRegExpReplace($avSize_Info[0], "\x20?XXXXXXXX", @TAB) EndIf ; Complete return array $avSize_Info[1] = $iLine_Height $avSize_Info[2] = $iMaxWidth ; Convert lines to pixels and add drop margin $avSize_Info[3] = ($iLine_Count * $iLine_Height) + 4 Else ; No wrapping required ; Create return array (add drop margin to height) Local $avSize_Info[4] = [$sText, $iLine_Height, $iLine_Width, ($asLines[0] * $iLine_Height) + 4] EndIf ; Clear 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) If $hLabel Then GUICtrlDelete($hLabel) Return $avSize_Info EndFunc ;==>_StringSize ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _StringSize_Error_Close ; Description ...: Releases DC and deleted font object if required after error ; Syntax ........: _StringSize_Error_Close ($iExtCode, $hDC, $hGUI) ; Parameters ....: $iExtCode - code to return ; $hDC, $hGUI - handles as set in _StringSize function ; Return value ..: $iExtCode as passed ; Author ........: Melba23 ; Modified.......: ; Remarks .......: This function is used internally by _StringSize ; =============================================================================================================================== Func _StringSize_Error_Close($iExtCode, $hDC = 0, $hFont = 0, $hLabel = 0) If $hFont <> 0 Then DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont) If $hDC <> 0 Then DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC) If $hLabel Then GUICtrlDelete($hLabel) Return $iExtCode EndFunc ;=>_StringSize_Error_Close ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _StringSize_DefaultFontName ; Description ...: Determines Windows default font ; Syntax ........: _StringSize_DefaultFontName() ; Parameters ....: None ; Return values .: Success - Returns name of system default font ; Failure - Returns "Tahoma" ; Author ........: Melba23, based on some original code by Larrydalooza ; Modified.......: ; Remarks .......: This function is used internally by _StringSize ; =============================================================================================================================== Func _StringSize_DefaultFontName() ; Get default system font data Local $tNONCLIENTMETRICS = DllStructCreate("uint;int;int;int;int;int;byte[60];int;int;byte[60];int;int;byte[60];byte[60];byte[60]") DLLStructSetData($tNONCLIENTMETRICS, 1, DllStructGetSize($tNONCLIENTMETRICS)) DLLCall("user32.dll", "int", "SystemParametersInfo", "int", 41, "int", DllStructGetSize($tNONCLIENTMETRICS), "ptr", DllStructGetPtr($tNONCLIENTMETRICS), "int", 0) Local $tLOGFONT = DllStructCreate("long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;char[32]", DLLStructGetPtr($tNONCLIENTMETRICS, 13)) If IsString(DllStructGetData($tLOGFONT, 14)) Then Return DllStructGetData($tLOGFONT, 14) Else Return "Tahoma" EndIf EndFunc ;=>_StringSize_DefaultFontName
NEW And all 5 files in zip format:
StringSize.zip 8.2K
1635 downloadsI hope you find this useful - I certainly do.
M23
Edited by Melba23, 16 August 2011 - 12:45 PM.







