C#RichTextBox删除Custom SelectionBackColor

在做了一些研究后,我相信我问的问题与删除richtextbox SelectionBackColor相同。 我遇到了同样的问题,但我认为该问题的答案不充分,因为问题没有得到明确解释。 请看下面:

RichTextBox ,如何从文本( SelectionBackColor )中的某些文本( SelectionBackColor )中删除自定义BackColor ,以便即使BackColor将来发生更改 ,它也会采用控件的BackColor

我有一个方法突出显示一些文本,并使用SelectionBackColor更改其BackColor 。 我有另一种方法来改变整个控件的BackColor 。 这些事件可以独立发生。

如果我想“删除”一些SelectionBackColor ,我可以尝试将SelectionBackColor设置为Color.Transparent ,但它最终是白色。 如果我的RichTextBox当前 BackColor是白色,那暂时没问题。 如果我将SelectionBackColor设置为当前的BackColor ,则暂时没问题, 直到BackColor从另一个方法更改为止。

RichTextBox.BackColor发生更改后,之前突出显示的任何位置都使用White或之前的BackColor ,而不是假设新颜色类似于之前未突出显示的文本。

我已经尝试删除和替换文本,但是根据我的知识,这会否定保留该文本的任何其他自定义格式的能力。 将SelectionBackColor设置为null不起作用。

我可以很容易地看到我在谈论使用下面的代码:

 protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); this.BackColor = Color.Gray; if (SelectionLength > 0) { SelectionBackColor = Color.Yellow; } } protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); this.ResetBackColor(); if (SelectionLength > 0) { // The goal of this line is to "remove" the yellow. // By assigning it any value, it seems to have lost // the ability to use the control's BackColor normally. SelectionBackColor = this.BackColor;// or Color.Transparent } } 

使用上面的代码在自定义RichTextBox对象中键入一些文本,突出显示它的一小部分,然后使框失去焦点。 您将看到黄色突出显示的文本。 然后,让盒子获得焦点。 正如预期的那样,黄色背景将消失。 但是,如果您将插入符号移动到文本的其他位置并使控件再次失去焦点,您将看到先前突出显示的文本不呈现灰色背景颜色。

这是有趣的。 看起来(在Windows 7 / .Net 3.5上我测试过,也许在其他地方) System.Windows.Forms.RichTextBox.SelectionBackColor可能有一个错误清除选择的颜色。 源代码确实:

  public Color SelectionBackColor { set { //Note: don't compare the value to the old value here: it's possible that //you have a different range selected. selectionBackColorToSetOnHandleCreated = value; if (IsHandleCreated) { NativeMethods.CHARFORMAT2A cf2 = new NativeMethods.CHARFORMAT2A(); if (value == Color.Empty) { cf2.dwEffects = RichTextBoxConstants.CFE_AUTOBACKCOLOR; } else { cf2.dwMask = RichTextBoxConstants.CFM_BACKCOLOR; cf2.crBackColor = ColorTranslator.ToWin32(value); } UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf2); } } } 

正如您所注意到的,当设置为richTextBox.BackColor时,实际上并没有清除背面颜色。 当设置为RichTextBox.DefaultBackColor ,它也不会清除颜色, RichTextBox.DefaultBackColor只是将选择背面颜色设置为默认的灰色控制颜色。 看起来源代码在设置为Color.Empty试图清除选择的背景颜色 – 但至少在我的机器上,它什么也没做。

但是,如果我创建一个也设置cf2.dwMask = RichTextBoxConstants.CFM_BACKCOLOR;的扩展方法cf2.dwMask = RichTextBoxConstants.CFM_BACKCOLOR; 如果在发送消息之前为空颜色,则SetSelectionBackColor(Color.Empty)现在可以正常工作!

  public static void SetSelectionBackColor(this RichTextBox richTextBox, Color value) { if (richTextBox.IsHandleCreated && value == Color.Empty) { var cf2 = new CHARFORMAT2(); cf2.dwEffects = RichTextBoxConstants.CFE_AUTOBACKCOLOR; cf2.dwMask = RichTextBoxConstants.CFM_BACKCOLOR; cf2.crBackColor = ColorTranslator.ToWin32(value); UnsafeNativeMethods.SendMessage(new HandleRef(richTextBox, richTextBox.Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf2); } else { richTextBox.SelectionBackColor = value; } } 

完整的方法,常量和类改编自这里和这里 , 这里 , 这里和这里 :

 public static class RichTextBoxConstants { // http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/RichTextBoxConstants.cs,31b52ac41e96a888 /* EM_SETCHARFORMAT wparam masks */ internal const int SCF_SELECTION = 0x0001; internal const int EM_SETCHARFORMAT = (NativeMethods.WM_USER + 68); internal const int CFM_BACKCOLOR = 0x04000000; /* NOTE: CFE_AUTOCOLOR and CFE_AUTOBACKCOLOR correspond to CFM_COLOR and CFM_BACKCOLOR, respectively, which control them */ internal const int CFE_AUTOBACKCOLOR = CFM_BACKCOLOR; } [StructLayout(LayoutKind.Sequential, Pack = 4)] public class CHARFORMAT2 { // http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/NativeMethods.cs,acde044a28b57a48 // http://pinvoke.net/default.aspx/Structures/CHARFORMAT2.html public int cbSize = Marshal.SizeOf(typeof(CHARFORMAT2)); public int dwMask; public int dwEffects; public int yHeight; public int yOffset; public int crTextColor; public byte bCharSet; public byte bPitchAndFamily; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szFaceName; public short wWeight; public short sSpacing; public int crBackColor; public int lcid; public int dwReserved; public short sStyle; public short wKerning; public byte bUnderlineType; public byte bAnimation; public byte bRevAuthor; public byte bReserved1; } public static class NativeMethods { // http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/NativeMethods.cs,e75041b5218ff60b public const int WM_USER = 0x0400; public static void SetSelectionBackColor(this RichTextBox richTextBox, Color value) { if (richTextBox.IsHandleCreated && value == Color.Empty) { var cf2 = new CHARFORMAT2(); cf2.dwEffects = RichTextBoxConstants.CFE_AUTOBACKCOLOR; cf2.dwMask = RichTextBoxConstants.CFM_BACKCOLOR; cf2.crBackColor = ColorTranslator.ToWin32(value); UnsafeNativeMethods.SendMessage(new HandleRef(richTextBox, richTextBox.Handle), RichTextBoxConstants.EM_SETCHARFORMAT, RichTextBoxConstants.SCF_SELECTION, cf2); } else { richTextBox.SelectionBackColor = value; } } } public static class UnsafeNativeMethods { // http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/UnsafeNativeMethods.cs,0d546f58103867e3 // For RichTextBox // [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, [In, Out, MarshalAs(UnmanagedType.LPStruct)] CHARFORMAT2 lParam); } 

我做了:

 SelectionBackColor = default(Color); 

它工作得很好。