自定义 CRichEditCtrl 控件
在VC中提供了两种很方便的编辑控件(CEdit 和CRichEditCtrl),一般来说这两种控件已经满足了我们大部分的需要,不过只有CEdit控件能响应我们鼠标右键消息,通过右键我们很容易的操作我们的编辑,而在CRichEditCtrl控件中我们不能得到这样的操作,同时CRichEditCtrl是能够包含各种格式的内容,就好像Word一样能够写入各种不同的字体,不过CRichEditCtrl没有给我们提供这样的要求,今天我的目的也就是给他添加这样的扩展操作。
本代码运行效果图 一. 首先我们要从CRichEditCtrl类派生一个我们自己的类CMyRichEdit,我们的操作也是在其中完成的。 二. 然后我们添加鼠标右键消息,在其中添加代码如下: 01. //设置为焦点
02. SetFocus();
03. 04. //创建一个弹出式菜单
05. CMenu popmenu;
06. popmenu.CreatePopupMenu();
07. 08. //添加菜单项目
09. 10. popmenu.AppendMenu(0, ID_RICH_UNDO,
"&Undo" ); 11. popmenu.AppendMenu(0, MF_SEPARATOR);
12. popmenu.AppendMenu(0, ID_RICH_CUT,
"&Cut" ); 13. popmenu.AppendMenu(0, ID_RICH_COPY,
"C&opy" ); 14. popmenu.AppendMenu(0, ID_RICH_PASTE,
"&Paste" ); 15. popmenu.AppendMenu(0, ID_RICH_CLEAR,
"C&lear" ); 16. popmenu.AppendMenu(0, MF_SEPARATOR);
17. popmenu.AppendMenu(0, ID_RICH_SELECTALL,
"Select &All" ); 18. popmenu.AppendMenu(0, MF_SEPARATOR);
19. popmenu.AppendMenu(0, ID_RICH_SETFONT,
"Select &Font" ); 20. 21. //初始化菜单项
22. UINT
nUndo=(CanUndo() ? 0 : MF_GRAYED ); 23. popmenu.EnableMenuItem(ID_RICH_UNDO, MF_BYCOMMAND|nUndo);
24. UINT
nSel=((GetSelectionType()!=SEL_EMPTY) ? 0 : MF_GRAYED) ;
25. popmenu.EnableMenuItem(ID_RICH_CUT, MF_BYCOMMAND|nSel);
26. popmenu.EnableMenuItem(ID_RICH_COPY, MF_BYCOMMAND|nSel);
27. popmenu.EnableMenuItem(ID_RICH_CLEAR, MF_BYCOMMAND|nSel);
28. UINT
nPaste=(CanPaste() ? 0 : MF_GRAYED) ; 29. popmenu.EnableMenuItem(ID_RICH_PASTE, MF_BYCOMMAND|nPaste);
30. 31. //显示菜单
32. CPoint pt;
33. GetCursorPos(&pt);
34. popmenu.TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y,
this ); 35. popmenu.DestroyMenu(); 三. 然后在.h文件中加入如下的ID定义: 1. #define ID_RICH_UNDO 101
2. #define ID_RICH_CUT 102
3. #define ID_RICH_COPY 103
4. #define ID_RICH_PASTE 104
5. #define ID_RICH_CLEAR 105
6. #define ID_RICH_SELECTALL 106
7. #define ID_RICH_SETFONT 107 不过这些值还可以通过VC++编译器中的菜单View->Resource Symbols进行添加。 四. 添加消息相应操作,由于这些ID是我们自己定义的,所以我们只能手动添加: 1.在头文件中添加: 1. afx_msg
void OnRButtonDown( UINT
nFlags, CPoint point); 2. afx_msg
void OnCopy() { Copy(); }
3. afx_msg
void OnCut() { Cut(); }
4. afx_msg
void OnPaste() { Paste(); }
5. afx_msg
void OnSelectall() { SetSel(0, -1); }
6. afx_msg
void OnUndo() { Undo(); }
7. afx_msg
void OnClear() { Clear(); }
8. afx_msg
void OnSelectfont(); //改变字体 2.在实现文件的消息映射宏中添加如下: 1. ON_COMMAND(ID_RICH_COPY, OnCopy)
2. ON_COMMAND(ID_RICH_CUT, OnCut)
3. ON_COMMAND(ID_RICH_PASTE, OnPaste)
4. ON_COMMAND(ID_RICH_SELECTALL, OnSelectall)
5. ON_COMMAND(ID_RICH_UNDO, OnUndo)
6. ON_COMMAND(ID_RICH_CLEAR, OnClear)
7. ON_COMMAND(ID_RICH_SETFONT, OnSelectfont) 3.最后添加字体变换函数: 01. CHARFORMAT cf;
02. LOGFONT lf;
03. memset (&cf, 0,
sizeof (CHARFORMAT));
04. memset (&lf, 0,
sizeof (LOGFONT));
05. 06. //判断是否选择了内容
07. BOOL
bSelect = (GetSelectionType() != SEL_EMPTY) ? TRUE : FALSE;
08. if
(bSelect) 09. {
10. GetSelectionCharFormat(cf);
11. }
12. else 13. {
14. GetDefaultCharFormat(cf);
15. }
16. 17. //得到相关字体属性
18. BOOL
bIsBold = cf.dwEffects & CFE_BOLD; 19. BOOL
bIsItalic = cf.dwEffects & CFE_ITALIC; 20. BOOL
bIsUnderline = cf.dwEffects & CFE_UNDERLINE; 21. BOOL
bIsStrickout = cf.dwEffects & CFE_STRIKEOUT; 22. 23. //设置属性
24. lf.lfCharSet = cf.bCharSet;
25. lf.lfHeight = cf.yHeight/15;
26. lf.lfPitchAndFamily = cf.bPitchAndFamily;
27. lf.lfItalic = bIsItalic;
28. lf.lfWeight = (bIsBold ? FW_BOLD : FW_NORMAL);
29. lf.lfUnderline = bIsUnderline;
30. lf.lfStrikeOut = bIsStrickout;
31. sprintf (lf.lfFaceName, cf.szFaceName);
32. 33. 34. CFontDialog dlg(&lf);
35. dlg.m_cf.rgbColors = cf.crTextColor;
36. if
(dlg.DoModal() == IDOK) 37. {
38. dlg.GetCharFormat(cf); //获得所选字体的属性
39. if
(bSelect) 40. SetSelectionCharFormat(cf);
//为选定的内容设定所选字体 41. else 42. SetWordCharFormat(cf);
//为将要输入的内容设定字体 43. } 然后在我们需要的地方添加头文件和实现文件,将定义的CRichEditCtrl对象改为用CMyRichEdit来定义,就可以了。 还有提醒的就是不要忘记在InitInstance()中调用AfxInitRichEdit() |
在VC中提供了两种很方便的编辑控件(CEdit 和CRichEditCtrl),一般来说这两种控件已经满足了我们大部分的需要,不过只有CEdit控件能响应我们鼠标右键消息,通过右键我们很容易的操作我们的编辑,而在CRichEditCtrl控件中我们不能得到这样的操作,同时CRichEditCtrl是能够包含各种格式的内容,就好像Word一样能够写入各种不同的字体,不过CRichEditCtrl没有给我们提供这样的要求,今天我的目的也就是给他添加这样的扩展操作。
本代码运行效果图 一. 首先我们要从CRichEditCtrl类派生一个我们自己的类CMyRichEdit,我们的操作也是在其中完成的。 二. 然后我们添加鼠标右键消息,在其中添加代码如下: 01. //设置为焦点
02. SetFocus();
03. 04. //创建一个弹出式菜单
05. CMenu popmenu;
06. popmenu.CreatePopupMenu();
07. 08. //添加菜单项目
09. 10. popmenu.AppendMenu(0, ID_RICH_UNDO,
"&Undo" ); 11. popmenu.AppendMenu(0, MF_SEPARATOR);
12. popmenu.AppendMenu(0, ID_RICH_CUT,
"&Cut" ); 13. popmenu.AppendMenu(0, ID_RICH_COPY,
"C&opy" ); 14. popmenu.AppendMenu(0, ID_RICH_PASTE,
"&Paste" ); 15. popmenu.AppendMenu(0, ID_RICH_CLEAR,
"C&lear" ); 16. popmenu.AppendMenu(0, MF_SEPARATOR);
17. popmenu.AppendMenu(0, ID_RICH_SELECTALL,
"Select &All" ); 18. popmenu.AppendMenu(0, MF_SEPARATOR);
19. popmenu.AppendMenu(0, ID_RICH_SETFONT,
"Select &Font" ); 20. 21. //初始化菜单项
22. UINT
nUndo=(CanUndo() ? 0 : MF_GRAYED ); 23. popmenu.EnableMenuItem(ID_RICH_UNDO, MF_BYCOMMAND|nUndo);
24. UINT
nSel=((GetSelectionType()!=SEL_EMPTY) ? 0 : MF_GRAYED) ;
25. popmenu.EnableMenuItem(ID_RICH_CUT, MF_BYCOMMAND|nSel);
26. popmenu.EnableMenuItem(ID_RICH_COPY, MF_BYCOMMAND|nSel);
27. popmenu.EnableMenuItem(ID_RICH_CLEAR, MF_BYCOMMAND|nSel);
28. UINT
nPaste=(CanPaste() ? 0 : MF_GRAYED) ; 29. popmenu.EnableMenuItem(ID_RICH_PASTE, MF_BYCOMMAND|nPaste);
30. 31. //显示菜单
32. CPoint pt;
33. GetCursorPos(&pt);
34. popmenu.TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y,
this ); 35. popmenu.DestroyMenu(); 三. 然后在.h文件中加入如下的ID定义: 1. #define ID_RICH_UNDO 101
2. #define ID_RICH_CUT 102
3. #define ID_RICH_COPY 103
4. #define ID_RICH_PASTE 104
5. #define ID_RICH_CLEAR 105
6. #define ID_RICH_SELECTALL 106
7. #define ID_RICH_SETFONT 107 不过这些值还可以通过VC++编译器中的菜单View->Resource Symbols进行添加。 四. 添加消息相应操作,由于这些ID是我们自己定义的,所以我们只能手动添加: 1.在头文件中添加: 1. afx_msg
void OnRButtonDown( UINT
nFlags, CPoint point); 2. afx_msg
void OnCopy() { Copy(); }
3. afx_msg
void OnCut() { Cut(); }
4. afx_msg
void OnPaste() { Paste(); }
5. afx_msg
void OnSelectall() { SetSel(0, -1); }
6. afx_msg
void OnUndo() { Undo(); }
7. afx_msg
void OnClear() { Clear(); }
8. afx_msg
void OnSelectfont(); //改变字体 2.在实现文件的消息映射宏中添加如下: 1. ON_COMMAND(ID_RICH_COPY, OnCopy)
2. ON_COMMAND(ID_RICH_CUT, OnCut)
3. ON_COMMAND(ID_RICH_PASTE, OnPaste)
4. ON_COMMAND(ID_RICH_SELECTALL, OnSelectall)
5. ON_COMMAND(ID_RICH_UNDO, OnUndo)
6. ON_COMMAND(ID_RICH_CLEAR, OnClear)
7. ON_COMMAND(ID_RICH_SETFONT, OnSelectfont) 3.最后添加字体变换函数: 01. CHARFORMAT cf;
02. LOGFONT lf;
03. memset (&cf, 0,
sizeof (CHARFORMAT));
04. memset (&lf, 0,
sizeof (LOGFONT));
05. 06. //判断是否选择了内容
07. BOOL
bSelect = (GetSelectionType() != SEL_EMPTY) ? TRUE : FALSE;
08. if
(bSelect) 09. {
10. GetSelectionCharFormat(cf);
11. }
12. else 13. {
14. GetDefaultCharFormat(cf);
15. }
16. 17. //得到相关字体属性
18. BOOL
bIsBold = cf.dwEffects & CFE_BOLD; 19. BOOL
bIsItalic = cf.dwEffects & CFE_ITALIC; 20. BOOL
bIsUnderline = cf.dwEffects & CFE_UNDERLINE; 21. BOOL
bIsStrickout = cf.dwEffects & CFE_STRIKEOUT; 22. 23. //设置属性
24. lf.lfCharSet = cf.bCharSet;
25. lf.lfHeight = cf.yHeight/15;
26. lf.lfPitchAndFamily = cf.bPitchAndFamily;
27. lf.lfItalic = bIsItalic;
28. lf.lfWeight = (bIsBold ? FW_BOLD : FW_NORMAL);
29. lf.lfUnderline = bIsUnderline;
30. lf.lfStrikeOut = bIsStrickout;
31. sprintf (lf.lfFaceName, cf.szFaceName);
32. 33. 34. CFontDialog dlg(&lf);
35. dlg.m_cf.rgbColors = cf.crTextColor;
36. if
(dlg.DoModal() == IDOK) 37. {
38. dlg.GetCharFormat(cf); //获得所选字体的属性
39. if
(bSelect) 40. SetSelectionCharFormat(cf);
//为选定的内容设定所选字体 41. else 42. SetWordCharFormat(cf);
//为将要输入的内容设定字体 43. } 然后在我们需要的地方添加头文件和实现文件,将定义的CRichEditCtrl对象改为用CMyRichEdit来定义,就可以了。 还有提醒的就是不要忘记在InitInstance()中调用AfxInitRichEdit() |