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