As opposed to the TextBox control which use CrLf
line endings the RichTextBox control use Lf
line endings. I don't want that. I need consistency. I need a RichTextBox control whom use CrLf line endings.
I opened the control in reflector and noticed that the getter of the Text
property calls the following function:
Private Function StreamOut(ByVal flags As Integer) As String
'...
Me.StreamOut(data, flags, False)
'...
End Function
Which ends up calling:
Private Sub StreamOut(ByVal data As Stream, ByVal flags As Integer, ByVal includeCrLfs As Boolean)
'...
Dim es As New EDITSTREAM
'...
ElseIf includeCrLfs Then
num = (num Or &H20)
Else
'...
es.dwCookie = DirectCast(num, IntPtr)
'...
End Sub
And as you can see, the includeCrLfs
parameter will always be False
.
So I subclassed the control and intercepted the EM_STREAMOUT message. The LParam
of this message contains the pointer to the EDITSTREAM structure. I appended the &H20
flag as seen in the function above, but this didn't work. The Text
property started to return an empty string. I believe that I might have to remove/append other flags, but I have no clue as to which flags. Also, MSDN do not provide any hints other than application-defined value.
dwCookie
Specifies an application-defined value that the rich edit control passes to the EditStreamCallback callback function specified by the pfnCallback member.
Here's my subclassed control:
Public Class UIRichTextBox
Inherits System.Windows.Forms.RichTextBox
Private Sub EmStreamOut(ByRef m As Message)
Dim es As New EDITSTREAM
es = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(EDITSTREAM)), EDITSTREAM)
If (IntPtr.Size = 4) Then
Dim cookie As Int32 = es.dwCookie.ToInt32()
'cookie = (cookie Or &H20I) '<- Didn't work
es.dwCookie = New IntPtr(cookie)
Else
Dim cookie As Int64 = es.dwCookie.ToInt64()
'cookie = (cookie Or &H20L) '<- Didn't work
es.dwCookie = New IntPtr(cookie)
End If
Marshal.StructureToPtr(es, m.LParam, True)
MyBase.WndProc(m)
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case EM_STREAMOUT
Me.EmStreamOut(m)
Exit Select
Case Else
MyBase.WndProc(m)
Exit Select
End Select
End Sub
Private Const EM_STREAMOUT As Integer = &H44A
Private Delegate Function EDITSTREAMCALLBACK(ByVal dwCookie As IntPtr, ByVal buf As IntPtr, ByVal cb As Integer, <Out()> ByRef transferred As Integer) As Integer
<StructLayout(LayoutKind.Sequential)> _
Private Class EDITSTREAM
Public dwCookie As IntPtr = IntPtr.Zero
Public dwError As Integer
Public pfnCallback As EDITSTREAMCALLBACK
End Class
End Class
Update
So it turns out that the flags are not undocumented at all. They are part of the EM_GETEDITSTYLE and EM_SETEDITSTYLE messages. But as you can see, the flag is obsolete.
SES_USECRLF Obsolete. Do not use.
So I guess I'm back at square one overriding the text property.
Public Overrides Property Text() As String
Get
Dim value As String = MyBase.Text
If (Not value Is Nothing) Then
value = value.Replace(ChrW(13), "")
value = value.Replace(ChrW(10), Environment.NewLine)
End If
Return value
End Get
Set(value As String)
MyBase.Text = value
End Set
End Property