Fix for the RichTextBox Undo Information Lost When Retrieving Text

In my work with the RichTextBox control, I've often run into this bug in the RichEdit control. You can read more about this bug by looking at Microsoft's knowledge base article - 812943. If you are unable to get the latest Riched20.dll then you can get around the problem using the following code …
 
 
using System; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms;

namespace TextUndoBuffer { /// <summary> /// Work around for KB 812943, The RichEdit Control Undo /// Information May Be Lost When the Control Retrieves Text. /// </summary> public class RichTextBoxEx : RichTextBox { [DllImport("user32.dll", EntryPoint="SendMessage", CharSet=CharSet.Auto )] static extern int SendMessage(IntPtr hWnd, int msg,

ref GETTEXTEX wParam, System.Text.StringBuilder lParam); [DllImport("user32.dll", EntryPoint="SendMessage", CharSet=CharSet.Auto )] static extern int SendMessage(IntPtr hWnd, int msg,
ref GETTEXTLENGTHEX wParam, int lParam);

 [StructLayout(LayoutKind.Sequential)]
 </span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> GETTEXTEX
 {
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Int32    cb;
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Int32    flags;
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Int32    codepage;
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> IntPtr   lpDefaultChar;
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> IntPtr   lpUsedDefChar;
 }

 [StructLayout(LayoutKind.Sequential)]
 </span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> GETTEXTLENGTHEX
 {
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Int32    flags;
     </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Int32    codepage;
 }
 </span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> WM_USER </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0x0400</span><span style="COLOR: #000000">;

 </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> RichEdit messages (Richedit.h)</span><span style="COLOR: #008000">

const int EM_GETTEXTEX =(WM_USER + 94); const int EM_GETTEXTLENGTHEX =(WM_USER + 95); // Flags for the GETEXTEX data structure const int GT_DEFAULT = 0; // Flags for the GETTEXTLENGTHEX data structure const int GTL_DEFAULT = 0; // Do default (return # of chars) const int GTL_CLOSE = 4; // Fast computation of a "close" answer public RichTextBoxEx() { }

 </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000"> Text
 {
     </span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">
     {
         GETTEXTLENGTHEX getLength </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> GETTEXTLENGTHEX();
         getLength.flags </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> GTL_CLOSE; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">get buffer size</span><span style="COLOR: #008000">

getLength.codepage = 1200; //Unicode int textLength = SendMessage(base.Handle, EM_GETTEXTLENGTHEX, ref getLength, 0);

         GETTEXTEX getText </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> GETTEXTEX();
         getText.cb </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> textLength</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">add space for null terminator</span><span style="COLOR: #008000">

getText.flags = GT_DEFAULT; getText.codepage = 1200; //Unicode StringBuilder sb = new StringBuilder(getText.cb);

         SendMessage(</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">.Handle, 
                EM_GETTEXTEX, 
                </span><span style="COLOR: #0000ff">ref</span><span style="COLOR: #000000"> getText, sb);
     
          </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> sb.ToString();
     }
     </span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">
     {
         </span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">.Text </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> value;
     }
 }

 </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> TextLength
 {
     </span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">
     {
         GETTEXTLENGTHEX getLength </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> GETTEXTLENGTHEX();
         getLength.flags </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> GTL_DEFAULT; </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Returns the number of characters</span><span style="COLOR: #008000">

getLength.codepage = 1200; //Unicode return SendMessage(base.Handle, EM_GETTEXTLENGTHEX, ref getLength, 0);
} } } }

 
~ Paul

4 Comments

Comments have been disabled for this content.