How do I return RTF for ALL selected text, including any invisible text, when .NET version is 4.7 or higher?

Robert Gustafson 606 Reputation points
2023-01-10T06:42:02.02+00:00

WHAT I HAVE: Visual Basic 2019, WinForms, .NET Framework 4+, RichTextBox

MY PROBLEM: For .NET Framework 4.6 and lower, SelectedRtf returns any and all hidden (invisible) text in a RichTextBox selection, even when the hidden text isn't surrounded within the selection by visible text. For .NET Framework 4.7 and higher, however, this is not the case! Sometimes in such an environment the RTF for hidden selected text isn't included in the property string (though it's still stored in the document) if the hidden part is at the beginning or end of the selection. (This anomaly doesn't exist for Rtf, which returns the RTF for the entire document, including all hidden text.) For that matter, hidden plain text is only returned for Text and SelectedText for pre-.NET 4.7, but there are "hidden properties"--particularly "WindowText", "CurSelStart", and "CurSelEnd"--that allow one to get the hidden plain text in the document or a selection thereof, using reflection, in a .NET 4.7+ situation. But that's for getting hidden plain text. How do I guarantee that all hidden RTF text is retrieved for a selection, regardless of .NET version?

Please provide any answer ASAP, in VB.NET, and as simply as possible.

PS. Is there a way to determine if some, but not necessarily all, text in a selection is protected (or hidden), short of parsing SelectedRtf for "\protect " (or "\v ")? The fact that SelectionProtected is True only when an entire selection is protected, yet the Protected event fires when an attempt is made to modify selected text when any is protected, creates an awkward programming situation. (For instance,

If Not rtb.SelectionProtected Then
   rtb.SelectedRtf = SomeString
End If

will still trigger the Protected event if the selection is semi-protected!)

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,828 questions
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,568 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Reza Aghaei 4,936 Reputation points MVP
    2023-02-07T11:36:06.33+00:00

    I've seen some issues in the past that I needed to upgrade the RichEdit to a higher version, for example look at my answers about selection highlight, or special characters, but I never needed to downgrade.

    Anyways, if you want to use a specific version of RichTextBox as suggested in the comments, then you need to load the DLL of that specific version and create the class of the specific version. For example, the following code is for using RichEdit20W from RichEd20.DLL library:

    Imports System
    Imports System.ComponentModel
    Imports System.Runtime.InteropServices
    Imports System.Windows.Forms
    
    Public Class ExRichText
        Inherits RichTextBox
        <DllImport("kernel32.dll", EntryPoint:="LoadLibraryW", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Private Shared Function LoadLibraryW(ByVal s_File As String) As IntPtr
        End Function
        Private Shared Function LoadLibrary(ByVal s_File As String) As IntPtr
            Dim [module] = LoadLibraryW(s_File)
            If [module] <> IntPtr.Zero Then Return [module]
            Dim [error] = Marshal.GetLastWin32Error()
            Throw New Win32Exception([error])
        End Function
        Protected Overrides ReadOnly Property CreateParams As CreateParams
            Get
                Dim cp = MyBase.CreateParams
                Try
                    LoadLibrary("RichEd20.DLL")
                    cp.ClassName = "RichEdit20W"
                Catch
                End Try
                Return cp
            End Get
        End Property
    End Class
    

    If you want to adjust the rich edit to use specific version, you can use the following classes and dlls based on what I see in source code of RichTextBox:

    Public Class RichEditConstants
        Public Const RICHEDIT_DLL10 As String = "RichEd32.DLL"
        Public Const RICHEDIT_DLL20 As String = "RichEd20.DLL"
        Public Const RICHEDIT_DLL30 As String = "RichEd20.DLL"
        Public Const RICHEDIT_DLL41 As String = "MsftEdit.DLL"
        Public Const RICHEDIT_CLASS10A As String = "RICHEDIT"
        Public Const RICHEDIT_CLASS20W As String = "RichEdit20W"
        Public Const RICHEDIT_CLASS30W As String = "RichEdit20W"
        Public Const RICHEDIT_CLASS41W As String = "RICHEDIT50W"
    End Class