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);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() { }[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">
getLength.codepage = 1200; //Unicode int textLength = SendMessage(base.Handle, EM_GETTEXTLENGTHEX, ref getLength, 0);</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">
getText.flags = GT_DEFAULT; getText.codepage = 1200; //Unicode StringBuilder sb = new StringBuilder(getText.cb);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">
getLength.codepage = 1200; //Unicode return SendMessage(base.Handle, EM_GETTEXTLENGTHEX, ref getLength, 0);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">
} } } }
~ Paul