文本框文本对齐

3

在TextBox中是否可以对文本进行对齐 (不是居中)?我知道

Justify (两端对齐)

txt.TextAlign = HorizontalAlignment.Left;

例如,但是左右两端都对齐的可能吗?

完全未经测试,因此不将其发布为答案,但不确定HorizontalAlignment是否是按位运算,如果是,则可以尝试使用|运算符添加左对齐和右对齐。虽然我不知道为什么你想这样做,也不知道它有什么用处。 - Skintkingle
1
我想要对齐而不是居中。 - c0dehunter
2
文本框控件中没有对齐文本的属性或方法,您可能需要通过覆盖现有的TextAlign来创建自定义文本框。 - Damith
2
我认为OP想要拉伸文本,就像在报纸和书籍中所做的那样。文本被展开以填满所有可用空间。 - General Grey
3个回答

2

这是一个很棘手的问题,正如先前所述,需要一个自定义控件来解决。然而,如果你像我一样只想在对话框或关于框中显示文本框数据(例如居中显示),那么可以使用PictureBox并将其渲染到其中,同时保持实际的文本框隐藏。需要将空格替换为特殊代码以指示间距的像素宽度。作为许多打印机驱动程序的老手,这对我来说已经很熟悉了。我将在下面提供执行此操作的代码,尽管我不确定它在此网页上的呈现效果如何。也许他们可以重新格式化它,或者如果他们要求,我会发送给他们原始代码。虽然我是一名汇编语言和C/C++开发人员,但我已经爱上了VB.NET,并用VB编写了它(我可以在两个小时内完成以前需要两周才能完成的工作)。

要使用这段代码,包括一个JustifyTextBox()方法和一个JustifyText_Paint()事件,只需放置所需的文本框并按照您想要的格式进行格式化。然后通过提供文本框调用JustifyTextBox()方法,例如JustifyTextBox(Me.MyTextBox),就可以开始工作了。它会处理所有PictureBox对象的创建和绘制工作。您可以将其应用于所需的任意数量的文本框。它不仅限于一个对象(这将违背面向对象的范例,无论如何)。

以下是所需的两个方法:

'*******************************************************************************
' Method Name : JustifyTextBox
' Copyright (c) David Ross GOben March 10, 2013. All rights reserved.
'
' Purpose     : Reformat spacing in a textbox to allow for variable spacing, exactly
'             : as a printer driver will process spacing for justification.
'             : Having written many dozens of printer drivers over the years, this
'             : is old hat. By the way, though you can do this with a RichTextBox,
'             : you really should consider interpreting the RTF code to properly
'             : render everything else, otherwise, if you were to simply replace
'             : the TextBox casting to a RichTextBox, it would only process the
'             : data from its Text property, so pretty text and coloring and font
'             : typeface, size, and enhancements will not display in the PictureBox.
'*******************************************************************************
' Set up your code to use the JustifyTextBox() method and the JustifyText_Paint() event like this:
'
'    JustifyTextBox(TextBoxObjectToJustify)    'create a PictureBox control to justify the text, and hide this TextBox
'                                              'This will also link the created PictureBox's Paint() event to JustifyText_Paint
'-------------------------------------------------------------------------------
' NOTE: You can duplicate the above code for as many text boxes as you require.
'       Also, there is no need to render them ReadOnly, because the user will not
'       be able to access them through the user itnerface.
'*******************************************************************************
Private Sub JustifyTextBox(ByRef TxtBox As TextBox)
    Dim picImage As PictureBox = New PictureBox                             'create a PictureBox object (The textBox data will be painted to this)
    With picImage
        .Location = TxtBox.Location                                         'locate the PictureBox to the provided TextBox control
        .Size = TxtBox.Size                                                 'size it to the textbox boundaries
        .Tag = TxtBox                                                       'save a reference to the textbox for use during printing
        .Parent = TxtBox.Parent                                             'set parent so it will display when the parent is displayed
        AddHandler picImage.Paint, AddressOf JustifyText_Paint              'attach an event handler to the picture box's paint event
        TxtBox.Visible = False                                              'render the associated textbox invisible
    End With
    '=======================================================================
    With TxtBox
        Dim TextSize As Size = TextRenderer.MeasureText("W y", .Font)       'get pixel width of "W y"
        Dim Yinc As Int32 = TextSize.Height                                 'get vertical spacing to increment lines
        Dim SpcSize As Int32 = TextSize.Width                               'save measurement (we will adust the Space Size variable property in a second)
        TextSize = TextRenderer.MeasureText("Wy", .Font)                    'get pixel width of "Wy", without the space
        SpcSize = SpcSize - TextSize.Width - 1                              'compute the width of a space (drop 1 more for proper rendering)
        Dim SpcInit As Int32 = 128 + SpcSize                                'initial size of space and ecoding of space codes (spacing size + 128)

        Dim CurlineIdx, NxtLineIdx, cAsc As Int32                           'used variables
        Dim LastLine As Int32 = .GetLineFromCharIndex(Len(.Text))           'get the last line index of the TextBox, offset from zero

        Dim Result As String = Nothing                                      'init encoded result
        Dim Txt As String = Nothing                                         'string to hold each line of text in the TextBox
        Dim Tmptext As String                                               'copy of Txt that is altered

        For Idx As Int32 = 0 To LastLine                                    'process each line (offset from 0)
            CurlineIdx = .GetFirstCharIndexFromLine(Idx)                    'get start of the indicated line number line
            If Idx = LastLine Then                                          'at the last line of text data in the TextBox (if so, we do not need to justify it?
                Txt = RTrim(.Text.Substring(CurlineIdx))                    'yes, so simply grab the text of the line from the start character index to the end of the text data
                Tmptext = Txt                                               'make a copy to TmpText
            Else                                                            'otherwise... grab the current line of text from the TextBox
                NxtLineIdx = .GetFirstCharIndexFromLine(Idx + 1)            'not the last line, so get the index to the start of the next line
                Txt = RTrim(.Text.Substring(CurlineIdx, NxtLineIdx - CurlineIdx)) 'grab the text of the current line. Also remove any trailing spaces
                If Len(Txt) <> 0 AndAlso VB.Right(Txt, 2) = vbCrLf Then     'does the current line end with CR/LF?
                    Tmptext = RTrim(VB.Left(Txt, Len(Txt) - 2))             'yes, so strip CR/LF and strip any spaced leading them. There is no need to justify this line
                ElseIf Len(Txt) = 0 Then                                    'otherwise, if the text notains NO data...
                    Tmptext = Nothing                                       'then simply make the line blank and do nothing else
                Else                                                        'otherwise... we have to encode the line to justify it
                    Tmptext = Txt                                           'get a copy of this string, which we will use to encode
                    TextSize = TextRenderer.MeasureText(Tmptext, .Font)     'get its current size
                    Dim SpcNeeded As Int32 = .Width - TextSize.Width        'compute number of pixels to add
                    If SpcNeeded > 0 Then                                   'do we need to add spacing? (allow for negative result)
                        Tmptext = Join(Split(Tmptext, " "), Chr(SpcInit))   'yes, so first replace spaces with special code for point-size spacing
                        Dim Idy As Int32 = 1                                'init column start index (used to skip over leading spaces)
                        Do While Asc(Mid(Tmptext, Idy, 1)) > 127
                            Idy += 1                                        'skip past leading spaces (indent)
                        Loop
                        '---------------------------------------------------
                        Dim AddedSpacing As Boolean = False                 'set up a flag to deterct if we added any spacing to the line
                        Do While SpcNeeded <> 0                             'now loop through and add a pixel to each space in the text until there are none left to add
                            For Idz As Int32 = Idy To Len(Tmptext)          'scan through line data
                                cAsc = Asc(Mid(Tmptext, Idz, 1))            'get code
                                If cAsc > 127 Then                          'special space character?
                                    cAsc += 1                               'add 1 pixel to its size
                                    Mid(Tmptext, Idz, 1) = Chr(cAsc)        'stuff result back
                                    AddedSpacing = True
                                    SpcNeeded -= 1                          'drop 1 from count of spacing needed
                                    If SpcNeeded = 0 Then                   'have we added all the spaces we need?
                                        Exit For                            'yes, so do not add any more
                                    End If
                                End If
                            Next
                            If Not AddedSpacing Then                        'if we could not add any space...
                                Exit Do                                     'then exit the loop
                            End If
                            AddedSpacing = False
                            '-----------------------------------------------
                        Loop                                                'loop through the line again to add additional spacing
                    End If
                End If
            End If
            '---------------------------------------------------------------
            Result &= vbCrLf & Tmptext                                      'add TmpText data, manipulated or not, to the Result accumulator string
        Next                                                                'process the next line of code
        .Text = Mid(Result, 3)                                              'stuff the result back to the TextBox for storage, less the leading CR+LF
    End With
End Sub

'*******************************************************************************
' Method Name : JustifyText_Paint
' Purpose     : Draw text from a textbox onto a PictureBox control (created in the
'             : setup code), using special spacing codes inserted by JustifyTextBox().
'             :
' NOTE        : A reference to the associated Textbox is stored in the PictureBox's Tag property
'*******************************************************************************
' NOTE: You may notice that we seem to add 1 pixel to the width of the space character,
'       below, but we subtracted 1 pixel in the the JustifyTextBox() method. This is
'       originally subtracting 1. It also allows the right margin to reamin at its
'       straightest. I realize that this actually has to do something with the margins
'       applied in the TextRender.MeasureText() process, and even though I have tried to
'       set theTextFormatFlags to NoPadding and in various other ways, and even none
'       at all (as it is now), it dors not make one bit of difference, at all. However,
'       on average, with or without using the TextFormatFlags, if we subtract a pixel from
'       the space size and subtract 6 (typical margin of 3 pixels on either side) from
'       measuring each word, the alignment is about perfect. However, a side effect is
'       that some long words seem to almost butt up against a fllowing word. A hack around
'       that is to simply manually insert an extra space between these words in the textbox.
'*******************************************************************************
Private Sub JustifyText_Paint(sender As Object, e As PaintEventArgs)
    With DirectCast(DirectCast(sender, PictureBox).Tag, TextBox)
        Dim TextSize As Size = TextRenderer.MeasureText("X y", .Font)               'get size of sample text
        Dim Yinc As Single = CSng(TextSize.Height)                                  'keep height for adding lines in the picturebox
        Dim SpcSize As Single = CSng(TextSize.Width)                                'save the length result
        TextSize = TextRenderer.MeasureText("Xy", .Font)                            'grab the same text, but without the space (drop 1 more for proper rendering)
        SpcSize = SpcSize - CSng(TextSize.Width + 1)                                'compute space width (we are actually subtracting an addtional pixel)
        Dim txtMargin As Single = CSng(.Margin.Left + .Margin.Right)                'compute the margin allowance (MeasureText adds this to the width)
        Dim PosnX As Single = CSng(e.ClipRectangle.Left)                            'start postion to draw text in the picturebox
        Dim PosnY As Single = CSng(e.ClipRectangle.Top)

        Dim Tmptxt As String = Nothing                                              'init temporary text holder
        Dim Brsh As New SolidBrush(.ForeColor)                                      'get the brush for the text color to use from the textbox
        For Idx As Int32 = 1 To Len(.Text)                                          'scan each character in the master text
            Dim iChar As Int32 = Asc(Mid(.Text, Idx, 1))                            'grab the cascii code for the currently indexed character
            Select Case iChar
                Case Is > 127                                                       'special spacing character?
                    If Len(Tmptxt) <> 0 Then                                        'yes, so dump the temp text if it has accumulated data
                        TextSize = TextRenderer.MeasureText(Tmptxt, .Font)          'first grab the size of the text
                        e.Graphics.DrawString(Tmptxt, .Font, Brsh, PosnX, PosnY)    'then draw it
                        PosnX += CSng(TextSize.Width - txtMargin)                   'then bump the x offset, less the margin allowance
                        Tmptxt = Nothing                                            'clear the temp text buffer
                    End If
                    PosnX += CSng((iChar And 127))                                  'finally, bump the x offset by the spaceing code (pixel count + 128)
                Case 13                                                             'vbCr?
                    If Len(Tmptxt) <> 0 Then                                        'yes, so dump the temp text if it has accumulated data
                        e.Graphics.DrawString(Tmptxt, .Font, Brsh, PosnX, PosnY)    'then draw it
                        Tmptxt = Nothing                                            'clear the temp text buffer
                    End If
                    PosnX = CSng(e.ClipRectangle.Left)                              'reset the X offset to the left side
                    PosnY += Yinc                                                   'bump the line index to the next line position
                Case 32                                                             'Space?
                    If Len(Tmptxt) <> 0 Then                                        'yes, so dump the temp text if it has accumulated data
                        TextSize = TextRenderer.MeasureText(Tmptxt, .Font)          'first grab the size of the text
                        e.Graphics.DrawString(Tmptxt, .Font, Brsh, PosnX, PosnY)    'then draw it
                        PosnX += CSng(TextSize.Width - txtMargin)                   'then bump the x offset, less the margin allowance
                        Tmptxt = Nothing                                            'clear the temp text buffer
                    End If
                    PosnX += SpcSize                                                'bump index by a space size
                Case 10                                                             'vbLf? If so, ignore it
                Case Else                                                           'normal character
                    Tmptxt &= Chr(iChar)                                            'add the character to the temp text buffer
            End Select
        Next

        If Len(Tmptxt) <> 0 Then                                                    'dump the temp text if it has accumulated data
            e.Graphics.DrawString(Tmptxt, .Font, Brsh, PosnX, PosnY)                'then draw it
        End If
        Brsh.Dispose()                                                              'finally, dispose of the used brush resource
    End With
End Sub

2
我认为OP所需要的是这个链接下的内容:http://en.wikipedia.org/wiki/Justification_(typesetting),然后找到下面这个标题:
Justified (flush left and right)
很遗憾,没有简单的方法来实现这一点。您需要像Damith建议的那样创建一个自定义控件,而即使这样也不容易,因为每次您输入一个字母时,您的文本间距将会缩小,看起来很奇怪。如果您想要做一个只读的文本框,那是可以做到的,但如果您希望用户向其中添加文本...我认为您需要有一个非常好的理由来花时间实现这个功能。

1

对齐方式可以设置为居中,以便左右两端对齐

textBox1.TextAlign = HorizontalAlignment.Center;

2
不,居中文本和对齐并不相同。 - Po-ta-toe
2
@downvoter不公平地对此进行了负评,他的回答在OP编辑问题并声明他不想居中之前就已经在这里了。 - General Grey
2
文本对齐是小学就教的简单概念,不应需要解释。 - Po-ta-toe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接