Fix for the RichTextBox Undo Information Lost When Retrieving Text
Posted
Friday, August 06, 2004 6:20 PM
by
pwelter34
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)]
struct GETTEXTEX
{
public Int32 cb;
public Int32 flags;
public Int32 codepage;
public IntPtr lpDefaultChar;
public IntPtr lpUsedDefChar;
}
[StructLayout(LayoutKind.Sequential)]
struct GETTEXTLENGTHEX
{
public Int32 flags;
public Int32 codepage;
}
const int WM_USER = 0x0400;
// RichEdit messages (Richedit.h)
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()
{
}
public override string Text
{
get
{
GETTEXTLENGTHEX getLength = new GETTEXTLENGTHEX();
getLength.flags = GTL_CLOSE; //get buffer size
getLength.codepage = 1200; //Unicode
int textLength = SendMessage(base.Handle,
EM_GETTEXTLENGTHEX,
ref getLength, 0);
GETTEXTEX getText = new GETTEXTEX();
getText.cb = textLength+2; //add space for null terminator
getText.flags = GT_DEFAULT;
getText.codepage = 1200; //Unicode
StringBuilder sb = new StringBuilder(getText.cb);
SendMessage(base.Handle,
EM_GETTEXTEX,
ref getText, sb);
return sb.ToString();
}
set
{
base.Text = value;
}
}
public override int TextLength
{
get
{
GETTEXTLENGTHEX getLength = new GETTEXTLENGTHEX();
getLength.flags = GTL_DEFAULT; //Returns the number of characters
getLength.codepage = 1200; //Unicode
return SendMessage(base.Handle,
EM_GETTEXTLENGTHEX,
ref getLength, 0);
}
}
}
}
~ Paul