Как я могу рассчитать количество строк в текстовом поле? - PullRequest
0 голосов
/ 27 февраля 2009

Я надеюсь, что кто-то может помочь мне с проблемой, которая возникла у меня на данный момент, с использованием Compact Framework.Net 2 SP 2.

На данный момент у меня есть пользовательский интерфейс с серией текстовых полей, и каждое текстовое поле отображает содержимое поля базы данных. Они показаны одна под другой с полосой прокрутки с правой стороны формы. Каждое текстовое поле имеет заданную ширину, которая может

Я хотел бы настроить высоту каждого текстового поля на основе количества строк, которые оно содержит, размера шрифта и шрифта, чтобы избежать использования полос прокрутки в каждом текстовом поле.

На данный момент я могу сделать это в тестовом приложении.


Скриншот:

см. Скриншот для вывода http://morrislgn.brinkster.net/SO/screenshot.jpg


Мой код:

'Text used in this example:
'TextBox1qwertyuiop lkjhgfdsazxcvbnm1234567890 TextBo

'x1qwer tyuioplkjhgfdsazxcvb nm1234567890

'qwe
'End of exmaple text.

Me.Textbox2.Text = Me.Textbox1.Text

Dim pobjGraphic As Graphics = Me.Textbox2.Parent.CreateGraphics()
Dim pobjSize As SizeF

'Padding values:
Dim piTop As Int32 = 4 'top of text and top of textbox
Dim piBottom As Int32 = 3 'bottom of text and top of textbox

Dim piLines As Int32 = 0

'Based on the font size chosen by the user, create a font to perform the calculation with.
Dim piFontSize As Single = 10

If Me.CheckBox1.Checked.Equals(True) Then
    piFontSize = 6
ElseIf Me.CheckBox2.Checked.Equals(True) Then
    piFontSize = 8
ElseIf Me.CheckBox3.Checked.Equals(True) Then
    piFontSize = 12
Else
    piFontSize = 10
End If

Dim pobjFont As New Font("Tahoma", piFontSize, FontStyle.Regular)

'Calculate the height of one line.
pobjSize = pobjGraphic.MeasureString("HELLO WORLD", pobjFont)
'Value of pobjSize returned: {Width = 71.0 Height = 13.0}


'Calculate the number of lines          
Dim b As Bitmap
b = New Bitmap(1, 1, Imaging.PixelFormat.Format32bppRgb)

'Calculate the number of lines required to display the text properly based on the lenght of the text the width of the control.
'Length of text to show divide by the width of the textbox
piLines = Graphics.FromImage(b).MeasureString(Me.Textbox2.Text, pobjFont).Width / Me.Textbox2.Width
'Value of piLines returned: 2

If piLines = 0 Then
    piLines = 1
End If

'Calculate the size of the text to be displayed using the margins, height of one line and number of lines.
Me.Textbox2.Height = (pobjSize.Height * piLines) + piTop + piBottom
' value produced: 33 = (13 * 2) + 4 + 3
'set font of text box
Me.Textbox2.Font = pobjFont

Наконец, я знаю, что это может быть достигнуто с помощью вызова COREDLL.dll с помощью p / invoke, но при этом происходит сбой приложения.

Привет, народ,

Ниже приведен код запроса pinvoke:

    <Runtime.InteropServices.DllImport("coredll.dll")> _
Private Function SendMessage( _
    ByVal hwnd As IntPtr, ByVal msg As Integer, _
    ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function

<Runtime.InteropServices.DllImport("coredll.dll")> _
Private Function GetCapture() As IntPtr
End Function

<Runtime.InteropServices.DllImport("coredll.dll")> _
Private Function ReleaseCapture() As Boolean
End Function

Public Function GetNumberOfLines(ByVal ptxtCountBox As TextBox) As Integer
    Try
        Dim hnd As IntPtr = New IntPtr

        ptxtCountBox.Capture = True

        ' Capture the textbox handle.
        hnd = GetCapture()
        ptxtCountBox.Capture = False

        ' Get the count of the lines in the box.
        Dim plCount As Integer = SendMessage(ptxtCountBox.Handle, EM_GETLINECOUNT, 0, 0)

        ' Count the number of return lines as we minus this from the total lines to take.
        plCount = plCount - (CharCount(ptxtCountBox.Text, vbCrLf, False))

        plCount += RemoveNonASCIIReturns(ptxtCountBox)

        ReleaseCapture()

        hnd = Nothing

        ' Return the line count.
        Return plCount
    Catch ex As Exception
        GenerateError(msCLASS_NAME, "GetNumberOfLines", ex.Message.ToString)
    End Try
End Function

Спасибо

Morris

Ответы [ 3 ]

0 голосов
/ 07 апреля 2009

Ну, я бы предложил вам разумное и разумное решение. Вот алгоритм:

  1. Используйте элемент управления Label для справки.
  2. Назначение: • Размер текстового поля для метки. • Шрифт Textbox для метки. • Autosize-свойство Label должно быть True . • BorderStyle Свойство метки как текстового поля '. • Свойство MinimumSize Label как исходный размер текстового поля. • Свойство MaximumSize для Label как Width - то же самое, что и original, и Height для большой кратности исходной высоты.

  3. Назначить текстовое поле 'Текст тексту метки.

  4. Теперь: если свойство PrefferdHeight для Label> Высота текстового поля == True Пришло время увеличить высоту текстового поля и проверить указанное выше условие, пока оно не станет ложным.
  5. Метка теперь может быть удалена.

Я также опубликовал аналогичное решение на форуме MSDN, которое также можно проверить: [http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/03fc8e75-fc13-417a-ad8c-d2b26a3a4dda][1]

С уважением. :)

0 голосов
/ 20 апреля 2009

Я задал похожий вопрос и получил ответ, который полностью удовлетворил мои потребности по этому вопросу! Пожалуйста, проверьте ответ Stevo3000 на мой вопрос: Авторазмер для надписи / TextBox в .NET Compact Framework

Он сослался на эти два поста в блоге, которые просто полностью решили мою проблему одним движением! http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html http://www.mobilepractices.com/2008/01/making-multiline-measurestring-work.html

0 голосов
/ 04 марта 2009

Думаю, я докопался до этого:

    Public Function GetNumberOfLines(ByVal pstext As String, ByVal pobjfont As Font, ByVal pobjDimensions As Size) As Decimal
    Dim pslines As String() = Nothing
    'Used to measure the string to be placed into the textbox
    Dim pobjBitMap As Bitmap = Nothing
    Dim pobjSize As SizeF = Nothing

    Try
        Dim psline As String = String.Empty
        Dim pilinecount As Decimal = 0.0
        'Spilt the text based on the number of lines breaks.
        pslines = pstext.Split(vbCrLf)
        For Each psline In pslines
            'Create a graphics image which is used to work out the width of the text.
            pobjBitMap = New Bitmap(1, 1, Imaging.PixelFormat.Format32bppRgb)
            pobjSize = Graphics.FromImage(pobjBitMap).MeasureString(psline, pobjfont)

            'If the width of the text is less than 1.0 then add one to the count. This would incidcate a line break.
            If pobjSize.Width < 1.0 Then
                pilinecount = pilinecount + 1
            Else
                'Based on the dimensions of the text, work out the number of lines. 0.5 is added to round the value to next whole number.
                pilinecount = pilinecount + (Round((pobjSize.Width / pobjDimensions.Width) + 0.5))
            End If
        Next

        'If the line count it less than 1 return one line.
        If pilinecount < 1.0 Then
            Return 1.0
        Else
            Return pilinecount
        End If
    Catch ex As Exception
        Return 1.0
    Finally
        If pslines IsNot Nothing Then
            Array.Clear(pslines, 0, pslines.Length - 1)
            pslines = Nothing
        End If
        If pobjBitMap IsNot Nothing Then
            pobjBitMap.Dispose()
        End If
    End Try
End Function

Конечно, это немного хак, но в данный момент все работает нормально! Любые замечания или комментарии о том, как улучшить это, приветствуются.

Кроме того, о p / invoke материал, обнаружил корень проблемы, или, скорее, решение. Обновлен .Net FX на моем устройстве, и это, похоже, решило проблему.

Спасибо

1010 * Моррис *

...