RichEdit控件的使用

我们在使用聊天工具的时候经常会看到消息显示为各种颜色、字体、下划线、超链接识别等效果,使用微软为我们提供的RichEdit控件就可以达到这样的效果,但是RichEdit控件使用起来并不简单,甚至于在使用的时候让我们的窗体中充斥着RichEdit的代码,下面让我们重新封装这个控件,以方面我们以后的使用。
一、效果图:

二、源码:
RichEditCtrlEx.h
C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/
// Name:        RICHEDITCTRLEX.H
// Purpose:     CRichEditCtrlEx
// Author:      yfq
// Modified by: 
// Created:     2010/12/24 11:01
// RCS-ID:      
// Copyright:   
// Licence:     
/
 
#ifndef __RICHEDITCTRLEX_H__
#define __RICHEDITCTRLEX_H__
 
class  CRichEditCtrlEx :    public  CRichEditCtrl
{
     DECLARE_DYNCREATE(CRichEditCtrlEx)
public :
     CRichEditCtrlEx( void );
     ~CRichEditCtrlEx( void );
     
     void  Initlize();
     /**
     * 最后追加一行
     *
     * @param text -[in] -要追加的文本
     *
     * @param newline -[in] -是否换行
     *
     * @param link     -[in] -是否带超链接
     *
     * @param nLinkBegin -[in] -超链接起始位置(索引从0开始)
     *
     * @param nLinkCount -[in] -超链接字符数
     *
     * @return -[NONE]
     */
     void  Append( LPCSTR  text, bool  newline =  false , bool  link =  false , int  nLinkBegin = 0, int  nLinkCount = 0);
     
     /**
      * 获得文本
      *
      * @param nBegin -[in] -开始位置
      *
      * @param nEnd -[in] -结束位置
      *
      * @param text -[out] -得到的文本
      *
      * @return -[NONE]
      */
     void  GetText( int  nBegin, int  nEnd,CString& text);
     
     /**
      * 新增文字时是否滚动到底部
      *
      * @param bottom -[in] -否滚动到底部
      *
      * @return -[NONE]
      */
     void  SetScrollBottom( bool  bottom= true );
     void  StopScroll();
 
     /**
      * 设置字体
      *
      * @param nBegin -[in] -开始位置
      *
      * @param nEnd -[in] -结束位置
      *
      * @param bold -[in] -粗体
      *
      * @param italic -[in] -斜体
      *
      * @param underline -[in] -下划线
      *
      * @param color -[in] -颜色
      *
      * @param size -[in] -文字大小
      *
      * @return -[NONE]
      */
     void  SetTextFont( int  nBegin, int  nEnd, bool  bold, bool  italic, bool  underline, COLORREF  color=0, int  size=0);
     
     /**
      * 为选中的文本添加超链接
      *
      * @return -[NONE]
      */
     void  AddLink();
 
     /**
      * 取消选中文本添的超链接
      *
      * @return -[NONE]
      */
     void  CancelLink();
 
     /**
     * 校验URL是否合法文件路径,依据为rfc2396
     * 这个函数只做粗略的校验,不完全符合RFC2369
     * 仅支持IPV4
     *
     */
     BOOL  CheckURL( const  CString &szUrl, CString &szMsg);
 
     void  OnSize(CWnd* pParent);
     void  OnSize(CRect& rect);
     void  OnSpecifySize(CWnd* pParent);
     bool  IsCreate();
     void  Clear();
     void  SetEditFocus( bool  focus);
     
     /**
      * 显示指定颜色的边框
      *
      * @param bShow -[in] -是否显示边框
      *
      * @param nColor -[in] -边框颜色
      *
      * @return -[NONE]
      */
     void  ShowBorderLine( BOOL  bShow, COLORREF  nColor = RGB(53, 104, 187));
     
     /**
      * 设置左侧偏移
      *
      * @param nOffset -[in] -偏移量
      *
      * @return -[NONE]
      */
     void  SetLeftOffset( int  nOffset);
public :
     afx_msg  void  OnPaint();
     afx_msg  void  OnSize( UINT  nType,  int  cx,  int  cy);
     afx_msg  BOOL  OnLink(NMHDR *in_pNotifyHeader,  LRESULT  *out_pResult);
     afx_msg  void  OnSetFocus(CWnd* pOldWnd);
     DECLARE_MESSAGE_MAP()
 
private :
     CWnd*        m_pParentWnd;
     bool        m_bBottom;
     BOOL        m_ShowBorder; 
     COLORREF    m_BorderColor; 
     bool        m_bCreate;
     bool        m_bFocus;
};
 
#endif //__RICHEDITCTRLEX_H__

C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#include "StdAfx.h"
#include <afxinet.h>
#include "RichEditCtrlEx.h"
 
#pragma warning(disable:4996)
 
CRichEditCtrlEx::CRichEditCtrlEx( void )
{
     m_ShowBorder =    TRUE;
     m_BorderColor = RGB(53, 104, 187);
     m_bBottom =  true ;
     m_bCreate =  false ;
     m_bFocus =  true ;
     AfxInitRichEdit2();
}
 
CRichEditCtrlEx::~CRichEditCtrlEx( void )
{
}
 
IMPLEMENT_DYNCREATE(CRichEditCtrlEx, CRichEditCtrl)
BEGIN_MESSAGE_MAP(CRichEditCtrlEx, CRichEditCtrl)
     ON_WM_RBUTTONDOWN()
     ON_WM_LBUTTONDBLCLK()
     ON_WM_PAINT()
     ON_NOTIFY_REFLECT_EX(EN_LINK, OnLink)
     ON_WM_SETFOCUS()
END_MESSAGE_MAP()
 
void  CRichEditCtrlEx::Initlize()
{
     m_bBottom =  true ;
     m_bCreate =  true ;
     SetEventMask(GetEventMask() | ENM_LINK) ; 
     //SendMessage(EM_AUTOURLDETECT, TRUE, 0);
     SetOptions(ECOOP_OR, ECO_AUTOVSCROLL);
     LimitText(0xFFFFFFFF);
     SetBackgroundColor(FALSE,RGB(248,248,248));
     SetLeftOffset(150);
}
void  CRichEditCtrlEx::Append( LPCSTR  text, bool  newline, bool  link, int  nLinkBegin, int  nLinkCount)
{
     int  nPrvTotal = GetTextLengthEx( GTL_DEFAULT, 1200 );
     SetSel(-1,-1);
     ReplaceSel(( LPCTSTR )text);
     if  (newline)
     {
         Append( "\r\n" );
     }
     if  (link)
     {
         if  (!newline)
         {
             Append( "\r\n" );
         }
         int  nTotal = GetTextLengthEx( GTL_DEFAULT, 1200 ) - 1;
         if ( nTotal > 0)
         {
             if  (nLinkCount>nTotal-nPrvTotal)
             {
                 nLinkCount = nTotal-nPrvTotal;
             }
             SetSel( nPrvTotal+nLinkBegin, nPrvTotal+nLinkBegin+nLinkCount );
             AddLink();
         }
     }
     // 随着输入随着自动滚动条滚动到最后一行
     if  (m_bBottom)
     {
         PostMessage(WM_VSCROLL, SB_BOTTOM,0);
     }
}
void  CRichEditCtrlEx::GetText( int  nBegin, int  nEnd,CString& text)
{
     CHARRANGE CharRange;
     CharRange.cpMin = nBegin;
     CharRange.cpMax = nEnd;
     SetSel(CharRange);
     CHAR  szTmp[1024] = {0};
     GetSelText(szTmp);
     text.Format( "%s" ,szTmp);
}
void  CRichEditCtrlEx::SetScrollBottom( bool  bottom)
{
     m_bBottom = bottom;
}
void  CRichEditCtrlEx::StopScroll()
{
     m_bBottom = !m_bBottom;
     if  (m_bBottom)
     {
         PostMessage(WM_VSCROLL, SB_BOTTOM,0);
     }
}
void  CRichEditCtrlEx::SetTextFont( int  nBegin, int  nEnd, bool  bold, bool  italic, bool  underline, COLORREF  color, int  size)
{
     SetSel(nBegin,nEnd);
     CHARFORMAT2 cf,oldCf;
     GetSelectionCharFormat(oldCf);
     GetSelectionCharFormat(cf);
     if  (bold)
     {
         cf.dwMask|=CFM_BOLD;
         cf.dwEffects|=CFE_BOLD;            //设置粗体,取消用cf.dwEffects&=~CFE_BOLD;
     }
     if  (italic)
     {
         cf.dwMask|=CFM_ITALIC;
         cf.dwEffects|=CFE_ITALIC;        //设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;
     }
     if  (underline)
     {
         cf.dwMask|=CFM_UNDERLINE;
         cf.dwEffects|=CFE_UNDERLINE;    //设置下划线,取消用cf.dwEffects&=~CFE_UNDERLINE;
     }
     if  (color)
     {
         cf.dwEffects &= ~CFE_AUTOCOLOR;    //这个最重要,设选中文字颜色的时候也要注意,dwEffects一定不能有CEF_AUTOCOLOR的属性
         cf.dwMask|=CFM_COLOR;
         cf.crTextColor = color;    //设置颜色
     }
     if  (size)
     {
         cf.dwMask|=CFM_SIZE;
         cf.yHeight =200;                //设置高度
     }
     cf.dwMask|=CFM_FACE;
     strcpy (cf.szFaceName ,_T( "宋体" )); //设置字体
     SetSelectionCharFormat(cf);
     SetSel(-1,-1);
     SetSelectionCharFormat(oldCf);
}
void  CRichEditCtrlEx::AddLink()
{
     CHARFORMAT2 cf2;
     ZeroMemory(&cf2,  sizeof (CHARFORMAT2));
     cf2.cbSize =  sizeof (CHARFORMAT2);
 
     cf2.dwMask |= CFM_LINK;
     cf2.dwEffects |= CFE_LINK;
 
     cf2.dwEffects &= ~CFE_AUTOCOLOR;    //这个最重要,设选中文字颜色的时候也要注意,dwEffects一定不能有CEF_AUTOCOLOR的属性
     cf2.dwMask |= CFM_COLOR;
     cf2.crTextColor = RGB( 255, 112, 5 );
 
     SetSelectionCharFormat(cf2);
     SetSel( -1, -1 );
}
 
void  CRichEditCtrlEx::CancelLink()
{
     CHARFORMAT2 cf2;
     ZeroMemory(&cf2,  sizeof (CHARFORMAT2));
     cf2.cbSize =  sizeof (CHARFORMAT2);
     cf2.dwMask = CFM_LINK;
     cf2.dwEffects &= ~CFE_LINK;
 
     SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM )&cf2);
     SetSel( -1, -1 );
}
BOOL  CRichEditCtrlEx::CheckURL( const  CString &szUrl, CString &szMsg)
{
     DWORD  dwService = 0;
     DWORD  dwValid = AFX_INET_SERVICE_FTP|AFX_INET_SERVICE_HTTP|AFX_INET_SERVICE_HTTPS|AFX_INET_SERVICE_FILE;
     CString strServer;  
     CString strObject;  
     INTERNET_PORT port; 
 
     BOOL  bValid = AfxParseURL(szUrl, dwService, strServer, strObject, port);  
     if  (!bValid)
    
         szMsg = szUrl +  " \n不是一个合法的下载地址URL" ;
         return  FALSE;  
     }
     return  TRUE;
}
BOOL  CRichEditCtrlEx::OnLink(NMHDR *pNotifyHeader,  LRESULT  *pResult)
{
     ENLINK *pEnLink =  reinterpret_cast <ENLINK *>(pNotifyHeader);
     CString      strURL;
     *pResult = 0;
     CHAR  szTmpLink[512] = {0};
     switch  (pNotifyHeader->code)
     {
     case  EN_LINK:
         switch  (pEnLink->msg)
         {
         case  WM_LBUTTONUP:
             SetSel(pEnLink->chrg);
             GetSelText(szTmpLink);
             strURL.Format( "%s" ,szTmpLink);
             CString strMsg;
             if  (CheckURL(strURL,strMsg))
             {
                 ShellExecute(GetSafeHwnd(), _T( "open" ), strURL, NULL, NULL, SW_SHOWNORMAL);
             }
             break ;
         }
         break ;
     }
     return  *pResult;
}
 
//    We need to handle the OnSize message to ensure that the most recent
//    line of text is visible.
void  CRichEditCtrlEx::OnSize( UINT  nType,  int  cx,  int  cy)
{
     CRichEditCtrl::OnSize(nType, cx, cy);
}
void  CRichEditCtrlEx::OnSize(CWnd* pParent)
{
     if  (!m_bCreate)
     {
         return ;
     }
     CRect parentRect;
     pParent->GetClientRect(parentRect);
     parentRect.bottom = parentRect.bottom - 5;
     parentRect.top = parentRect.top + 5;
     parentRect.left = parentRect.left + 5;
     parentRect.right = parentRect.right - 5;
     MoveWindow(parentRect,TRUE);
}
void  CRichEditCtrlEx::OnSize(CRect& rect)
{
     if  (!m_bCreate)
     {
         return ;
     }
     rect.bottom = rect.bottom - 5;
     rect.top = rect.top + 5;
     rect.left = rect.left + 5;
     rect.right = rect.right - 5;
     MoveWindow(rect,TRUE);
}
void  CRichEditCtrlEx::OnSpecifySize(CWnd* pParent)
{
     if  (!m_bCreate)
     {
         return ;
     }
     CRect parentRect;
     pParent->GetClientRect(parentRect);
     parentRect.left = 5;
     parentRect.top = 197;
     parentRect.right -= 5;
     parentRect.bottom -= 5;
     MoveWindow(parentRect,TRUE);
 
}
void  CRichEditCtrlEx::OnPaint()
{
     if  (!m_ShowBorder)
     {
         CRichEditCtrl::OnPaint();
         return ;
     }
     CRichEditCtrl::OnPaint();
     CClientDC dc( this );
     if  (!m_pParentWnd)
     {
         return ;
     }
     CRect rect;
     GetWindowRect(rect);
     rect.left-=1;
     rect.top-=1;
     rect.right+=1;
     rect.bottom+=1;
     ScreenToClient(rect);
     dc.Draw3dRect(rect,m_BorderColor,m_BorderColor);
}
// 如果控件可以获得焦点,则当控件有焦点时会自动滚动到底部,所以要屏蔽一下
void  CRichEditCtrlEx::OnSetFocus(CWnd* pOldWnd)
{
     if  (!m_bFocus)
     {
         return ;
     }
     CRichEditCtrl::OnSetFocus(pOldWnd);
}
 
bool  CRichEditCtrlEx::IsCreate()
{
     return  m_bCreate;
}
void  CRichEditCtrlEx::Clear()
{
     if  (GetWindowLong( this ->m_hWnd,GWL_STYLE) & ES_READONLY)
     {
         SetReadOnly(FALSE);
         CRichEditCtrl::Clear();
         SetReadOnly();
     }
     else
     {
         CRichEditCtrl::Clear();
     }
}
void  CRichEditCtrlEx::SetEditFocus( bool  focus)
{
     m_bFocus = focus;
}
void  CRichEditCtrlEx::ShowBorderLine( BOOL  bShow, COLORREF  nColor)
{
     m_ShowBorder = bShow;
}
void  CRichEditCtrlEx::SetLeftOffset( int  nOffset)
{
     PARAFORMAT2 PF_his;
     PF_his.dwMask = PFM_ALIGNMENT|PFM_STARTINDENT;
     PF_his.wAlignment = PFA_LEFT;
     PF_his.dxStartIndent = nOffset;
     SetParaFormat(PF_his);
}
#pragma warning(default:4996)

三、使用方法
1、在窗体上放一个Rich Edit 2.0 Control,修改属性,例如,你需要多行显示则要把Multiline属性设置为TRUE,如果需要垂直滚动条则需要把Vertical Scroll属性设置为TRUE
2、为新添加的RichEdit控件关联控件变量:
在头文件中声明CRichEditCtrlEx m_RichEdit;
在DoDataExchange中写入DDX_Control(pDX, IDC_RICHEDIT21, m_RichEdit);

3、初始化控件
在窗体的OnInitDialog()中添加代码:m_RichEdit.Initlize();
4、其它函数的使用见代码注释

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值