- Сообщения
- 5,379
- Репутация
- 2,724
Это финальная часть этой темы. Если посмотреть на последнее мое сообщение, то я там описывал проблему, связанную с определением длины отсупов табуляции в AutoIt. Поэтому приходилось однозначно задавать это значение для каждого шрифта и размера. Но я ее все-таки сделал. Оказалось все очень просто, длина отступов табуляции в AutoIt для любого шрифта вычисляется следующим образом:
Ну а поправить функцию уже не составляет труда. Итак, функция _GetTabbedStringSizeEx() возвращает ширину и высоту указанной табулированной или нетабулированной строки, которая, к тому же, может содержать символы возврата каретки (@CR или @CRLF). Дополнительно можно выровнять входную строку по символу @TAB для отображения в виде таблицы (см. скриншот). Теперь значения отступов табуляции вычисляются автоматически в зависимости от используемого шрифта.
Код:
8 * TEXTMETRIC("tmAveCharWidth")
Ну а поправить функцию уже не составляет труда. Итак, функция _GetTabbedStringSizeEx() возвращает ширину и высоту указанной табулированной или нетабулированной строки, которая, к тому же, может содержать символы возврата каретки (@CR или @CRLF). Дополнительно можно выровнять входную строку по символу @TAB для отображения в виде таблицы (см. скриншот). Теперь значения отступов табуляции вычисляются автоматически в зависимости от используемого шрифта.
Код:
#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