Что нового

Получение размеров табулированной строки

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Это финальная часть этой темы. Если посмотреть на последнее мое сообщение, то я там описывал проблему, связанную с определением длины отсупов табуляции в AutoIt. Поэтому приходилось однозначно задавать это значение для каждого шрифта и размера. Но я ее все-таки сделал. Оказалось все очень просто, длина отступов табуляции в AutoIt для любого шрифта вычисляется следующим образом:

Код:
8 * TEXTMETRIC("tmAveCharWidth")

Ну а поправить функцию уже не составляет труда. Итак, функция _GetTabbedStringSizeEx() возвращает ширину и высоту указанной табулированной или нетабулированной строки, которая, к тому же, может содержать символы возврата каретки (@CR или @CRLF). Дополнительно можно выровнять входную строку по символу @TAB для отображения в виде таблицы (см. скриншот). Теперь значения отступов табуляции вычисляются автоматически в зависимости от используемого шрифта.

post_img_092.png

Код:
#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
 
  • Like
Реакции: Norm
Верх