|
一.常见问题
& v; |0 H0 W# b3 ]3 v/ m# Oa.可以编译,不能执行的
8 M1 o" I4 i3 V" R# JAfxInitRichEdit();
3 n' s7 I, \" X; K$ s; a4 I* G: C# g; e; w O* [
b.升级默认的Riched版本(默认的有一些bug),如7 s/ ?( Y& v. h0 |0 K
可在InitInstance中添加" ]! p1 p. M F
LoadLibrary("RICHED20.DLL") & Y# `8 ?* A6 {9 H# n3 H9 A
最后注意 FreeLibrary* I; ]8 i" y0 D, y
1 R I; K6 \2 I" x3 W4 z! x
如果是CRichEditView基类的可用9 j$ _% \4 i/ {2 }6 O( ?+ m" ?! F
BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)% y/ K6 `5 G: p4 S. i9 t% W
{+ O( `1 f2 J! O: S z
//装入rich edit version 2.0
0 I& Q% u1 Y1 X7 q7 S& Q" w# e+ Zif (LoadLibraryA("RICHED20.DLL") == NULL)7 a+ G; I, D8 y5 x
{, i4 m; a3 p3 r
AfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);
6 V0 A" T, S& W/ k3 vPostMessage(WM_QUIT,0,0);
; e* P% P5 |, i& E( \ T, Mreturn FALSE;. r. ]! F! b& ?; G
}
( m) S2 [7 ?" k# U; f
% `9 x4 N* D$ i7 `- c/ Lm_strClass = RICHEDIT_CLASSA;//for 2.0 class& g1 W+ Y9 i. S; `
/ T, l; f, `( d- Q0 ]$ e$ l
return CRichEditView::PreCreateWindow(cs);
9 u- U, w- \! Y. d}% K- |# L; V3 r
8 y# N4 Z, t9 K2 u6 wc.最后追加行
7 Y6 |0 V. U4 y" h; w8 C- w$ Bricheditctrl.SetSel(-1, -1);
. b# J* m, _4 u. K. K9 t; A2 Aricheditctrl.ReplaceSel( (LPCTSTR)str );
8 p9 f8 c3 n. T- d& z x0 u) A& h" a6 T ]& d
d.字数限制
8 T) u% v2 T5 P, rCRichEditCtrl::LimitText(long nChars)5 h1 `' n' t4 u" v ?+ A' E6 J
5 c: S) a( k/ h+ m# @( h& Qe.换行切换' m( S+ I. o1 Q& c. `; F8 ]: k
CRichEditView的OnInitialUpdate()函数中加入下面两句:
' D. n" q! l- Cm_nWordWrap = WrapNone;$ v' J% `$ A0 O+ d. o( D$ `' t. O
WrapChanged(); ( w: _% c5 t- M3 g: A$ T5 q" f
WrapChanged实际上也是调用' L7 v3 ^) B, x
ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone
1 M# k: U" [2 X" l# E4 o9 ^( bctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow
4 z, p' m9 ?: n3 K: U还有不常用的 m_nWordWrap == WrapToTargetDevice
4 L1 \/ u8 O8 _ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());# t+ E8 S* R, S$ Q
如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return" C) G. D; I8 {/ m# @9 R- y2 b
$ x9 M5 P5 I) @! D
f.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴2 X+ f- H$ X. d* ^5 {
pmyRichEditCtrl->PasteSpecial(CF_TEXT);
! [9 e9 w1 J7 g. Q% Y4 b( Y" f4 m; I; R! J: h8 [, a" q, S8 M ^1 k
g.随着输入随着自动滚动条滚动到最后一行
6 V3 Q0 u' M" H0 P# g) Cint nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();+ p: y4 H6 c8 d6 R
if (nFirstVisible > 0)
6 d4 k& ~7 k# p' d{+ H% Y6 L( ~9 K# T N
pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);
/ R* W% h/ O7 N}$ r/ B2 H- C2 o
或
+ `9 j! \# A T% v8 Cm_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);
, e2 G& r/ c9 V0 B! Z9 x2 @) w6 H: G. E; s
5 l, |8 p+ V3 J% T1 Y8 K
h.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级), A4 p9 v# ]' h7 C8 a5 T
SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);# n3 X9 p! T4 B, E, i! k
TM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数 ( X U: B: W* r$ N7 U
SendMessage(EM_SETUNDOLIMIT,100,0);5 v% {. ~6 f3 g& ^7 ~: r
# s* k* S5 k$ @* k2 a. `6 P! a
i.响应OnChange" m. T5 f0 O A9 L9 I0 j, T
EM_SETEVENTMASK 设置 ENM_CHANGE
4 T) Z* o2 A% |( `5 `long lMask = GetEventMask();6 A6 C& D1 c) b% k6 g' n; o
lMask |= ENM_CHANGE;5 H; u! P0 ~1 ?$ b$ w+ M
lMask &= ~ENM_PROTECTED;
, }5 K0 V# \( Z, v- BSetEventMask(lMask);
/ Q/ Q- B( L: f% ~6 m( H
% _% k6 v* \( G. }& g" H+ yj.设置只读
' x+ W1 K; f4 OCRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );8 ^$ T. c% y6 h! x4 l
通过设置PROTECTED实现选中的文本只读,参见
; m0 U1 o8 l) l- ^( n; j4 Bhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/
; i" U& s: w% {7 O' A4 ?- W. i. ?5 q" l3 }
二.函数应用
# X( \% `7 t; Za.设置字体(主要是通过SetSelectionCharFormat)
4 b* W% y M, G. j* CCHARFORMAT cf;" ~6 z0 W* w8 I
rich.GetSelectionCharFormat(cf);
# S( C# h& ?( j3 J/ pcf.dwMask|=CFM_BOLD;
! |" {1 w3 @$ e$ b' rcf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;* i- B, s+ A* ]4 }0 _
cf.dwMask|=CFM_ITALIC;3 X0 f" j: j, Q D+ F
cf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;5 L; D8 T9 _7 @
cf.dwMask|=CFM_UNDERLINE;
6 M! z$ S5 K5 Ecf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;+ g2 d8 [. ^' S. R
cf.dwMask|=CFM_COLOR; X! e$ i" t% V
cf.crTextColor = RGB(255,0,0);//设置颜色" V7 ]# p% k1 ]+ D! w
cf.dwMask|=CFM_SIZE;
8 V4 k: V ?" Ecf.yHeight =200;//设置高度9 M8 ^ t4 D' i( `' `/ ^- ^
cf.dwMask|=CFM_FACE;' q! g, U+ X& f* A
strcpy(cf.szFaceName ,_T("隶书"));//设置字体
+ }1 H& W8 G) B; o- X" trich.SetSelectionCharFormat(cf);9 g5 i/ B4 j" K* j
7 W2 M, ~! F6 O4 e5 D! K6 Y
b.设置字体的行间距# g2 _) a; Z" ^3 Q3 u
要用richedit2.0以上
7 t# v; @+ T- L7 t# r" v试试& K6 N5 a: o4 G1 P
PARAFORMAT2 pf;" }, E) C1 B. ]& u8 s9 ? n
pf.cbSize = sizeof(PARAFORMAT2);3 S2 i; x4 J9 Q* z: C7 M# B* s9 K# v
pf.dwMask = PFM_NUMBERING | PFM_OFFSET;6 U8 L/ @5 J, X3 x. x$ c5 {
pf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING
4 {6 x5 L" z2 T" `pf.dxOffset = 10;
( A" R1 R/ B- ^4 u% B$ }3 O8 aVERIFY(SetParaFormat(pf));
0 E+ s D0 l$ F) O) I常用的dwMask有0 T% e9 G: ~. @/ s
PFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET
0 q% {4 p9 p; u" j% ]6 i6 s2 使用阿拉伯数字 (1, 2, 3, ...).
" b: O5 z4 ]( H7 F$ o) G3 使用小写字母 (a, b, c, ...).
, z! H3 ]7 L: f+ a& f6 E2 @4 使用大写字母 (A, B, C, ...). " z' v' E3 k4 O0 q2 `7 m
5 使用小写罗马数字 (i, ii, iii, ...). $ I( \* h x# s5 r& e
6 使用大写罗马数字 (I, II, III, ...). , K* E" F7 P! V" s6 W' c, p
7 自定义,字符见成员 wNumberingStart.
7 H+ R+ v% j$ MPFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips
/ ~9 q( H- H) d) tPFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进
7 Q5 D- C; J% T- y0 UPFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距
8 }3 J, x+ \: `, B9 `% j" i7 p7 f2 bPFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距
/ F, S* _- D2 {% E, t7 J2 y# c
0 N- L0 E" E3 p( Pc.设置CRichEditCtrl(2.0)背景透明 8 K) S8 [, V: ]2 n
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);) I, e, X% \; w" M
style &= WS_EX_TRANSPARENT;+ [6 Z5 ?5 Q& V$ Z% \
::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);
1 \. j4 F' x; b y% i2 q3 T$ X4 |% K5 f- r或 CreateEx,然后把WS_EX_TRANSPARENT样式加上
! Z- M& a4 u( z# M( _1 x# ?" G* v
+ r8 F- o3 f5 ~9 Q4 D/ S1 be.得到内容有三种9 w7 v: y; Z0 R" z" U" j3 {* d
1)GetWindowText
! i$ ~# t2 w1 ]* s2)使用EM_GETTEXTEX
; e# w: ]1 K$ d6 g3 v( T5 dGETTEXTEX gt;
1 }: |5 I1 a8 w+ A1 I( }! d; kgt.cb = 200;
: v: A; q7 K7 n1 k5 ggt.flags = GT_DEFAULT;! }3 P$ b& \( u+ Q% p# n
gt.codepage = CP_ACP ;
$ M; h7 C) a* b1 mgt.lpDefaultChar = NULL; 5 M5 _# F% `; o1 n3 v! G7 D9 z
gt.lpUsedDefChar = NULL;. v1 j; f2 }8 W( V
SendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);
# d! x0 M% V) H" R) q3 R# F% t" I3)StreamOut(主要用于RTF等格式输出)0 G$ c) p5 I# S0 W
static DWORD CALLBACK Y) I# p) ?# H+ B7 g, [% p
MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
! n6 h. s- {3 [( K0 _{
" N; b/ i h7 b0 [7 Z X8 E R CFile* pFile = (CFile*) dwCookie;
" H' w5 n5 z$ \! t; F) y V4 X& a6 \( E
pFile->Write(pbBuff, cb);
) Y: K- x' {$ k+ C* T; |$ R *pcb = cb;& i% _) }" l! m3 V; p. V
& B, U1 W! y" ?9 }# F; V+ x
return 0;
1 s# ]$ n, p. e, h}: T- V/ t+ F) r5 y9 `' H) G
) C* ~- g/ l* V+ q# ` e8 }* D) i: P/ s4 \/ X& {, X! f
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);; V5 ]& T& D! S+ T
EDITSTREAM es;
7 @5 x$ j- A, o' j; F2 F es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用' z0 U' j1 y* M
es.pfnCallback = MyStreamOutCallback; ' p% B3 s( A$ R! B
pmyRichEditCtrl->StreamOut(SF_RTF, es);
0 H! c0 Z5 ~( C2 O6 y! Y1 ~读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn
0 M! Z( Q% W/ S
- j: ~8 e0 B2 e& l0 Ff.查找字符串5 [( D% b$ @% W5 d5 o0 O+ M1 \
FINDTEXTEX ft;" w. Z7 F5 p/ m
ft.chrg.cpMin = 0;
$ C l% @3 G- P. a- Tft.chrg.cpMax = -1;
2 w" c; M/ U7 {. cft.lpstrText = "|";1 V5 l" q3 P8 \' ]
long lPos = FindText(0, &ft);, B8 o! ]2 k2 B& c. U7 \( H* J5 `
6 P, o# Y% Z3 Y, i0 x
如果要继续查找,修改cpMin,如
$ D* Z* d( a5 A3 \int nCount = 0;' i" x$ P3 |1 S8 f( E7 a- o
do
4 ~ M6 x: V5 E ]7 C: y. ~{3 L# p/ v5 f% M" F4 |3 r
long lPos = GetRichEditCtrl().FindText(0, &ft);
, Y1 h0 e. ^1 a, T1 A1 F if( -1 == lPos) break;
( J: K" E7 \, @ ft.chrg.cpMin = lPos + strlen(ft.lpstrText);
/ O: q6 [" f- K# f1 Z' V ++nCount;1 |; w/ f$ R1 M# E; \3 k2 N9 V
}while(TRUE);
9 {4 c9 n: P( y3 h# H6 }" y( e
/ X1 [; a* z' xg.以Html格式保存
( r5 x( x8 I* f目前做法可先转为RTF格式,再通过RTF-to-HTML Converter6 \3 |+ f8 `# c( D) o: x
http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/; c* x% v& j8 v( e. X& P
3 m4 Y1 Y# t1 k7 h( a& eh.重载OnProtected函数得到对应的消息,如粘贴等
6 `- s7 M- |3 F8 evoid CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
) b5 d( X. e, a' ^8 d{4 ^( S+ m) u3 l4 \& R& s
ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
5 k7 e4 I: X2 V; m& g6 g
6 a ?: q8 f1 y switch (pEP->msg) {
h2 A, Z! G. G" U- y" L y: v9 m case WM_KEYDOWN://按键,判断pEP->wParam
: L e0 k" i. N6 @& v8 f0 p case WM_PASTE://粘贴
- l" o: V. \. E+ I! ~ case WM_CUT://剪切
7 {8 c' t; c! a case EM_SETCHARFORMAT:8 B# n/ h/ z! F) t v% p' S
default:
. J( A6 r" `" p break;
) h$ b% R* b! P, [ };
8 y3 z- c0 W" k2 J. N
6 f* X2 o$ Q3 T. \. O4 A1 s3 s *pResult = FALSE;/ O0 k# l6 q# [ z9 T0 z/ g
}6 X* k9 w5 h1 F1 d s% o& n
$ l9 [0 O5 F: y. ]. {/ A/ Q$ J
三.聊天常用 ! n& O: d. _/ \
a.LINK 链接功能
' e+ H8 f: R4 i I! B& w1. LoadLibrary(_T("Riched20.dll"));
3 r& y! t. Y( m$ C# F2. 创建RichEdit2.0控件
9 k+ G* X& x' X5 E3 j CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP
0 X% d( @7 o4 W% L9 H" t|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,
+ e) H2 j/ g3 Q4 r2 n) n: n$ ~ rect.left, rect.top, cx, cy,+ `. M9 W: ^$ S0 n
pParentWnd->m_hWnd, (HMENU)nID, NULL);
# r* g, ~" [# @, p3. 设定选中的文字为链接显示: e! h% {! @. X+ R, `
CHARFORMAT2 cf2;- P y& C& K I, |1 u: ^" }
ZeroMemory(&cf2, sizeof(CHARFORMAT2));//7 i: _! K- P, Q7 i
cf2.cbSize = sizeof(CHARFORMAT2); e8 X* p! e1 ]& `# F
cf2.dwMask = CFM_LINK;
) D3 N! r$ L8 h3 \8 Kcf2.dwEffects |= CFE_LINK;
. \6 G8 C, b% H+ d/ c6 i9 `m_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);* S1 [9 g& l6 I; s
4.支持链接的点击响应
$ r: }8 z) v) G. H3 v( Y9 A) im_cRichEdit.SetEventMask(ENM_LINK);4 {1 }9 o9 |3 m/ Z( f
5.响应链接的点击EN_LINK( _+ f& z* ~2 D3 @
) M& g1 V, j8 C# s3 @) D' O
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)0 ~- Z9 U3 y6 F
ON_NOTIFY_REFLECT(EN_LINK,OnURL)
7 J0 S! m P1 ^( y7 o/ nEND_MESSAGE_MAP()
& i/ M- g& E1 j/ {2 D....../ |# r. b* O/ Z/ j
& q$ W/ m, i9 Tvoid CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
) _" V( E! I6 F5 [7 o4 b{% k1 ` Y0 h, z( @
TCHAR LinkChar[512];+ [0 R ]9 ~1 ]& O% Y: v
ENLINK *pLink = (ENLINK *)pNmhdr;
& ?4 i% q8 Q# n( ?/ d+ o7 D, }$ X. Tif (pLink->msg == WM_LBUTTONUP)' _! A( ~) m" `' ~/ V
{' `% ~1 M a7 _% X5 S
SetSel(penLink->chrg);//这是链接的文字范围
- Y, j" K: ]+ B3 plong Res = GetSelText((char *)LinkChar);//这是链接文字9 O: b6 \+ T4 X. o9 H# S! F
//后面是你的处理过程
& u! j9 D7 ~5 Q7 V' ~( K8 H ......6 z: R" A) D: q: ~4 F" }% J8 T# @/ X# m
}
7 z9 w1 o% v! ?. o; ^: w. I}8 G' s" Q% `: r x" |4 `6 H# T3 F! W
& T$ ?9 w, e: G6 N6 |: ~b.插入位图
% D1 `1 @, f, A' M! w- Zhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/
7 o6 L9 }1 X7 l- s; v; s- m }8 Fhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/& Q1 d( } [3 W* d
( m) l0 d M5 t. S8 M
自定义在RichEdit中插入对象的图标/ `! \0 U" n' s' a7 N
http://www.blogcn.com/user3/jiangsheng/blog/1319738.html3 z1 y9 o+ O7 k+ j/ k" }( t$ E! G7 z
方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control; t2 C( W/ R# h% ^
只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片" H2 Q- M) |( T" m. _
( O. m# e D: _/ k使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。
2 S n& x; w, F2 `另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。 - u& Q/ O, W# j7 K$ C
! z' S. p7 O6 A+ zc.显示GIF动画
: _. T% y2 x4 C常用的是通过qq的imageole.dll(也有用Gif89.dll的)% } b& H2 y1 A: p# {: T
http://www.xiaozhou.net/cooldog/blogview.asp?logID=82+ J" c0 c+ k% [& s+ j
http://www.codeproject.com/richedit/AnimatedEmoticon.asp
, F9 e, ~0 B# R7 c! N) Z0 C5 ^ r5 {# ]8 A" q0 Z% a# H
在richedit控件中插入动态GIF (Native C++版)& e7 M: X5 q9 K
http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx
% L3 J8 t4 X9 t4 K1 I$ M( ?$ h4 B# z
- V0 e1 o$ g3 J, b2 Rd.IRichEditOleCallback的使用 U) `" M, G$ ]$ R4 N: X6 g
http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022; I, d: U& ^. b( S) C
+ K9 U6 f( K- E( o7 c9 m7 E类似 MSN 信息发送框的制作(上)+ \; i& C$ G+ v
http://www.vckbase.com/document/viewdoc/?id=1087# Q$ l3 u/ n& J% [
内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串, t7 n/ U N; T0 B
4 _ @. b( D, v, k; c; Y* T, N8 L
自定义 CRichEditCtrl 控件
# M+ {3 q5 U9 i2 N0 u4 phttp://www.vckbase.com/document/viewdoc/?id=328" h# P2 x0 g# L2 O
内容包含:鼠标右键消息,消息映射,字体变换
6 a/ D& G. J- o! t5 x* N! W
) d- s) Z! {% t1 a" K& m+ e: [PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母; q8 t0 s4 N6 W- p
是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778
5 x' a2 Y$ C2 _----------------------; O$ ?% Y6 l5 G( X: q4 o/ q1 r$ w: R
比我想象中还要花时间,所以最后潦草了点,见谅 |
|