Jerry@完美生活

青春的岁月,我们身不由己,只因这胸中,燃烧的梦想;青春的岁月,放浪的生涯,就任这时光,奔腾如流水。 体会这狂野,体会孤独,体会这欢乐,爱恨离别;体会这狂野,体会孤独,这是我的完美生活,也是你的完美生活。 我多想看到你,那依旧灿烂的笑容,再一次释放自己,胸中那灿烂的情感,我多想告诉你,那依旧灿烂的笑容,再一次释放自己。

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::
有朋友问我怎么在RichTextBox中实现高亮度显示几段文字,其实就是设置几段文字的背景。在.net framework1.1中,RichTextBox不支持SelectionBackColor,从.net framework2.0的帮助文档中,我发现有这个属性,但是没试过。于是,我就顺手写了一个,效果如下:
 
其实,从Rich Edit Control 2.0 开始就支持设置背景颜色,只不过.net framework没有把它暴露出来而已,我们只需要把它暴露出来。
 
Rich Edit Control中字符的格式都是通过向控件发送EM_SETCHARFORMAT消息实现的,发送时需要传递两个参数,wParam为格式应用的对象,系统定义了SCF_ALL, SCF_SELECTION等常量,lParam为一个指向类型为CHARFORMAT的指针。详细信息,可以查看MSDN。
 
下面我们一步一步来实现它:
 
首先,建一个新的类RichTextBoxEx,继承RichTextBox。需要定义一些常量,你可以在RichEdit.h里面找到这些常量的原始定义:
        private const int WM_USER = 0x400;
        
private const int EM_GETCHARFORMAT = WM_USER + 58;
        
private const int EM_SETCHARFORMAT = WM_USER + 68;

        
private const int CFM_BACKCOLOR    = 0x04000000;
        
private const int SCF_SELECTION    =    0x0001;
 
然后,定义CHARFORMAT的数据结构,在Rich Eidt Control 2.0中,使用的是CHARFORMAT2,以前的版本CHARFORMAT不含有背景颜色的定义,所有我们需要使用CHARFORMAT2,这个数据结构的也是在RichEdit.h中声明的:
      
[StructLayout(LayoutKind.Sequential, Pack=4)]
         
public class CHARFORMATA2 {
            
public int cbSize;
            
public int dwMask;
            
public int dwEffects;
            
public int yHeight;
            
public int yOffset;
            
public int crTextColor;
            
public byte bCharSet;
            
public byte bPitchAndFamily;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst
=0x20)]
            
public byte[] 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 CHARFORMATA2() {
                
this.cbSize = Marshal.SizeOf(typeof(CHARFORMATA2));
                
this.szFaceName = new byte[0x20];
            }

        }
 
为了向控件发送消息,还需要声明SendMessage方法:
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, [In, Out, MarshalAs(UnmanagedType.LPStruct)] CHARFORMATA2 lParam);
 
所有准备工作都完成了,下面就可以实现SelectionBackColor了。声明 SelectionBackColor属性,
[Browsable(false)]
public Color SelectionBackColor {
}
 
Gets方法就是通过发送EM_GETCHARFORMAT消息,读取字符的格式信息,也可以把这部分封装到一个单独的方法里面去:
        private CHARFORMATA2 GetSelectionCharFormat() {
            CHARFORMATA2 charformata2 
= new CHARFORMATA2();
            SendMessage(
new HandleRef(thisbase.Handle), EM_GETCHARFORMAT, SCF_SELECTION, charformata2);
            
return charformata2;
        }

读取里面的背景颜色值返回出来:
            get {
                Color backColor 
= Color.Empty;
                
this.ForceHandleCreate();
                CHARFORMATA2 charformat 
= GetSelectionCharFormat();
                
if ((charformat.dwMask & CFM_BACKCOLOR) != 0{
                    backColor 
= ColorTranslator.FromOle(charformat.crBackColor);
                }

                
return backColor;
            }
 
 
Sets方法就是通过发送EM_SETCHARFORMAT,设置字符的格式信息,我们只需要设置背景,可以设置掩码为CFM_BACKCOLOR
            set {
                
this.ForceHandleCreate();
                CHARFORMATA2 charformat
= GetSelectionCharFormat();
                charformat.dwMask 
= CFM_BACKCOLOR;
                charformat.dwEffects 
= 0;
                charformat.crBackColor 
= ColorTranslator.ToWin32(value);
                SendMessage(
new HandleRef(thisbase.Handle), EM_SETCHARFORMAT, SCF_SELECTION, charformat);
            }
 其中,ForceHandleCreate为:
        private void ForceHandleCreate() {
            IntPtr ptr 
= base.Handle;
        }
到此,一个支持SelectionBackColor的RichTextBox创建完成了,可以像使用SelectionForeColor等属性一样,先设置SelectionStart, SelectionLength,然后再设置SelectionBackColor,最后别忘了恢复SelectionStart, SelectionLength。
 
其实,还有很多的Rich Edit Control中的字符格式在.net framework1.1 中没有公布,像Link,把一段文字设为连接等,都可以按照上面的方法把它公布出来。

下载源代码>>>
posted on 2005-06-08 15:29  Jerry Zhou  阅读(4057)  评论(4)    收藏  举报