Search code examples
vb.netvisual-studio-2017richtextbox

Line spacing in richtextbox vb.net


I have a richtextbox that is filled with the result of a SqlServer query on vb.net. The result joins all items horizontally and when reaching the richtextbox margin it will wrap the line.

Code:

   'Function of loading data into Datagridview

   Private Sub entregue()
    dgv1.Rows.Clear()
    Cursor.Current = Cursors.WaitCursor
    Dim consultando As New frm_aguarde_consultando
    consultando.Show()
    ' Set cursor as hourglass
    Application.DoEvents()

    Dim ano, mes, dia As Integer
    Dim var1data, var2data As Date
    Dim dinicio, dfim As String

    var1data = DateTimePicker1.Value '.ToString.Substring(0, 10)
    dia = var1data.Day
    mes = var1data.Month
    ano = var1data.Year
    dinicio = ano & "-" & mes & "-" & dia

    var2data = DateTimePicker2.Value
    dia = var2data.Day
    mes = var2data.Month
    ano = var2data.Year
    dfim = ano & "-" & mes & "-" & dia

    Using sqlcoon As SqlConnection = GetConnectionsql()
        Dim READER As SqlDataReader
        'ENTREGUE
        Try
            sqlcoon.Open()
            Dim Query As String
            Query = "select MOV_IDENTIFICACAO,MOV_PROTOCOLO,MOV_DATADOC,MOV_SITUACAO,MOV_DATAENTREGA,MOV_HORAENTREGA,MOV_SITEND_CODIGO
                    from movimento where MOV_DATADOC = '" & dinicio & "' 
                    AND MOV_CLI_CODIGO = '" & txtcod.Text & "' AND MOV_SITUACAO = '" & "E" & "'
                    AND CAST(MOV_DATAENTREGA AS DATE) = '" & dfim & "' "


            Dim COMMAND As SqlCommand = New SqlCommand(Query, sqlcoon)

            READER = COMMAND.ExecuteReader

            While READER.Read
                Dim MOV_IDENTIFICACAO = READER("MOV_IDENTIFICACAO")
                Dim MOV_DATADOC = READER("MOV_DATADOC")
                Dim MOV_DATAENTREGA = READER("MOV_DATAENTREGA")
                Dim MOV_PROTOCOLO = READER("MOV_PROTOCOLO")
                Dim MOV_SITUACAO = READER("MOV_SITUACAO")
                Dim MOV_SITEND_CODIGO = READER("MOV_SITEND_CODIGO")
                dgv1.Rows.Add(MOV_IDENTIFICACAO, MOV_PROTOCOLO, MOV_DATADOC, MOV_SITUACAO, MOV_DATAENTREGA, MOV_SITEND_CODIGO)

            End While
            READER.Close()
            sqlcoon.Close()

            For Each linha In dgv1.Rows
                Dim altura As Integer = 17
                linha.height = altura

            Next

            If dgv1.Rows.Count >= 0 Then
                ' Set cursor as default arrow
                Cursor.Current = Cursors.Default

                ' Hide the please wait form
                consultando.Hide()

            End If
        Catch ex As SqlException
            MessageBox.Show(ex.Message)
        Finally
            ' sqlcoon.Dispose()


        End Try

        sqlcoon.Open()

        Try


            For r As Integer = 0 To dgv1.Rows.Count - 1
                Dim COMMAND3 As SqlCommand
                Dim READER3 As SqlDataReader
                Dim Query_3 As String

                Query_3 = "select IMOV_CODIGORECBTO from imovimento where IMOV_MOV_IDENTIFICACAO ='" & dgv1.Rows(r).Cells(0).Value.ToString & "'"

                COMMAND3 = New SqlCommand(Query_3, sqlcoon)
                READER3 = COMMAND3.ExecuteReader

                While READER3.Read
                    Dim IMOV_CODIGORECBTO = READER3("IMOV_CODIGORECBTO")
                    'DataGridView1.Columns(6).HeaderCell.Value = "ID"
                    dgv1.Rows(r).Cells(6).Value = IMOV_CODIGORECBTO
                End While
                READER3.Close()

            Next
            dgv1.Sort(dgv1.Columns(6), ListSortDirection.Ascending)
            sqlcoon.Close()
        Catch ex As SqlException
            MsgBox(ex.Message)
        End Try


    End Using

End Sub
 
'Function of loading data into Richtextbox

Private Sub preenchimento_rchrelatorio()
Dim entregue = "ENTREGUE"
rchrelatorio.Text += entregue & Environment.NewLine & Environment.NewLine

For r As Integer = 0 To dgv1.Rows.Count - 1
    'richtextbox
    rchrelatorio.Text += dgv1.Rows(r).Cells(0).Value & "   "

Next

Dim totalentregue = "TOTAL:  " & dgv1.Rows.Count

rchrelatorio.Text += Environment.NewLine & Environment.NewLine & totalentregue & Environment.NewLine & Environment.NewLine

end sub

Result:

enter image description here

How can the spacing between the lines of this rich text box be increased so that it looks like this:

enter image description here

Is there any possible way to achieve the result on vb.net ? I saw many forms in C# but I couldn't convert.


Solution

  • To be able to solve this way:

     Imports System.Runtime.InteropServices
    
     Public Class frm_relatorio_entregas
    
      Private Structure Paraformat2
        Dim cbSize As UInteger
        Dim dwMask As UInteger
        Dim wNumbering As UInt16
        Dim wEffects As UInt16
        Dim dxStartIndent As Integer
        Dim dxRightIndent As Integer
        Dim dxOffset As Integer
        Dim wAlignment As UInt16
        Dim cTabCount As Int16
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)>
        Public rgxTabs() As Integer
        Dim dySpaceBefore As Integer
        Dim dySpaceAfter As Integer
        Dim dyLineSpacing As Integer
        Dim sStyle As Int16
        Dim bLineSpacingRule As Byte
        Dim bOutlineLevel As Byte
        Dim wShadingWeight As UInt16
        Dim wShadingStyle As UInt16
        Dim wNumberingStart As UInt16
        Dim wNumberingStyle As UInt16
        Dim wNumberingTab As UInt16
        Dim wBorderSpace As UInt16
        Dim wBorderWidth As UInt16
        Dim wBorders As UInt16
    End Structure
    
    
    <DllImport("user32", CharSet:=CharSet.Auto)>
    Private Shared Function SendMessage(ByVal hWnd As HandleRef, ByVal msg As Integer, ByVal wParam As Integer, ByRef lParam As Paraformat2) As Integer
    End Function
    
    
    Const EM_LINEFROMCHAR As Integer = &HC9
    Const EM_LINEINDEX As Integer = &HBB
    
    Const EM_SETPARAFORMAT As Integer = &H447
    Const PFM_LINESPACING As Integer = &H100
    
     Public Sub SelLineSpacing(ByVal rtbTarget As RichTextBox, ByVal SpacingRule As Byte, Optional ByVal LineSpacing As Integer = 20)
    
        Dim Para As New Paraformat2
    
        With Para
            ReDim .rgxTabs(31)
    
            .cbSize = CUInt(Marshal.SizeOf(Para))
            .dwMask = PFM_LINESPACING
            .bLineSpacingRule = SpacingRule
            .dyLineSpacing = LineSpacing
        End With
    
        Dim result As Integer = SendMessage(New HandleRef(rtbTarget, rtbTarget.Handle), EM_SETPARAFORMAT, 1, Para)
    
        If result = 0 Then
            MessageBox.Show("EM_SETPARAFORMAT Failed")
        End If
    End Sub
    
       Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        ' some dummy text to test with
        rchrelatorio.AppendText("2323" & vbCrLf)
        rchrelatorio.AppendText("2323" & vbCrLf)
        rchrelatorio.AppendText("2323" & vbCrLf)
        rchrelatorio.AppendText("2323" & vbCrLf)
    
        ' optionally select existing text
        ' so as to apply changes to the existing text
        ' as well as future text
        rchrelatorio.SelectAll()
    
        Dim s As String
        s = InputBox("Insert a RULE number (0 to 5)")
    
        ' SpacingRule
        ' Type of line spacing. To use this member, set the PFM_SPACEAFTER flag in the dwMask member. This member can be one of the following values.
        ' 0 - Single spacing. The dyLineSpacing member is ignored.
        ' 1 - One-and-a-half spacing. The dyLineSpacing member is ignored.
        ' 2 - Double spacing. The dyLineSpacing member is ignored.
        ' 3 - The dyLineSpacing member specifies the spacingfrom one line to the next, in twips. However, if dyLineSpacing specifies a value that is less than single spacing, the control displays single-spaced text.
        ' 4 - The dyLineSpacing member specifies the spacing from one line to the next, in twips. The control uses the exact spacing specified, even if dyLineSpacing specifies a value that is less than single spacing.
        ' 5 - The value of dyLineSpacing / 20 is the spacing, in lines, from one line to the next. Thus, setting dyLineSpacing to 20 produces single-spaced text, 40 is double spaced, 60 is triple spaced, and so on.
    
    
        Dim ruleNum As Byte
    
        ' returns ruleNum as the number input by the user,
        ' or 255 if user input is bad
        If Not Byte.TryParse(s, ruleNum) Then ruleNum = 255
    
        Select Case ruleNum
            Case 0 ' Single spacing.
                SelLineSpacing(rchrelatorio, ruleNum)
    
            Case 1 ' One-and-a-half spacing.
                SelLineSpacing(rchrelatorio, ruleNum)
    
            Case 2 ' Double spacing.
                SelLineSpacing(rchrelatorio, ruleNum)
    
            Case 3 ' Spacing in Twips (1440 twips = 1 inch) : ignores spacing less than Single Spacing
                SelLineSpacing(rchrelatorio, ruleNum, 720)
    
            Case 4 ' Spacing in Twips (1440 twips = 1 inch) : allows spacing less than Single Spacing
                SelLineSpacing(rchrelatorio, ruleNum, 72)
    
            Case 5 ' Spacing in 20ths of a line (40 = Double Spacing : 100 = 5 line Spacing)
                SelLineSpacing(rchrelatorio, ruleNum, 100)
    
            Case Else
                MessageBox.Show("rule number must be between 0 amd 5")
        End Select
    
    End Sub
    
     End Class
    

    With the code above, at the moment when the richtextbox (rchrelatorio) is filled with the text and then the button is pressed, it generates a dialog box where it asks the spacing size between 0 and 5, and then just run to celebrate.

    Important detail.

    a problem if in case you want to print the formatted content, you will have to use a shipping method that does not change the configured richtextbox formatting.