Yashied Posted May 28, 2012 Share Posted May 28, 2012 (edited) Many people on the forum wrote a functions to calculate the dimensions of a string, but I have not found a solution if the string contains one or more tab characters (at best, replaced @TAB by 4 or more other characters). All use the GetTextExtentPoint32() function, but there is GetTabbedTextExtent() that supports the tabbed strings. There's only one problem using it in AutoIt. We need to specify the tab-stop positions in pixels (see "nTabPositions" and "lpnTabStopPositions" parameters). If it is incorrect then the result will be wrong. The value of tab-stop position should be strictly the same that use AutoIt to draw the tabbed strings. But the difficulty is that this value depends on the typeface and size of the used font. After some experimentation, I came to the conclusion that the value of tab-stop position can be calculated as follows: 8 * TEXTMETRIC("tmAveCharWidth")So, the following function returns the dimensions of a tabbed or non-tabbed string. Moreover, the string can contain carriage returns (@CR or @CRLF). Additionally, you can align the string through a tab characters to display it as a table in the Label control (see screenshot). I tested the example which is shown below with a few fonts and it works fine. expandcollapse popup#Include <GUIConstants.au3> #Include <WindowsConstants.au3> Opt('MouseCoordMode', 2) Global $Text = '#1' & @TAB & '0B7' & @TAB & '#2' & @TAB & '01F' & @TAB & '#3' & @TAB & '2FF' & @TAB & '#4' & @TAB & '077' & @CRLF & _ 'COMPRESS_COPY' & @TAB & '+' & @TAB & 'PREFIX_PLATFORM' & @TAB & '+' & @TAB & 'TEST' & @TAB & '+' & @TAB & 'WIN7_PROGRESSBAR' & @TAB & '+' & @CRLF & _ 'COMPRESS_BCJ' & @TAB & '+' & @TAB & 'PREFIX_WAITALL' & @TAB & '+' & @TAB & 'LANG' & @TAB & '+' & @TAB & 'RTF_CONTROL' & @TAB & '+' & @CRLF & _ 'COMPRESS_BCJ2' & @TAB & '+' & @TAB & 'PREFIX_HIDCON' & @TAB & '+' & @TAB & 'ELEVATION' & @TAB & '+' & @TAB & 'IMAGES' & @TAB & '+' & @CRLF & _ 'COMPRESS_DEFLATE' & @TAB & '-' & @TAB & 'PREFIX_NOWAIT' & @TAB & '+' & @TAB & 'CHECK_RAM' & @TAB & '+' & @CRLF & _ 'COMPRESS_LZMA' & @TAB & '+' & @TAB & 'PREFIX_FORCENOWAIT' & @TAB & '+' & @TAB & 'CHECK_FREE_SPACE' & @TAB & '+' & @CRLF & _ 'COMPRESS_LZMA2' & @TAB & '+' & @TAB & '' & @TAB & '' & @TAB & 'BEGINPROMPTTIMEOUT' & @TAB & '+' & @CRLF & _ 'COMPRESS_PPMD' & @TAB & '-' & @TAB & '' & @TAB & '' & @TAB & 'CONFIG_PLATFORM' & @TAB & '+' & @CRLF & _ 'CRYPTO' & @TAB & '+' & @TAB & '' & @TAB & '' & @TAB & 'EARLY_PASSWORD' & @TAB & '+' & @CRLF & _ 'VOLUMES' & @TAB & '-' & @TAB & '' & @TAB & '' & @TAB & 'VOLUME_NAME_STYLE' & @TAB & '-' & @CRLF & _ 'PROTECT' & @TAB & '-' & @TAB & '' & @TAB & '' & @TAB & 'ENVIRONMENT_VARS' & @TAB & '+' Global $Font[20] = [1.5, 2.3, 3.0, 3.8, 4.5, 5.3, 6.0, 6.8, 7.5, 8.3, 9.0, 9.8, 10.5, 11.3, 12.0, 12.8, 13.5, 14.3, 15.0, 15.8] For $i = 0 To UBound($Font) - 1 _Form($Text, 'Segoe UI', $Font[$i]) Next Func _Form($sText, $sFont, $nFont) Local $hForm, $Button, $Pos, $Size $hForm = GUICreate(StringFormat('%s - %.1f', $sFont, $nFont), 0, 0) GUISetFont(9.0, 400, 0, 'Segoe UI') GUISetBkColor(0xF0F0F0) GUICtrlCreateLabel('', 10, 10) GUICtrlSetFont(-1, $nFont, 400, 0, $sFont) GUICtrlSetBkColor(-1, 0xFFFFFF) $Size = _GetTabbedStringSizeEx(-1, $sText, 1) If Not @Error Then GUICtrlSetPos(-1, -1, -1, $Size[0], $Size[1]) GUICtrlSetData(-1, $sText) EndIf $Pos = WinGetPos($hForm) WinMove($hForm, '', (@DesktopWidth - ($Pos[2] + $Size[0] + 20)) / 2, (@DesktopHeight - ($Pos[3] + $Size[1] + 70)) / 2, $Pos[2] + $Size[0] + 20, $Pos[3] + $Size[1] + 70) GUICtrlCreateGraphic(0, 0, $Size[0] + 20, $Size[1] + 20) GUICtrlSetBkColor(-1, 0xFFFFFF) GUICtrlSetState(-1, $GUI_DISABLE) GUICtrlCreateGraphic(0, $Size[1] + 20, $Size[0] + 20, 1) GUICtrlSetBkColor(-1, 0xDFDFDF) GUICtrlSetState(-1, $GUI_DISABLE) $Button = GUICtrlCreateButton('OK', ($Size[0] + 20) / 2 - 37, $Size[1] + 32, 88, 27) GUICtrlSetState(-1, BitOR($GUI_DEFBUTTON, $GUI_FOCUS)) GUISetState() MouseMove(($Size[0] + 20) / 2 + 7, $Size[1] + 46, 0) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $Button ExitLoop EndSwitch WEnd GUIDelete($hForm) EndFunc ;==>_Form Func _GetTabbedStringSizeEx($CtrlID, ByRef $sString, $fAlignment = False) Local $W = 0, $H, $tTM, $pTM, $hDC = 0, $hSv = 0, $aTemp, $aSize, $aData, $aTabs, $aText, $sText = '', $Error, $Tab, $Ret Local $tTM = DllStructCreate('long;long;long;long;long;long;long;long;long;long;long;wchar;wchar;wchar;wchar;byte;byte;byte;byte;byte') ;~ Local $tTM = DllStructCreate($tagTEXTMETRIC) Local $pTM = DllStructGetPtr($tTM) Local $tData = DllStructCreate('long;long') Local $pData = DllStructGetPtr($tData) Local $aResult[2] = [0, 0] If Not IsHWnd($CtrlID) Then $CtrlID = GUICtrlGetHandle($CtrlID) If Not $CtrlID Then Return SetError(1, 0, 0) EndIf EndIf Do $Error = 1 $Ret = DllCall('user32.dll', 'ptr', 'GetDC', 'hwnd', $CtrlID) If (@Error) Or (Not $Ret[0]) Then ExitLoop EndIf $hDC = $Ret[0] $Ret = DllCall('user32.dll', 'ptr', 'SendMessageW', 'hwnd', $CtrlID, 'uint', 0x0031, 'wparam', 0, 'lparam', 0) If (@Error) Or (Not $Ret[0]) Then ExitLoop EndIf $Ret = DllCall('gdi32.dll', 'ptr', 'SelectObject', 'hwnd', $hDC, 'ptr', $Ret[0]) If (@Error) Or (Not $Ret[0]) Then ExitLoop EndIf $hSv = $Ret[0] $Ret = DllCall('gdi32.dll', 'int', 'GetTextMetricsW', 'hwnd', $hDC, 'ptr', $pTM) If (@Error) Or (Not $Ret[0]) Then ExitLoop EndIf $Tab = 8 * DllStructGetData($tTM, 6) If Not $Tab Then ExitLoop EndIf $aData = StringSplit(StringReplace($sString, @CRLF, @CR), @CR, 2) $H = UBound($aData) If ($H > 1) And ($fAlignment) Then For $i = 0 To $H - 1 $aTemp = StringSplit($aData[$i], @TAB) If $W < $aTemp[0] Then $W = $aTemp[0] EndIf Next Dim $aText[$H][$W] Dim $aSize[$H][$W] For $i = 0 To $H - 1 $aTemp = StringSplit($aData[$i], @TAB) For $j = 0 To $W - 1 Select Case $aTemp[0] < $j + 1 $aText[$i][$j] = 0 $aSize[$i][$j] = -1 Case $aTemp[0] = $j + 1 $aText[$i][$j] = $aTemp[$j + 1] $aSize[$i][$j] = -1 Case Else $aText[$i][$j] = $aTemp[$j + 1] $Ret = DllCall('gdi32.dll', 'int', 'GetTextExtentPoint32W', 'hwnd', $hDC, 'wstr', $aTemp[$j + 1], 'int', StringLen($aTemp[$j + 1]), 'ptr', $pData) If (Not @Error) And ($Ret[0]) Then $aSize[$i][$j] = DllStructGetData($tData, 1) Else $aSize[$i][$j] = 0 EndIf EndSelect Next Next Dim $aTabs[$W] For $j = 0 To $W - 1 $aTabs[$j] = 1 For $i = 0 To $H - 1 If $aSize[$i][$j] <> -1 Then If $aSize[$i][$j] < $Tab Then $aSize[$i][$j] = 1 Else $aSize[$i][$j] = Floor($aSize[$i][$j] / $Tab) + 1 If $aTabs[$j] < $aSize[$i][$j] Then $aTabs[$j] = $aSize[$i][$j] EndIf EndIf EndIf Next Next Dim $aData[$H] For $i = 0 To $H - 1 $aData[$i] = '' For $j = 0 To $W - 1 If IsString($aText[$i][$j]) Then $aData[$i] &= $aText[$i][$j] If $aSize[$i][$j] <> -1 Then $aSize[$i][$j] = $aTabs[$j] - $aSize[$i][$j] EndIf For $k = 1 To $aSize[$i][$j] + 1 $aData[$i] &= @TAB Next Else ExitLoop EndIf Next $sText &= $aData[$i] & @CRLF Next EndIf $Error = 1 DllStructSetData($tData, 1, $Tab) For $i = 0 To $H - 1 $Ret = DllCall('user32.dll', 'dword', 'GetTabbedTextExtentW', 'hwnd', $hDC, 'wstr', $aData[$i], 'int', StringLen($aData[$i]), 'int', 1, 'ptr', $pData) If (Not @Error) And ($Ret[0]) Then $aResult[1] += BitShift($Ret[0], 16) $Ret = BitAND($Ret[0], 0xFFFF) If $aResult[0] < $Ret Then $aResult[0] = $Ret EndIf Else ExitLoop 2 EndIf Next $Error = 0 Until 1 If $hSv Then DllCall('gdi32.dll', 'ptr', 'SelectObject', 'hwnd', $hDC, 'ptr', $hSv) EndIf If $hDC Then DllCall('user32.dll', 'int', 'ReleaseDC', 'hwnd', $CtrlID, 'hwnd', $hDC) EndIf If $Error Then Return SetError(1, 0, 0) EndIf If $fAlignment Then $sString = StringTrimRight($sText, 2) EndIf Return $aResult EndFunc ;==>_GetTabbedStringSizeEx Edited December 22, 2013 by Yashied mLipok, UEZ and funkey 3 My UDFs: iKey | FTP Uploader | Battery Checker | Boot Manager | Font Viewer | UDF Keyword Manager | Run Dialog Replacement | USBProtect | 3D Axis | Calculator | Sleep | iSwitcher | TM | NetHelper | File Types Manager | Control Viewer | SynFolders | DLL Helper Animated Tray Icons UDF Library | Hotkeys UDF Library | Hotkeys Input Control UDF Library | Caret Shape UDF Library | Context Help UDF Library | Most Recently Used List UDF Library | Icons UDF Library | FTP UDF Library | Script Communications UDF Library | Color Chooser UDF Library | Color Picker Control UDF Library | IPHelper (Vista/7) UDF Library | WinAPI Extended UDF Library | WinAPIVhd UDF Library | Icon Chooser UDF Library | Copy UDF Library | Restart UDF Library | Event Log UDF Library | NotifyBox UDF Library | Pop-up Windows UDF Library | TVExplorer UDF Library | GuiHotKey UDF Library | GuiSysLink UDF Library | Package UDF Library | Skin UDF Library | AITray UDF Library | RDC UDF Library Appropriate path | Button text color | Gaussian random numbers | Header's styles (Vista/7) | ICON resource enumeration | Menu & INI | Tabbed string size | Tab's skin | Pop-up circular menu | Progress Bar without animation (Vista/7) | Registry export | Registry path jumping | Unique hardware ID | Windows alignment More... Link to comment Share on other sites More sharing options...
Yashied Posted June 2, 2012 Author Share Posted June 2, 2012 (edited) I slightly modified the function. It seems now a universal tool to retrieve dimensions of a string in AutoIt. Global $Text[3] = ['Simple string', 'String' & @TAB & 'with' & @TAB & 'tab' & @TAB & 'characters', 'String with carriage' & @CRLF & 'return'] Global $Label[3] $hForm = GUICreate('MyGUI', 318, 116) GUISetFont(15, 400, 0, 'Tahoma') For $i = 0 To 2 $Label[$i] = GUICtrlCreateLabel($Text[$i], 0, 0) $Size = _GetTabbedStringSizeEx(-1, $Text[$i]) GUICtrlSetPos(-1, 5, 5 + 29 * $i, $Size[0], $Size[1]) GUICtrlSetBkColor(-1, 0xFFC0C0) Next GUISetState() Do Until GUIGetMsg() = -3 Edited February 6, 2014 by Yashied My UDFs: iKey | FTP Uploader | Battery Checker | Boot Manager | Font Viewer | UDF Keyword Manager | Run Dialog Replacement | USBProtect | 3D Axis | Calculator | Sleep | iSwitcher | TM | NetHelper | File Types Manager | Control Viewer | SynFolders | DLL Helper Animated Tray Icons UDF Library | Hotkeys UDF Library | Hotkeys Input Control UDF Library | Caret Shape UDF Library | Context Help UDF Library | Most Recently Used List UDF Library | Icons UDF Library | FTP UDF Library | Script Communications UDF Library | Color Chooser UDF Library | Color Picker Control UDF Library | IPHelper (Vista/7) UDF Library | WinAPI Extended UDF Library | WinAPIVhd UDF Library | Icon Chooser UDF Library | Copy UDF Library | Restart UDF Library | Event Log UDF Library | NotifyBox UDF Library | Pop-up Windows UDF Library | TVExplorer UDF Library | GuiHotKey UDF Library | GuiSysLink UDF Library | Package UDF Library | Skin UDF Library | AITray UDF Library | RDC UDF Library Appropriate path | Button text color | Gaussian random numbers | Header's styles (Vista/7) | ICON resource enumeration | Menu & INI | Tabbed string size | Tab's skin | Pop-up circular menu | Progress Bar without animation (Vista/7) | Registry export | Registry path jumping | Unique hardware ID | Windows alignment More... Link to comment Share on other sites More sharing options...
ValeryVal Posted June 4, 2012 Share Posted June 4, 2012 Any thoughts.What is about solution of the inverse task of your one? Receive size and font to place string given into label (edit) space with prescribed length and height.However this task can have the set of fonts (with it's sizes). There is some of interest to get optimum from list of fonts.Thank you. The point of world view Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 4, 2012 Moderators Share Posted June 4, 2012 Yashied, Sorry I missed this when you posted it. Excellent work - probably the last word in measuring strings. 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...
KaFu Posted December 20, 2012 Share Posted December 20, 2012 Stumbled into the same problem and found this solution, excellent as always ... OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) 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