Автор Тема: Получение размеров табулированной строки  (Прочитано 2633 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Это финальная часть этой темы. Если посмотреть на последнее мое сообщение, то я там описывал проблему, связанную с определением длины отсупов табуляции в AutoIt. Поэтому приходилось однозначно задавать это значение для каждого шрифта и размера. Но я ее все-таки сделал. Оказалось все очень просто, длина отступов табуляции в AutoIt для любого шрифта вычисляется следующим образом:

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


Код: AutoIt [Выделить]
#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

« Последнее редактирование: Июнь 02, 2012, 20:51:35 от Yashied »


Думай, прежде чем говорить.

Русское сообщество AutoIt

Получение размеров табулированной строки
« Отправлен: Май 29, 2012, 00:42:53 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
15 Ответов
10674 Просмотров
Последний ответ Сентябрь 10, 2009, 03:37:56
от Yashied
2 Ответов
3915 Просмотров
Последний ответ Октябрь 26, 2010, 13:48:33
от amorph
3 Ответов
4122 Просмотров
Последний ответ Февраль 17, 2011, 23:49:16
от `p r o x y
18 Ответов
7764 Просмотров
Последний ответ Июнь 30, 2011, 18:42:09
от CreatoR
9 Ответов
2091 Просмотров
Последний ответ Июль 02, 2014, 13:09:19
от damien2008
7 Ответов
2035 Просмотров
Последний ответ Февраль 01, 2015, 17:18:36
от rivega
0 Ответов
678 Просмотров
Последний ответ Февраль 01, 2015, 16:19:00
от madmasles
0 Ответов
479 Просмотров
Последний ответ Октябрь 23, 2017, 08:29:59
от Атос
2 Ответов
339 Просмотров
Последний ответ Ноябрь 23, 2017, 15:38:34
от InnI
1 Ответов
210 Просмотров
Последний ответ Январь 09, 2018, 15:00:41
от InnI