Что нового

[Данные, строки] Получить длину строки в пикселях.

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
gora
Проверил, длина GUICtrlCreateLabel не подстраивается под переменную длину @Tab. Наверно лучше использовать StringFormat, при моноширинном тексте получается колончатый формат. Главное определить максимальную длину каждой колонки в символах. Вот как я делал для combo
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
AZJIO [?]
длина GUICtrlCreateLabel не подстраивается под переменную длину @Tab.
НЕ понял, что Вы имели ввиду? Скриншот на предыдущей странице, это табулированный текст, каждая строка которого выведена через GUICtrlCreateLabel Все GUICtrlCreateLabel одинаковой длины и выравнивание текста осуществляется только табуляцией. Значит @Tab в GUICtrlCreateLabel работает и работает корректно.
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
gora
_TextSize использует принцип создания GUICtrlCreateLabel и получения длинны элемента. Оно и доказывает, что не подстраивается.

Код:
#include <StaticConstants.au3>

GUICreate('My Program', 650, 260)
$s_Data1='AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'A'
$iStatusBar = GUICtrlCreateLabel($s_Data1, 5, 3, Default, 23, $SS_LEFTNOWORDWRAP)

$s_Data2='A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A' ; не подстраивается
$iStatusBar = GUICtrlCreateLabel($s_Data2, 5, 26, Default, 23, $SS_LEFTNOWORDWRAP)

$s_Data3='AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'AAAAAA'&@TAB&'A'&@CRLF& _
'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'
$iStatusBar = GUICtrlCreateLabel($s_Data3, 5, 50, Default, 44, $SS_LEFTNOWORDWRAP)
GUISetState()
Do
Until GUIGetMsg() = -3
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
AZJIO [?]
Оно и доказывает, что не подстраивается.
А если так?
Код:
#include <StaticConstants.au3>

GUICreate('My Program', 650, 260)
$s_Data1='AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'A'
$iStatusBar = GUICtrlCreateLabel($s_Data1, 5, 3, 600, 23, $SS_LEFTNOWORDWRAP)

$s_Data2='A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A' ; не подстраивается
$iStatusBar = GUICtrlCreateLabel($s_Data2, 5, 26, 600, 23, $SS_LEFTNOWORDWRAP)

$s_Data3='AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'AAAA'&@TAB&'A'&@CRLF& _
'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'&@TAB&'A'
$iStatusBar = GUICtrlCreateLabel($s_Data3, 5, 50, 600, 44, $SS_LEFTNOWORDWRAP)
GUISetState()
Do
Until GUIGetMsg() = -3



Добавлено:
Сообщение автоматически объединено:

AZJIO [?]
_TextSize использует принцип создания GUICtrlCreateLabel и получения длинны элемента
Мне кажется там это сделано не корректно. На Win7, если текст достаточно длинный, а длина GUICtrlCreateLabel не указана, то текст складывается в две строки.
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
gora сказал(а):
Это подстраивание файктов

то текст складывается в две строки
Стиль $SS_LEFTNOWORDWRAP - без переноса строк. Да там и видно что пол-буквы обрезается, а при переносе обычно буквы не обрезаются.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
gora

Вся проблема заключается в том, что какого-либо свойства, связанного с табуляцией, у окон нет (ну, по крайней мере, я не нашел). Вывод табулированного текста производится по маркерам (сетке), которые определяет пользователь. В большинстве случаев, ширина сетки берется одинаковая, но можно задать и разные значения для каждой позиции табуляции. А так, как ты выводишь текст не самостоятельно (см. TabbedTextOut()), а с помощью AutoIt, т.е. GUICtrlCreateLabel(), то не можешь знать значения маркеров табуляции. Как правило, они зависят от начертания и размера шрифта.

Узнать ширину и высоту табулированной строки, как уже сказал inververs, можно с помощью GetTabbedTextExtent() функции. Но проблема здесь как раз заключается в значениях маркеров табуляции, которые нужно передать этой функции, чтобы получить корректные размеры строки. Но чтобы все-таки заставить эту функцию работать, нужно сделать следующее:

  • Однозначно задать шрифт для Label или всего GUI сразу, т.к. по умолчанию используется "MS Shell Dlg", а это подстановочный шрифт и, теоретически, может быть любым. Для окон, как правило, используется "Microsoft Sans Serif", он же и есть "MS Shell Dlg".

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes

  • Определиться с размером шрифта. По умолчанию для Label это будет 8.3.
  • Померить значение первого маркера табуляции в каком-нибудь графическом редакторе.

Для "Microsoft Sans Serif, 8.3" размер сетки будет 40 точек, т.е. все отступы будут выравниваться через отрезки, кратные 40 точкам. Ну а дальше дело техники...

Код:
#Include <GUIConstants.au3>
#Include <WinAPI.au3>

$Text = 'AAAAA' & @TAB & 'AAAAA' & @TAB & 'AAAAA' & @TAB & 'AAAAA' & @TAB & 'AAAAA' & @TAB & 'AAAAA' & @TAB & 'AAAAA' & @CRLF & _
		'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @CRLF & _
		'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @CRLF & _
		'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @CRLF & _
		'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A'

$hForm = GUICreate('MyGUI', 0, 0)
GUISetFont(8.3, 400, 0, 'Microsoft Sans Serif')
GUICtrlCreateLabel($Text, 0, 0)
GUICtrlSetBkColor(-1, 0xC0C0FF)
$Size = _GetTabbedStringSize(-1, $Text)
If Not @Error Then
	GUICtrlSetPos(-1, -1, -1, $Size[0], $Size[1])
EndIf
$Pos = WinGetPos($hForm)
WinMove($hForm, '', (@DesktopWidth - ($Pos[2] + $Size[0])) / 2, (@DesktopHeight - ($Pos[3] + $Size[1])) / 2, $Pos[2] + $Size[0], $Pos[3] + $Size[1])
GUISetState()

Do
Until GUIGetMsg() = -3

Func _GetTabbedStringSize($CtrlID, $sString, $iTabStop = 40)

	Local $hDC, $hSv, $tTab, $Ret
	Local $Result[2] = [0, 0]

	If Not IsHWnd($CtrlID) Then
		$CtrlID = GUICtrlGetHandle($CtrlID)
		If Not $CtrlID Then
			Return SetError(1, 0, 0)
		EndIf
	EndIf
	$Ret = DllCall('user32.dll', 'ptr', 'SendMessageW', 'hwnd', $CtrlID, 'uint', 0x0031, 'wparam', 0, 'lparam', 0)
	If (@Error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	$hDC = _WinAPI_GetDC($CtrlID)
	$hSv = _WinAPI_SelectObject($hDC, $Ret[0])
	$tTab = DllStructCreate('int')
	DllStructSetData($tTab, 1, $iTabStop)
	$sString = StringSplit(StringReplace($sString, @CRLF, @CR), @CR)
	For $i = 1 To $sString[0]
		$Ret = DllCall('user32.dll', 'dword', 'GetTabbedTextExtentW', 'hwnd', $hDC, 'wstr', $sString[$i], 'int', StringLen($sString[$i]), 'int', 1, 'ptr', DllStructGetPtr($tTab))
		If (Not @Error) And ($Ret[0]) Then
			$Result[1] += _WinAPI_HiWord($Ret[0])
			$Ret = _WinAPI_LoWord($Ret[0])
			If $Result[0] < $Ret Then
				$Result[0] = $Ret
			EndIf
		Else
			$Result = 0
			ExitLoop
		EndIf
	Next
	_WinAPI_SelectObject($hDC, $hSv)
	_WinAPI_ReleaseDC($CtrlID, $hDC)
	If Not IsArray($Result) Then
		Return SetError(1, 0, 0)
	EndIf
	Return $Result
EndFunc   ;==>_GetTabbedStringSize


P.S

Заменять табуляцию на пробелы можно только в моноширинных шрифтах, например "Courier", "Courier New", и т.д., иначе все "поплывет".

P.S.S

Как вариант, можно сделать отдельный Label для каждой ячейки.



Добавлено:
Сообщение автоматически объединено:

А если поиграться с этой функцией, то можно получить красивую форматированную таблицу.

Код:
#Include <GUIConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPI.au3>

$Text = '--= Группа 2 =--' & @TAB & '0B7' & @TAB & '--= Группа 3 =--'   & @TAB & '01F' & @TAB & '--= Группа 4 =--'   & @TAB & '2FF' & @TAB & '--= Группа 5 =--' & @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 & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'COMPRESS_LZMA'    & @TAB & '+'   & @TAB & 'PREFIX_FORCENOWAIT' & @TAB & '+'   & @TAB & 'CHECK_FREE_SPACE'   & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'COMPRESS_LZMA2'   & @TAB & '+'   & @TAB & ''                   & @TAB & ''    & @TAB & 'BEGINPROMPTTIMEOUT' & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'COMPRESS_PPMD'    & @TAB & '-'   & @TAB & ''                   & @TAB & ''    & @TAB & 'CONFIG_PLATFORM'    & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'CRYPTO'           & @TAB & '+'   & @TAB & ''                   & @TAB & ''    & @TAB & 'EARLY_PASSWORD'     & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'VOLUMES'          & @TAB & '-'   & @TAB & ''                   & @TAB & ''    & @TAB & 'VOLUME_NAME_STYLE'  & @TAB & '-'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'PROTECT'          & @TAB & '-'   & @TAB & ''                   & @TAB & ''    & @TAB & 'ENVIRONMENT_VARS'   & @TAB & '+'   & @TAB & ''                 & @TAB & ''

$hForm = GUICreate('Опции сборки модуля', 0, 0)
GUISetFont(9.3, 400, 0, 'Segoe UI')
GUISetBkColor(0xFFFFFF)
GUICtrlCreateLabel('', 50, 10)
$Size = _GetTabbedStringSizeEx(-1, $Text, 48)
If Not @Error Then
	GUICtrlSetPos(-1, -1, -1, $Size[0], $Size[1])
	GUICtrlSetData(-1, $Text)
EndIf
$Pos = WinGetPos($hForm)
WinMove($hForm, '', (@DesktopWidth - ($Pos[2] + $Size[0] + 60)) / 2, (@DesktopHeight - ($Pos[3] + $Size[1] + 74)) / 2, $Pos[2] + $Size[0] + 60, $Pos[3] + $Size[1] + 74)
GUICtrlCreateIcon(@SystemDir & '\user32.dll', -3, 10, 11, 32, 32)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlCreateGraphic(0, $Size[1] + 20, $Size[0] + 60, 1)
GUICtrlSetBkColor(-1, 0xDFDFDF)
GUICtrlSetState(-1, $GUI_DISABLE)
$hBottom = GUICreate('', $Size[0] + 60, 53, 0, $Size[1] + 21, BitOR($WS_CHILD, $WS_TABSTOP), -1, $hForm)
GUISetFont(9.3, 400, 0, 'Segoe UI')
GUISetBkColor(0xF0F0F0)
$Button = GUICtrlCreateButton('OK', ($Size[0] + 60) / 2 - 37, 13, 88, 27)
GUICtrlSetState(-1, BitOR($GUI_DEFBUTTON, $GUI_FOCUS))
GUISetState(@SW_SHOW, $hBottom)
GUISetState(@SW_SHOW, $hForm)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE, $Button
			ExitLoop
		Case Else

	EndSwitch
WEnd

GUIDelete($hForm)
GUIDelete($hBottom)

Func _GetTabbedStringSizeEx($CtrlID, ByRef $sString, $iTab = 40)

	Local $hDC, $hSv, $aData, $tData, $pData, $aSize, $aTabs, $aTemp, $aText, $sText = '', $Ret, $Count = 0
	Local $Result[2] = [0, 0]

	If Not IsHWnd($CtrlID) Then
		$CtrlID = GUICtrlGetHandle($CtrlID)
		If Not $CtrlID Then
			Return SetError(1, 0, 0)
		EndIf
	EndIf
	If $iTab <= 0 Then
		Return SetError(1, 0, 0)
	EndIf
	$Ret = DllCall('user32.dll', 'ptr', 'SendMessageW', 'hwnd', $CtrlID, 'uint', 0x0031, 'wparam', 0, 'lparam', 0)
	If (@Error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	$hDC = _WinAPI_GetDC($CtrlID)
	$hSv = _WinAPI_SelectObject($hDC, $Ret[0])
	$aTemp = StringSplit(StringReplace($sString, @CRLF, @CR), @CR)
	For $i = 1 To $aTemp[0]
		$aData = StringSplit($aTemp[$i], @TAB)
		If $Count < $aData[0] Then
			$Count = $aData[0]
		EndIf
	Next
	$tData = DllStructCreate('long;long')
	$pData = DllStructGetPtr($tData)
	Dim $aTabs[$Count]
	Dim $aText[$aTemp[0]][$Count]
	Dim $aSize[$aTemp[0]][$Count]
	For $i = 1 To $aTemp[0]
		$aData = StringSplit($aTemp[$i], @TAB)
		For $j = 0 To $Count - 1
			Select
				Case $aData[0] < $j + 1
					$aText[$i - 1][$j] = 0
					$aSize[$i - 1][$j] =-1
				Case $aData[0] = $j + 1
					$aText[$i - 1][$j] = $aData[$j + 1]
					$aSize[$i - 1][$j] =-1
				Case Else
					$aText[$i - 1][$j] = $aData[$j + 1]
					$Ret = DllCall('gdi32.dll', 'int', 'GetTextExtentPoint32W', 'hwnd', $hDC, 'wstr', $aData[$j + 1], 'int', StringLen($aData[$j + 1]), 'ptr', $pData)
					If (Not @Error) And ($Ret[0]) Then
						$aSize[$i - 1][$j] = DllStructGetData($tData, 1)
					Else
						$aSize[$i - 1][$j] = 0
					EndIf
			EndSelect
		Next
	Next
	For $j = 0 To $Count - 1
		$aTabs[$j] = 1
		For $i = 1 To $aTemp[0]
			If $aSize[$i - 1][$j] <> -1 Then
				$aSize[$i - 1][$j] = Ceiling($aSize[$i - 1][$j] / ($iTab - 1))
				If Not $aSize[$i - 1][$j] Then
					$aSize[$i - 1][$j] = 1
				Else
					If $aTabs[$j] < $aSize[$i - 1][$j] Then
						$aTabs[$j] = $aSize[$i - 1][$j]
					EndIf
				EndIf
			EndIf
		Next
	Next
	Dim $aData[$aTemp[0]]
	For $i = 1 To $aTemp[0]
		$aData[$i - 1] = ''
		For $j = 0 To $Count - 1
			If IsString($aText[$i - 1][$j]) Then
				$aData[$i - 1] &= $aText[$i - 1][$j]
				If $aSize[$i - 1][$j] <> -1 Then
					$aSize[$i - 1][$j] = $aTabs[$j] - $aSize[$i - 1][$j]
				EndIf
				For $k = 1 To $aSize[$i - 1][$j] + 1
					$aData[$i - 1] &= @TAB
				Next
			Else
				ExitLoop
			EndIf
		Next
		$sText &= $aData[$i - 1] & @CRLF
	Next
	$tData = DllStructCreate('uint')
	DllStructSetData($tData, 1, $iTab)
	$pData = DllStructGetPtr($tData)
	For $i = 1 To $aTemp[0]
		$Ret = DllCall('user32.dll', 'dword', 'GetTabbedTextExtentW', 'hwnd', $hDC, 'wstr', $aData[$i - 1], 'int', StringLen($aData[$i - 1]), 'int', 1, 'ptr', $pData)
		If (Not @Error) And ($Ret[0]) Then
			$Result[1] += _WinAPI_HiWord($Ret[0])
			$Ret = _WinAPI_LoWord($Ret[0])
			If $Result[0] < $Ret Then
				$Result[0] = $Ret
			EndIf
		Else
			$Result = 0
			ExitLoop
		EndIf
	Next
	_WinAPI_SelectObject($hDC, $hSv)
	_WinAPI_ReleaseDC($CtrlID, $hDC)
	If Not IsArray($Result) Then
		Return SetError(1, 0, 0)
	EndIf
	$sString = StringTrimRight($sText, 2)
	Return $Result
EndFunc   ;==>_GetTabbedStringSizeEx



Добавлено:
Сообщение автоматически объединено:

Вот окончательная функция.

Код:
#Include <GUIConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPI.au3>

$Text = '--= Группа 2 =--' & @TAB & '0B7' & @TAB & '--= Группа 3 =--'   & @TAB & '01F' & @TAB & '--= Группа 4 =--'   & @TAB & '2FF' & @TAB & '--= Группа 5 =--' & @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 & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'COMPRESS_LZMA'    & @TAB & '+'   & @TAB & 'PREFIX_FORCENOWAIT' & @TAB & '+'   & @TAB & 'CHECK_FREE_SPACE'   & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'COMPRESS_LZMA2'   & @TAB & '+'   & @TAB & ''                   & @TAB & ''    & @TAB & 'BEGINPROMPTTIMEOUT' & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'COMPRESS_PPMD'    & @TAB & '-'   & @TAB & ''                   & @TAB & ''    & @TAB & 'CONFIG_PLATFORM'    & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'CRYPTO'           & @TAB & '+'   & @TAB & ''                   & @TAB & ''    & @TAB & 'EARLY_PASSWORD'     & @TAB & '+'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'VOLUMES'          & @TAB & '-'   & @TAB & ''                   & @TAB & ''    & @TAB & 'VOLUME_NAME_STYLE'  & @TAB & '-'   & @TAB & ''                 & @TAB & ''    & @CRLF & _
		'PROTECT'          & @TAB & '-'   & @TAB & ''                   & @TAB & ''    & @TAB & 'ENVIRONMENT_VARS'   & @TAB & '+'   & @TAB & ''                 & @TAB & ''

$hForm = GUICreate('Опции сборки модуля', 0, 0)
GUISetFont(9.3, 400, 0, 'Segoe UI')
GUISetBkColor(0xF0F0F0)
GUICtrlCreateLabel('', 10, 10)
GUICtrlSetBkColor(-1, 0xFFFFFF)
$Size = _GetTabbedStringSizeEx(-1, $Text, 1, 48)
If Not @Error Then
	GUICtrlSetPos(-1, -1, -1, $Size[0], $Size[1])
	GUICtrlSetData(-1, $Text)
EndIf
$Pos = WinGetPos($hForm)
WinMove($hForm, '', (@DesktopWidth - ($Pos[2] + $Size[0] + 20)) / 2, (@DesktopHeight - ($Pos[3] + $Size[1] + 74)) / 2, $Pos[2] + $Size[0] + 20, $Pos[3] + $Size[1] + 74)
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] + 34, 88, 27)
GUICtrlSetState(-1, BitOR($GUI_DEFBUTTON, $GUI_FOCUS))
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE, $Button
			ExitLoop
		Case Else

	EndSwitch
WEnd

Func _GetTabbedStringSizeEx($CtrlID, ByRef $sString, $fAlignment = False, $iTab = 40)

	Local $W = 0, $H, $hDC, $hSv, $aTemp, $aSize, $aData, $aTabs, $aText, $sText = '', $Ret
	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
	If $iTab < 1 Then
		Return SetError(1, 0, 0)
	EndIf
	$Ret = DllCall('user32.dll', 'ptr', 'SendMessageW', 'hwnd', $CtrlID, 'uint', 0x0031, 'wparam', 0, 'lparam', 0)
	If (@Error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	$hDC = _WinAPI_GetDC($CtrlID)
	$hSv = _WinAPI_SelectObject($hDC, $Ret[0])
	$aData = StringSplit(StringReplace($sString, @CRLF, @CR), @CR)
	$H = $aData[0]
	If $fAlignment Then
		For $i = 1 To $H - 1
			$aTemp = StringSplit($aData[$i + 1], @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 + 1], @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 $iTab = 1 Then
						$aSize[$i][$j] = 1
					Else
						$aSize[$i][$j] = Ceiling($aSize[$i][$j] / ($iTab - 1))
						If Not $aSize[$i][$j] Then
							$aSize[$i][$j] = 1
						Else
							If $aTabs[$j] < $aSize[$i][$j] Then
								$aTabs[$j] = $aSize[$i][$j]
							EndIf
						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
	DllStructSetData($tData, 1, $iTab)
	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] += _WinAPI_HiWord($Ret[0])
			$Ret = _WinAPI_LoWord($Ret[0])
			If $aResult[0] < $Ret Then
				$aResult[0] = $Ret
			EndIf
		Else
			$aResult = 0
			ExitLoop
		EndIf
	Next
	_WinAPI_SelectObject($hDC, $hSv)
	_WinAPI_ReleaseDC($CtrlID, $hDC)
	If Not IsArray($aResult) Then
		Return SetError(1, 0, 0)
	EndIf
	If $fAlignment Then
		$sString = StringTrimRight($sText, 2)
	EndIf
	Return $aResult
EndFunc   ;==>_GetTabbedStringSizeEx



Добавлено:
Сообщение автоматически объединено:

Ха-Ха. Я сделал ее. Оказывается в AutoIt отступы табуляции вычисляются следующим образом:

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

Осталось дело за функцией.
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
Yashied
Спасибо, мне понравилось Ваше решение.
Но в этом варианте сразу создается окно и потом оно перемещается (становится видимым). Мне же надо "Получить длину строки в пикселях."
Т.е., я в цикле перебираю все строки (включая заголовок), которые будут в окне, нахожу максимальное значение и вычисляю размер (ширину, высоту задаю самостоятельно) окна. Потом я создаю это окно и вывожу в нем нужные строки, дополнительные кнопки, чекбоксы, и прочее. Кроме этого я хотел использовать эту функцию для расчета размера некоторых элементов, например, ширины выпадающего списка в _GUICtrlComboBox_SetDroppedWidth
Т.о. мне неудобно совмещать вычисление ширины и создание окна, как это сделано в вашем примере.
Можно ли вычленить из примера только определение ширины строки без рисования при этом самого окна?
Можно ли при вычислении этого размера обойтись без создания "технологического" окна, пусть и невидимого?
Шрифт у меня в окнах используется
Код:
GUISetFont(8.5,400,0,'Tahoma')
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
gora
А как на счёт того, что шрифт в каждом элементе может быть разный? Нужно получить шрифт и ещё получить размер шривта для конкретного элемента, потом использовать коэфициент соответственный размеру шрифта. На разных системах шрифт разный, зависит одни от темы, другие от установки в реестре.
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
AZJIO
Я устанавливаю нужный мне шрифт в своем окне и рассчитываю (возможно ошибочно), что шрифт во всех элементах моего окна будет именно таким. Разве нет?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Порядок действий должен быть такой:

  • Создаете Label (необязательно видимый)
  • Определяете ширину строки для него.
  • Изменяете размеры Label.
  • Вставляете строку.

В чем здесь проблема? Ведь тебе же все равно нужно создавать Label'ы для отображения текста. Без создания Label не получится, т.к. все функции для работы с текстом требуют HDC с установленным в нем шрифтом, из которого, собственно, и берут информацию о шрифте.
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
Yashied [?]
Порядок действий должен быть такой:
Создаете Label (необязательно видимый)
Определяете ширину строки для него.
Изменяете размеры Label.
Вставляете строку.
В чем здесь проблема?
Чтобы выполнить последнее действие (Вставляете строку) мне нужно рассчитать размеры окна, положение каждого Label и потом уже их вставлять в окно.
Вот меня и интересует, как это ("Получить длину строки в пикселях.") реализовать?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
:blink:

Ну так создай окно любого размера, на нем размести один Label любого размера и в любом месте, а затем узнай размеры всех своих строк и переразмерь окно и Label(ы)...

Код:
Global $Label[4]
Global $Text[4] = ['AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA' & @TAB & 'AAAA', _
				   'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA' & @TAB & 'AAA', _
				   'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA' & @TAB & 'AA', _
				   'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A' & @TAB & 'A']

$hForm = GUICreate('MyGUI', 0, 0)
GUISetFont(8.3, 400, 0, 'Tahoma')
$Width = 0
For $i = 0 To 3
	$Label[$i] = GUICtrlCreateLabel($Text[$i], 0, 0)
	GUICtrlSetBkColor(-1, 0xC0C0FF)
	$Size = _GetTabbedStringSizeEx(-1, $Text[$i])
	If Not @Error Then
		GUICtrlSetPos(-1, 0, 14 * $i, $Size[0], 14)
		If $Width < $Size[0] Then
			$Width = $Size[0]
		EndIf
	EndIf
Next
$Pos = WinGetPos($hForm)
WinMove($hForm, '', (@DesktopWidth - ($Pos[2] + $Width)) / 2, (@DesktopHeight - ($Pos[3] + 14 * 4)) / 2, $Pos[2] + $Width, $Pos[3] + 14 * 4)
GUISetState()

Do
Until GUIGetMsg() = -3


Функцию _GetTabbedStringSizeEx() возьми отсюда (я ее немного изменил). Эта функция возвращает размеры абсолютно любой строки (необязательно содержащей @TAB или @CRLF).
 
Верх