Hi!
I would like to turn of redrawing of richtextbox while procesing text inside it.
I have found one solution, but I can't get it to work.
code:
SendMessage( new HandleRef( this, Handle ),
WM_SETREDRAW, 0, 0 );
Error Message I get:
The name 'SendMessage' does not exist in the current context

How to turn off redrawing?
ruper
I have already tried that, but it isn't working. Perhaps I am not using it correctly
I tried it like this:
MyRichTextBox.SuspendLayout();
PS: Processing text = finding and replacing text in RichTextBox.
Peter Mourfield
hi Karthikeya,
You code for the CustomRichBox control is awesome.
However I could not get to do the following
Given a startposition and length, create an underline for that word in the richtextbox control. How can we achieve this the method can be something like,
customRichTextBoxControl.MarkUnderline(int startposition, int length, UnderlineStyle style, UnderlineColor color);
what would be the sendmessage parameters here
Any help would be greately appreciated.
Istvan Majercsik
i copied your code without asking your permission first.
Please forgive me.
is it ok to work with your code
chrisk13
juanborde
Karthikeya Pavan Kumar .B - I thought your code and explanation was awesome as well. I'm now wondering if you can help me. My scenario follows:
I'm using VSTS 2005 to do automated testing. The tests are working fine; however, the code that I'm testing uses the statement MessageBox.Show (by design). I don't want to comment out the messageboxes before running my tests.
I've created a DB for my tests. The tests are pulling the data that needs to be validated from the DB via a DataReader placed inside a While loop...so one test can actually validate numerous inputs. Of course, when I run the tests, the message boxes from the code that I'm testing are being displayed each time through the loop.
I don't want to keep having to push the OK button on the message boxes when I'm running my tests. I want to be able to walk away from my PC, while the tests are executing. However, the message boxes halt test execution until the message box's OK button is pushed. So, if there are 200 entries in my DB, I'd have to push the {Enter} key 200 times before my test will be complete.
If you could show me sample code as to how I can capture and handle the Messages, I'd be most grateful. I've tried a BackgroundWorker and the SendKeys.Send("{Enter}") function, but it's too unpredictable. Sometimes it will work, sometimes it won't.
Any help you can give me would be greatly appreciated.
P.S. As mentioned earlier, I'm using C# in VSTS 2005...will that code be much different from C# Express Edition code
gtimofte
Sorry for that..Probably my reply was not clear anyways here is the sample code.. Let me know if this works for you
/* ========================== */
/* ========================== */
/* ========================== */
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace FlatControls2
{
/// <summary>
/// Represents a custom rich text box control with additional properties for internal use.
/// </summary>
public class CustomRichTextBox : RichTextBox
{
#region Private fields and constructors
private int _Updating = 0;
private int _OldEventMask = 0;
/// <summary>
/// Initializes a new instance of the <see cref="CustomRichTextBox"/> class.
/// </summary>
public CustomRichTextBox()
{
/*
* The following list describes which versions of Rich Edit are included in which releases of Microsoft WindowsR.
*
* Windows XP SP1 Includes Rich Edit 4.1, Rich Edit 3.0, and a Rich Edit 1.0 emulator.
* Windows XP Includes Rich Edit 3.0 with a Rich Edit 1.0 emulator.
* Windows Me Includes Rich Edit 1.0 and 3.0.
* Windows 2000 Includes Rich Edit 3.0 with a Rich Edit 1.0 emulator.
* Windows NT 4.0 Includes Rich Edit 1.0 and 2.0.
* Windows 98 Includes Rich Edit 1.0 and 2.0.
* Windows 95 Includes only Rich Edit 1.0. However, Riched20.dll is compatible with Windows 95 and may be installed by an application that requires it.
*/
// Remove any XP style applied to the rich text box.
RemoveTheme();
}
#endregion
#region Windows API
private const int WM_SETREDRAW = 0x0B;
private const int EM_SETEVENTMASK = 0x0431;
private const int EM_SETCHARFORMAT = 0x0444;
private const int EM_GETCHARFORMAT = 0x043A;
private const int EM_GETPARAFORMAT = 0x043D;
private const int EM_SETPARAFORMAT = 0x0447;
private const int EM_SETTYPOGRAPHYOPTIONS = 0x04CA;
private const int CFM_UNDERLINETYPE = 0x800000;
private const int CFM_BACKCOLOR = 0x4000000;
private const int CFE_AUTOBACKCOLOR = 0x4000000;
private const int SCF_SELECTION = 0x01;
private const int PFM_ALIGNMENT = 0x08;
private const int TO_ADVANCEDTYPOGRAPHY = 0x01;
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, ref CHARFORMAT2 lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, ref PARAFORMAT2 lParam);
[DllImport("uxtheme.dll", CharSet=CharSet.Unicode)]
private static extern int SetWindowTheme(
HandleRef hWnd,
[MarshalAs(UnmanagedType.LPWStr)]
string pszSubAppName,
[MarshalAs(UnmanagedType.LPWStr)]
string pszSubIdList);
/// <summary>
/// Contains information about character formatting in a rich edit control.
/// </summary>
/// <remarks><see cref="CHARFORMAT"/> works with all Rich Edit versions.</remarks>
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMAT
{
public int cbSize;
public uint dwMask;
public uint dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public char[] szFaceName;
}
/// <summary>
/// Contains information about character formatting in a rich edit control.
/// </summary>
/// <remarks><see cref="CHARFORMAT2"/> requires Rich Edit 2.0.</remarks>
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMAT2
{
public int cbSize;
public uint dwMask;
public uint dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public char[] szFaceName;
public short wWeight;
public short sSpacing;
public int crBackColor;
public int LCID;
public uint dwReserved;
public short sStyle;
public short wKerning;
public byte bUnderlineType;
public byte bAnimation;
public byte bRevAuthor;
}
/// <summary>
/// Contains information about paragraph formatting in a rich edit control.
/// </summary>
/// <remarks><see cref="PARAFORMAT"/> works with all Rich Edit versions.</remarks>
[StructLayout(LayoutKind.Sequential)]
private struct PARAFORMAT
{
public int cbSize;
public uint dwMask;
public short wNumbering;
public short wReserved;
public int dxStartIndent;
public int dxRightIndent;
public int dxOffset;
public short wAlignment;
public short cTabCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public int[] rgxTabs;
}
/// <summary>
/// Contains information about paragraph formatting in a rich edit control.
/// </summary>
/// <remarks><see cref="PARAFORMAT2"/> requires Rich Edit 2.0.</remarks>
[StructLayout(LayoutKind.Sequential)]
private struct PARAFORMAT2
{
public int cbSize;
public uint dwMask;
public short wNumbering;
public short wReserved;
public int dxStartIndent;
public int dxRightIndent;
public int dxOffset;
public short wAlignment;
public short cTabCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public int[] rgxTabs;
public int dySpaceBefore;
public int dySpaceAfter;
public int dyLineSpacing;
public short sStyle;
public byte bLineSpacingRule;
public byte bOutlineLevel;
public short wShadingWeight;
public short wShadingStyle;
public short wNumberingStart;
public short wNumberingStyle;
public short wNumberingTab;
public short wBorderSpace;
public short wBorderWidth;
public short wBorders;
}
#endregion
#region Property: SelectionUnderlineStyle
/// <summary>
/// Gets or sets the underline style to apply to the current selection or insertion point.
/// </summary>
/// <value>A <see cref="UnderlineStyle"/> that represents the underline style to
/// apply to the current text selection or to text entered after the insertion point.</value>
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public UnderlineStyle SelectionUnderlineStyle
{
get
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
// Get the underline style
SendMessage(new HandleRef(this, Handle), EM_GETCHARFORMAT, SCF_SELECTION, ref fmt);
if ((fmt.dwMask & CFM_UNDERLINETYPE) == 0)
{
return UnderlineStyle.None;
}
else
{
byte style = (byte)(fmt.bUnderlineType & 0x0F);
return (UnderlineStyle)style;
}
}
set
{
// Ensure we don't alter the color
UnderlineColor color = SelectionUnderlineColor;
// Ensure we don't show it if it shouldn't be shown
if (value == UnderlineStyle.None)
color = UnderlineColor.Black;
// Set the underline type
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = CFM_UNDERLINETYPE;
fmt.bUnderlineType = (byte)((byte)value | (byte)color);
SendMessage(new HandleRef(this, Handle), EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
}
}
#endregion
#region Property: SelectionUnderlineColor
/// <summary>
/// Gets or sets the underline color to apply to the current selection or insertion point.
/// </summary>
/// <value>A <see cref="UnderlineColor"/> that represents the underline color to
/// apply to the current text selection or to text entered after the insertion point.</value>
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public UnderlineColor SelectionUnderlineColor
{
get
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
// Get the underline color
SendMessage(new HandleRef(this, Handle), EM_GETCHARFORMAT, SCF_SELECTION, ref fmt);
if ((fmt.dwMask & CFM_UNDERLINETYPE) == 0)
{
return UnderlineColor.None;
}
else
{
byte style = (byte)(fmt.bUnderlineType & 0xF0);
return (UnderlineColor)style;
}
}
set
{
// If the an underline color of "None" is specified, remove underline effect
if (value == UnderlineColor.None)
{
SelectionUnderlineStyle = UnderlineStyle.None;
}
else
{
// Ensure we don't alter the style
UnderlineStyle style = SelectionUnderlineStyle;
// Ensure we don't show it if it shouldn't be shown
if (style == UnderlineStyle.None)
value = UnderlineColor.Black;
// Set the underline color
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = CFM_UNDERLINETYPE;
fmt.bUnderlineType = (byte)((byte)style | (byte)value);
SendMessage(new HandleRef(this, Handle), EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
}
}
}
#endregion
#region Property: SelectionBackColor
/// <summary>
/// Gets or sets the background color to apply to the
/// current selection or insertion point.
/// </summary>
/// <value>A <see cref="Color"/> that represents the background color to
/// apply to the current text selection or to text entered after the insertion point.</value>
/// <remarks>
/// <para>A value of Color.Empty indicates that the default background color is used.</para>
/// <para>If the selection contains more than one background
/// color, then this property will indicate it by
/// returning Color.Empty.</para>
/// </remarks>
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Color SelectionBackColor
{
get
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
// Get the background color
SendMessage(new HandleRef(this, Handle), EM_GETCHARFORMAT, SCF_SELECTION, ref fmt);
// Default to Color.Empty as there could be
// several colors present in this selection
if ((fmt.dwMask & CFM_BACKCOLOR) == 0)
return Color.Empty;
// Default to Color.Empty if the background color is automatic
if ((fmt.dwEffects & CFE_AUTOBACKCOLOR) == CFE_AUTOBACKCOLOR)
return Color.Empty;
// Deal with the weird Windows color format
return ColorTranslator.FromWin32(fmt.crBackColor);
}
set
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = CFM_BACKCOLOR;
if (value.IsEmpty)
fmt.dwEffects = CFE_AUTOBACKCOLOR;
else
fmt.crBackColor = ColorTranslator.ToWin32(value);
// Set the background color
SendMessage(new HandleRef(this, Handle), EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
}
}
#endregion
#region Property: SelectionAlignment
/// <summary>
/// Gets or sets the text alignment to apply to the current
/// selection or insertion point.
/// </summary>
/// <value>A member of the <see cref="RichTextAlign"/> enumeration that represents
/// the text alignment to apply to the current text selection or to text entered
/// after the insertion point.</value>
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new RichTextAlign SelectionAlignment
{
get
{
PARAFORMAT2 fmt = new PARAFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
SendMessage(new HandleRef(this, Handle), EM_GETPARAFORMAT, SCF_SELECTION, ref fmt);
if ((fmt.dwMask & PFM_ALIGNMENT) == 0)
return RichTextAlign.Unknown;
else
return (RichTextAlign)fmt.wAlignment;
}
set
{
PARAFORMAT2 fmt = new PARAFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = PFM_ALIGNMENT;
fmt.wAlignment = (short)value;
// Set the alignment
SendMessage(new HandleRef(this, Handle), EM_SETPARAFORMAT, SCF_SELECTION, ref fmt);
}
}
#endregion
#region Method: BeginUpdate
/// <summary>
/// Maintains performance while updating.
/// </summary>
/// <remarks>
/// <para>
/// It is recommended to call this method before doing
/// any major updates that you do not wish the user to
/// see. Remember to call EndUpdate when you are finished
/// with the update. Nested calls are supported.
/// </para>
/// <para>
/// Calling this method will prevent redrawing. It will
/// also setup the event mask of the underlying richedit
/// control so that no events are sent.
/// </para>
/// </remarks>
public void BeginUpdate()
{
// Deal with nested calls
_Updating++;
if (_Updating > 1)
return;
// Prevent the control from raising any events
_OldEventMask = SendMessage(new HandleRef(this, Handle), EM_SETEVENTMASK, 0, 0);
// Prevent the control from redrawing itself
SendMessage(new HandleRef(this, Handle),WM_SETREDRAW, 0, 0);
}
#endregion
#region Method: EndUpdate
/// <summary>
/// Resumes drawing and event handling.
/// </summary>
/// <remarks>
/// This method should be called every time a call is made
/// made to BeginUpdate. It resets the event mask to it's
/// original value and enables redrawing of the control.
/// </remarks>
public void EndUpdate()
{
// Deal with nested calls
_Updating--;
if (_Updating > 0)
return;
// Allow the control to redraw itself
SendMessage(new HandleRef(this, Handle), WM_SETREDRAW, 1, 0);
// Allow the control to raise event messages
SendMessage(new HandleRef(this, Handle), EM_SETEVENTMASK, 0, _OldEventMask);
}
#endregion
#region Method: RemoveTheme
/// <summary>
/// Removes the themed style from the specified window.
/// </summary>
/// <param name="handle">An <see cref="IntPtr"/> that contains the window handle (HWND) of the control.</param>
private void RemoveTheme()
{
// Check OS version
bool supportsThemes = false;
if (System.Environment.OSVersion.Version.Major > 5)
supportsThemes = true;
else if ((System.Environment.OSVersion.Version.Major == 5) && (System.Environment.OSVersion.Version.Minor >= 1))
supportsThemes = true;
// Call API function
if (supportsThemes)
SetWindowTheme(new HandleRef(this, Handle), " ", " ");
}
#endregion
#region Method: OnHandleCreated
/// <summary>
/// Raises the <see cref="HandleCreated"/> event.
/// </summary>
/// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
// Enable support for justification
SendMessage(new HandleRef(this, Handle), EM_SETTYPOGRAPHYOPTIONS, TO_ADVANCEDTYPOGRAPHY, TO_ADVANCEDTYPOGRAPHY);
}
#endregion
}
/// <summary>
/// Specifies horizontal alignment for a segment of rich text.
/// </summary>
public enum RichTextAlign
{
/// <summary>
/// The text alignment is unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// The text is aligned to the left.
/// </summary>
Left = 1,
/// <summary>
/// The text is aligned to the right.
/// </summary>
Right = 2,
/// <summary>
/// The text is aligned in the center.
/// </summary>
Center = 3,
/// <summary>
/// The text is justified.
/// </summary>
Justify = 4
}
/// <summary>
/// Specifies the underline styles for a segment of rich text.
/// </summary>
public enum UnderlineStyle
{
/// <summary>
/// No underlining.
/// </summary>
None = 0,
/// <summary>
/// Single-line solid underline.
/// </summary>
Normal = 1,
/// <summary>
/// Single-line underline broken between words.
/// </summary>
Word = 2,
/// <summary>
/// Double-line underline.
/// </summary>
Double = 3,
/// <summary>
/// 'Dotted' pattern underline.
/// </summary>
Dotted = 4,
/// <summary>
/// 'Dash' pattern underline.
/// </summary>
Dash = 5,
/// <summary>
/// 'Dash-dot' pattern underline.
/// </summary>
DashDot = 6,
/// <summary>
/// 'Dash-dot-dot' pattern underline.
/// </summary>
DashDotDot = 7,
/// <summary>
/// Single-line wave style underline.
/// </summary>
Wave = 8,
/// <summary>
/// Single-line solid underline with extra thickness.
/// </summary>
Thick = 9,
/// <summary>
/// Single-line solid underline with less thickness.
/// </summary>
HairLine = 10,
/// <summary>
/// Double-line wave style underline.
/// </summary>
DoubleWave = 11,
/// <summary>
/// Single-line wave style underline with extra thickness.
/// </summary>
HeavyWave = 12,
/// <summary>
/// 'Long Dash' pattern underline.
/// </summary>
LongDash = 13,
/// <summary>
/// 'Dash' pattern underline with extra thickness.
/// </summary>
ThickDash = 14,
/// <summary>
/// 'Dash-dot' pattern underline with extra thickness.
/// </summary>
ThickDashDot = 15,
/// <summary>
/// 'Dash-dot-dot' pattern underline with extra thickness.
/// </summary>
ThickDashDotDot = 16,
/// <summary>
/// 'Dotted' pattern underline with extra thickness.
/// </summary>
ThickDotted = 17,
/// <summary>
/// 'Long Dash' pattern underline with extra thickness.
/// </summary>
ThickLongDash = 18
}
/// <summary>
/// Specifies the color of underline for a segment of rich text.
/// </summary>
public enum UnderlineColor
{
/// <summary>
/// No specific underline color specified.
/// </summary>
None = -1,
/// <summary>
/// Black.
/// </summary>
Black = 0x00,
/// <summary>
/// Blue.
/// </summary>
Blue = 0x10,
/// <summary>
/// Cyan.
/// </summary>
Cyan = 0x20,
/// <summary>
/// LimeGreen.
/// </summary>
LimeGreen = 0x30,
/// <summary>
/// Magenta.
/// </summary>
Magenta = 0x40,
/// <summary>
/// Red.
/// </summary>
Red = 0x50,
/// <summary>
/// Yellow.
/// </summary>
Yellow = 0x60,
/// <summary>
/// White.
/// </summary>
White = 0x70,
/// <summary>
/// DarkBlue.
/// </summary>
DarkBlue = 0x80,
/// <summary>
/// DarkCyan.
/// </summary>
DarkCyan = 0x90,
/// <summary>
/// Green.
/// </summary>
Green = 0xA0,
/// <summary>
/// DarkMagenta.
/// </summary>
DarkMagenta = 0xB0,
/// <summary>
/// Brown.
/// </summary>
Brown = 0xC0,
/// <summary>
/// OliveGreen.
/// </summary>
OliveGreen = 0xD0,
/// <summary>
/// DarkGray.
/// </summary>
DarkGray = 0xE0,
/// <summary>
/// Gray.
/// </summary>
Gray = 0xF0
}
}
ablmf
I am not sure about this but might be this code snippet will solve the problem. Just try it and let me know if this works fine
/// <summary>
/// Maintains performance while updating.
/// </summary>
/// <remarks>
/// <para>
/// It is recommended to call this method before doing
/// any major updates that you do not wish the user to
/// see. Remember to call EndUpdate when you are finished
/// with the update. Nested calls are supported.
/// </para>
/// <para>
/// Calling this method will prevent redrawing. It will
/// also setup the event mask of the underlying richedit
/// control so that no events are sent.
/// </para>
/// </remarks>
public void BeginUpdate()
{
// Deal with nested calls.
++updating;
if ( updating > 1 )
return;
// Prevent the control from raising any events.
oldEventMask = SendMessage( new HandleRef( this, Handle ),
EM_SETEVENTMASK, 0, 0 );
// Prevent the control from redrawing itself.
SendMessage( new HandleRef( this, Handle ),
WM_SETREDRAW, 0, 0 );
}
/// <summary>
/// Resumes drawing and event handling.
/// </summary>
/// <remarks>
/// This method should be called every time a call is made
/// made to BeginUpdate. It resets the event mask to it's
/// original value and enables redrawing of the control.
/// </remarks>
public void EndUpdate()
{
// Deal with nested calls.
--updating;
if ( updating > 0 )
return;
// Allow the control to redraw itself.
SendMessage( new HandleRef( this, Handle ),
WM_SETREDRAW, 1, 0 );
// Allow the control to raise event messages.
SendMessage( new HandleRef( this, Handle ),
EM_SETEVENTMASK, 0, oldEventMask );
}
robinwebb
Leslie Brown
I am sorry for asking such trivial thing, but how do I include this in my code I have pasted this in "form1.cs" under "public partial class Form1 : Form" and I get this error:
The name 'updating' does not exist in the current context
Gustavo Frederico
It works
Thank you Karthikeya Pavan Kumar .B
It took me loong time. First I had exams then I realised that I won't get far with this code with knowledge on c# I had, so I read a book on c# and now I finally did ti :)
I added this.Refresh(); on the end of endUpdate() method, because RichTextBox did not update itself.
When you posted second example I saw that I have to use Dllimport. I don't fully understand how do you know when you have to use this. Is there anything I could read about this
Thanks again