【发布时间】:2014-07-27 18:39:52
【问题描述】:
与使用CrLf 行尾的TextBox 控件相反,RichTextBox 控件使用Lf 行尾。我不想要那个。我需要一致性。我需要一个使用 CrLf 行尾的 RichTextBox 控件。
我在反射器中打开控件,发现Text属性的getter调用了如下函数:
Private Function StreamOut(ByVal flags As Integer) As String
'...
Me.StreamOut(data, flags, False)
'...
End Function
最终调用:
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
如您所见,includeCrLfs 参数将始终为False。
所以我将控件子类化并截获了EM_STREAMOUT 消息。此消息的LParam 包含指向EDITSTREAM 结构的指针。我在上面的函数中附加了&H20 标志,但这不起作用。 Text 属性开始返回一个空字符串。我相信我可能必须删除/附加其他标志,但我不知道哪些标志。此外,除了应用程序定义的值之外,MSDN 不提供任何提示。
dwCookie
指定富编辑控件传递给 pfnCallback 成员指定的 EditStreamCallback 回调函数的应用程序定义值。
这是我的子类控件:
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
更新
事实证明,这些标志根本没有记录在案。它们是EM_GETEDITSTYLE 和EM_SETEDITSTYLE 消息的一部分。但正如您所见,该标志已过时。
SES_USECRLF 已过时。不要使用。
所以我想我又回到了第一个覆盖文本属性的地方。
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
【问题讨论】:
-
与其修补未记录的内部结构,为什么不将输出字符串中的 lf 替换为 crlf?
-
我没有发现问题。不同的是,不,它没有。事实上,我可以开箱即用地复制+粘贴到记事本中,然后它们被转换为 CRLF,当将文本保存到文件时,它们也最终成为 CRLF (0D+0A)。但我可以确认它们仅在 RichTextBox 中是 LF。哦,好吧,如果比较文本,我可以看到这将是一个问题;o 或者只是剥离所有 0D。此外,richtextbox 本身在开头附加了大约 20-30 个 ascii 字符,这些字符不会出现在输出中。
-
哦,这 30 个字符是:
System.Windows.Forms.RichTextBox, Text:lmao ;p 当您执行 .ToString 时 :) WTH? ;pfor each line in RTB.lines:\ -
啊,如果你使用
RichTextBox.Rtf属性,它会返回一个带有 CRLF (0D & 0A) 的字符串来替换 LF (0A)。所以那里有内部代码。您还可以设置该属性以从我想的文件中加载文本。但它也返回一些用于字体等的 RTF 格式代码:\ -
C#相关问题:RichTextBox Newline Conversion?最近才遇到这个,很奇怪的行为。
标签: vb.net winforms winapi richtextbox