|
一.常见问题# K2 ~8 B Y' N! @4 [
a.可以编译,不能执行的
: i; @6 G2 [: v# ^AfxInitRichEdit();
3 P8 g5 `/ w5 ]8 F
4 q8 x5 n* q/ _0 |b.升级默认的Riched版本(默认的有一些bug),如
8 n; E4 ~$ k1 q" ~$ ~) B可在InitInstance中添加, I+ C8 d- ]# r
LoadLibrary("RICHED20.DLL")
# K, ~9 @6 U" Y+ K7 W0 C1 ^最后注意 FreeLibrary/ Y. {, ?6 A# y# p1 m; q
/ ?7 D- |, S8 z& ~% b! R' O如果是CRichEditView基类的可用- m( w, ?) H% d& D! N! A
BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)* S5 h: p. @8 g6 F5 F
{: I) B2 u' ~, a
//装入rich edit version 2.07 M3 H3 Y+ ]" [3 b; Y; ^
if (LoadLibraryA("RICHED20.DLL") == NULL)
a3 v" [' A# v{
0 F2 V8 w6 s9 b: O( @# h/ AAfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);
4 i. ?+ M+ F0 RPostMessage(WM_QUIT,0,0);6 N( j& O3 O# c% p# K7 a3 X
return FALSE;$ I; D# V/ ]- e7 I, \2 |! Q
}" K- }* q1 z0 ~
" {; }, l) m8 C ^8 n/ Q! R5 xm_strClass = RICHEDIT_CLASSA;//for 2.0 class
& m4 p! I7 ?9 f+ x7 m- [- _$ b9 f4 x! `4 U' X2 E _, ]
return CRichEditView::PreCreateWindow(cs);" H1 m. R$ n! G
}$ O, _" S3 C& d9 _8 c; @( [
! Q' L( S! I" j
c.最后追加行
$ V+ Y2 z1 v& R" j; P# Bricheditctrl.SetSel(-1, -1);
. u& ?) f r: T4 b P* Yricheditctrl.ReplaceSel( (LPCTSTR)str );4 s- B4 k0 {0 [: q
, P) ]6 d' I- C M; @& c7 l; Q
d.字数限制
' [7 h1 A( Y* `5 O2 j3 D) q; cCRichEditCtrl::LimitText(long nChars)
7 y9 Y% ~) g- S9 f$ G% N. `$ m; S$ a$ n5 E. r! t
e.换行切换
q* G" ^0 u- g- v1 U; ~. hCRichEditView的OnInitialUpdate()函数中加入下面两句:
: v, [2 g8 M9 e" w1 om_nWordWrap = WrapNone;1 |3 @9 Q1 c) f4 `0 F: {/ y$ n
WrapChanged();
7 I0 c5 K0 {! s7 i \. DWrapChanged实际上也是调用1 v; O8 v. X' m$ R1 Y0 f8 m3 r
ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone9 K# ?) U1 J: C* S6 I
ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow- P' t, |& h" r
还有不常用的 m_nWordWrap == WrapToTargetDevice/ z: Q" v. f/ V; y1 i& N. V4 } j
ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
' Z l2 ? Y5 {$ g8 C! x如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return
% C2 Q4 d3 D& U: h0 `9 X9 b5 c# V% K! h- e4 U3 ] e
f.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴
+ D0 F. ~, P' N9 O$ w/ ]8 X6 rpmyRichEditCtrl->PasteSpecial(CF_TEXT);3 e, P* C, k5 I& e2 d" ~( l. i5 ]' d
- Q' v7 S% V& _( og.随着输入随着自动滚动条滚动到最后一行& J1 E. c1 e3 f. d. `3 ?
int nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();
/ |. i8 |* \. q# K! F$ I/ z5 Uif (nFirstVisible > 0) |0 a' c7 t5 m+ K# S1 l
{
# f4 I5 T4 q7 C; P# U# L% {9 \: A pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);$ d) E5 [3 S! @$ ]
}
4 B. c9 `4 N; x5 q6 y或* y( b3 B4 ~( X5 C y5 C
m_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);
( y# K+ `! G Q8 H6 J
% m7 w# n0 l2 F4 V0 \0 a i2 W3 O# p5 `; V, Q& h
h.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级)
$ F& \# Q4 w! Y5 ]4 c" I4 ?" ~SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);
; g m! I* \( l! @& rTM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数
: V8 c, k, F5 YSendMessage(EM_SETUNDOLIMIT,100,0);) r) J; D1 J! p. e, D' s3 n
9 a, L! g! F7 F; U' Ki.响应OnChange
0 u( `2 I4 ]% U3 MEM_SETEVENTMASK 设置 ENM_CHANGE
# r% U6 j9 m8 R$ G3 f! y5 J4 Glong lMask = GetEventMask();, Z6 M% Y5 ^$ k; B
lMask |= ENM_CHANGE;
# X! ?$ u/ T, b$ M; b" ]lMask &= ~ENM_PROTECTED;
6 u& M+ R2 z" mSetEventMask(lMask);
8 Z* z9 f4 D) r) J! W/ O K5 h* z3 n# U5 T3 u) b$ H2 O
j.设置只读
" p5 B, X+ Q+ v& k% yCRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );4 W1 L7 ~6 D% j) A% m( l
通过设置PROTECTED实现选中的文本只读,参见
' Z; y& Y5 W$ I1 Hhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/
! u$ a4 G9 e& j+ x1 z$ Z0 d1 v( r
* e$ J! q* e& k' y! i二.函数应用
5 y4 g1 ^+ q8 W0 k; Q. sa.设置字体(主要是通过SetSelectionCharFormat)# w6 Z$ Q k( `/ ~
CHARFORMAT cf;4 S% p: G) o; R3 ~/ w
rich.GetSelectionCharFormat(cf);
' ?+ \ J# J1 Fcf.dwMask|=CFM_BOLD;
9 \. \6 u; q+ p" k7 E: A: [0 rcf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;
! g! C9 R" }$ @: \$ gcf.dwMask|=CFM_ITALIC;" U' q, h9 k: v- }( W$ l; l
cf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;
' W& I3 i4 F. W4 }+ R8 `& a, {cf.dwMask|=CFM_UNDERLINE;
7 z1 T: G+ J/ Vcf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;
* D6 v* t9 A, H1 z; h6 @cf.dwMask|=CFM_COLOR;
* X) c# d: L. G% Qcf.crTextColor = RGB(255,0,0);//设置颜色
7 B v7 m0 d `" c4 E6 W( Ccf.dwMask|=CFM_SIZE;
. z) x) B& i( t# g4 H) A& Qcf.yHeight =200;//设置高度; F" p% G' O( E8 W/ @6 i# K4 H5 I
cf.dwMask|=CFM_FACE;2 y* `: g2 I1 n7 P* o
strcpy(cf.szFaceName ,_T("隶书"));//设置字体
3 F& L. ~& m" x& X3 |* ]- krich.SetSelectionCharFormat(cf);
( X/ S7 ~3 u$ q6 o9 O' O* F, q( M" I
3 g, o4 p- y5 Z* S& y! lb.设置字体的行间距
% n+ m/ w4 U$ Y要用richedit2.0以上 }3 M: L# Y/ p- k) G
试试% \) j4 G0 j: S: o) s# r
PARAFORMAT2 pf;4 T! V7 q8 c9 t( _; W: N' H
pf.cbSize = sizeof(PARAFORMAT2);+ X; b1 H, ?4 h+ z/ x
pf.dwMask = PFM_NUMBERING | PFM_OFFSET;
/ t4 N' l/ W, N& P! u& }, Gpf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING
& R) }0 P2 c- C3 G2 {, S9 tpf.dxOffset = 10;) s9 ^; e! D$ X I* W: F0 L
VERIFY(SetParaFormat(pf));
0 M. [0 }5 p3 H6 \0 N3 e. l# h常用的dwMask有
5 X2 \) ]" O& j4 Q* x: V6 e% d9 RPFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET$ g Y5 J- i( Z' \% o$ U
2 使用阿拉伯数字 (1, 2, 3, ...). 8 o2 B# q1 L/ r% F4 P
3 使用小写字母 (a, b, c, ...). ' `: r# R5 E% ?# i
4 使用大写字母 (A, B, C, ...). 6 ^/ W& P3 s% i0 w4 y
5 使用小写罗马数字 (i, ii, iii, ...). + v! |7 O" |3 i% U
6 使用大写罗马数字 (I, II, III, ...). / d' G" f) n& |3 s1 ]
7 自定义,字符见成员 wNumberingStart. 4 g2 f1 j2 F w2 I6 K+ Q9 b
PFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips# A8 S6 c6 u; `! W# E# a
PFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进
4 Q7 @9 ~/ q/ cPFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距/ G9 S* A8 O, a) M$ M8 s
PFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距; P* H% s- _2 L, V
3 K9 X/ j2 t! b. s
c.设置CRichEditCtrl(2.0)背景透明 ) F2 \9 Y1 y/ @; g) y* C. P% R2 a$ }
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE); `+ j* U7 P( n8 u5 C6 v
style &= WS_EX_TRANSPARENT;
, _ U6 W0 J; U$ N- ?3 L::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);6 B# Z, a P) U( H) G
或 CreateEx,然后把WS_EX_TRANSPARENT样式加上
0 q3 e$ j- D. G1 l8 S' ]8 h4 e% r" n+ n" a- D
e.得到内容有三种( _7 o4 S6 I# L2 u1 @3 R
1)GetWindowText
; b( q) d+ Y% o+ l1 L1 `2)使用EM_GETTEXTEX
) y+ j' a2 y. rGETTEXTEX gt;
; \& _: N. u6 u3 D0 M. agt.cb = 200;4 f4 n8 L' p% p$ V+ h
gt.flags = GT_DEFAULT;
8 A- I) f3 a2 g4 T6 Hgt.codepage = CP_ACP ;/ Q6 h1 v7 O9 c5 F7 N: w* `4 i
gt.lpDefaultChar = NULL; 3 w$ K9 |# K- {% Q
gt.lpUsedDefChar = NULL;4 I* s! C4 l% `, r( t2 I- `
SendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);
# v5 F* ^ B! ^! P$ {: A! I3)StreamOut(主要用于RTF等格式输出), ]: v& R# q0 b* I
static DWORD CALLBACK ; M, n) q- f1 P( `
MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
0 f* N: I: X. E{. g4 E- Z- t3 p3 g& ?
CFile* pFile = (CFile*) dwCookie;
. `4 L( c; v ~
/ d9 Y; s- t# s! W0 y pFile->Write(pbBuff, cb);
[6 B5 H0 ?- q *pcb = cb;
* n% Y6 L% _6 a4 q, B$ ?7 r" z& x) e7 S& o) o' V
return 0;. D' |! ]7 [1 E( g0 f# d
}
) f: ]$ C0 {) B4 ^( t: ^
. t) D8 y& q2 N S: ^& c% w: ~3 L. G$ s8 N
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);* k7 h' D" f$ _5 E3 z' H
EDITSTREAM es;5 d& H4 Q+ f+ i& b& l$ T
es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用$ C0 r; D) F9 I) w( g+ X
es.pfnCallback = MyStreamOutCallback;
$ U$ C& e/ J7 l4 R2 F pmyRichEditCtrl->StreamOut(SF_RTF, es);# Q+ [' b6 J6 ^: A% T
读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn) R) K6 G) u: R6 v7 X( j0 j
$ D0 X# j9 ]' {6 ]! A
f.查找字符串
0 \ y$ F. x6 z4 h8 J' \FINDTEXTEX ft;
: ^$ I$ W, t( m1 ^% f% A0 qft.chrg.cpMin = 0;4 V- f% T- c }) s1 U) ~
ft.chrg.cpMax = -1;& j5 {& }6 {$ }5 k2 L. ^# F* B0 J
ft.lpstrText = "|";
( V" z! Z2 K b, I; p+ U8 tlong lPos = FindText(0, &ft);4 |. s9 D/ M) v/ ~
/ u0 Q: V& K) M# t
如果要继续查找,修改cpMin,如9 B7 d3 j: p% k% \* j# J! s4 H/ a4 I
int nCount = 0;
3 l* q/ F& v7 I3 `% Q# Kdo
1 F$ n5 q+ R1 J" T* i{
8 H8 f& K* {9 ?" I+ T1 X) p5 d long lPos = GetRichEditCtrl().FindText(0, &ft);
( [2 F; P( l' f& { if( -1 == lPos) break;
6 p7 \/ l6 A# E Y4 \# z4 ^ ft.chrg.cpMin = lPos + strlen(ft.lpstrText);
& y- [( }8 w8 o% B+ S }3 l ++nCount;. p6 w/ n2 }# q7 I! _4 V
}while(TRUE);
' ]- ^! L1 {, a1 T/ U. g2 i3 ~( H. i! Y s q2 Q
g.以Html格式保存
$ u2 \3 y# K8 L6 U目前做法可先转为RTF格式,再通过RTF-to-HTML Converter
$ c. w9 e6 x: J4 H& y) Dhttp://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/
" D" p& B5 E+ X
4 Y7 q _8 [, ^* ^0 X, T! T8 Ph.重载OnProtected函数得到对应的消息,如粘贴等/ K1 [) T9 L6 k; F# @' N
void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult): O$ }- ^) A" e# e5 k/ X* ~% T
{
5 S+ v& t1 z5 S6 D5 A1 p ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
2 z, @( y0 F4 K( f# A5 P, D( l) f2 i v7 a
switch (pEP->msg) {. a" v3 N/ k! j: V% p) X" d
case WM_KEYDOWN://按键,判断pEP->wParam# j Y: U; F4 t* O$ |) z( F
case WM_PASTE://粘贴
, {$ M6 e. F6 T1 a! \" d case WM_CUT://剪切' q! l1 E5 Y) o
case EM_SETCHARFORMAT:2 t* q# q" X& g& k( m! h3 c
default:
e2 @$ M0 X- _( J break;
0 O" |; }* V: `# G1 M* [( z };) m/ a# s5 Q8 Q1 }0 r
* S" b: G2 |* {# z8 r* s *pResult = FALSE;
4 _; S' x, o' T# Q( O}4 L; W y8 M! d6 V
( y0 [# A& Q3 _9 [( P) c% W
三.聊天常用 % `$ J* \5 ?! ?$ c3 r0 C7 Q
a.LINK 链接功能
* s! a8 ]7 E7 o7 n' L) S7 S! m# K1. LoadLibrary(_T("Riched20.dll"));
3 F- ? J/ M+ {* P2 R5 b% w2. 创建RichEdit2.0控件% ~% c# Z; D- S/ m; |
CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP
$ |# l, `2 c! J; o1 ~" c0 b|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,0 a* q% |# ~6 s; K( M0 l B
rect.left, rect.top, cx, cy,
8 n/ L; g" W% k! E- Y6 d& n1 ~ pParentWnd->m_hWnd, (HMENU)nID, NULL);
8 L6 [1 p& c, ^7 W2 o" o3. 设定选中的文字为链接显示
3 S. o# t, Y1 `& j; t) W/ O8 eCHARFORMAT2 cf2;
; `/ @$ G- u2 n" P$ ~ZeroMemory(&cf2, sizeof(CHARFORMAT2));//
( f8 E8 ^1 X+ g% E$ d: g. Dcf2.cbSize = sizeof(CHARFORMAT2);
7 L" m J. ]' m1 F; I( }3 \' B4 c8 Xcf2.dwMask = CFM_LINK;4 v# F- ?; Y0 M+ C$ g( G
cf2.dwEffects |= CFE_LINK;
4 H- } z+ v4 l% S) d$ xm_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
3 u9 ?/ O* i9 K4 q* H4.支持链接的点击响应2 _; M6 {8 t: B+ s8 m4 S3 n! K
m_cRichEdit.SetEventMask(ENM_LINK);' T5 |9 Y$ ^ g! x; C9 u2 t" [
5.响应链接的点击EN_LINK9 t, r5 O3 y8 T6 s7 h
2 V- Y# B- }4 m/ G3 k/ nBEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
+ y/ B& e$ ?' b9 {; ^: W7 b6 V. iON_NOTIFY_REFLECT(EN_LINK,OnURL)9 n% r4 k) v3 ]% }& c1 j @/ B! i
END_MESSAGE_MAP()
- P1 u1 z# G* ]+ h* r4 H( n% z......
+ K F. T! P" w# I! B, T* i7 J
5 [4 _$ q; P/ ] z; zvoid CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
0 u# U8 [& J) u- K/ g% x+ n{
7 B( G- j- Y) R6 FTCHAR LinkChar[512];% z. ` n$ K4 q, P6 F
ENLINK *pLink = (ENLINK *)pNmhdr;! }/ h- a6 d7 ^# L( {' {- f$ N
if (pLink->msg == WM_LBUTTONUP)
3 s# Y, P; Q0 ^; e) Q3 ~2 A{
& B1 Y$ i* f# s" C5 r3 k, x8 I5 cSetSel(penLink->chrg);//这是链接的文字范围
" _. G* _) P$ P4 e7 Vlong Res = GetSelText((char *)LinkChar);//这是链接文字
) M0 V1 M% `* h- r4 T8 y5 e/ o! x //后面是你的处理过程
5 t% E" F- D8 y! w1 |- W1 V ......& G2 ^: R, E9 }2 l
}
( B8 n! H0 I8 i0 l5 O/ b" b}9 `( L- w) a8 n/ G, a
- }5 e" N0 u' d7 F1 U* P; l9 T) A
b.插入位图! ~& d: F, C" \5 \3 M5 R' I
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/0 n. e1 K# q3 s/ V* C. V3 T* [6 Y
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/" h5 ~) ` [: y3 Z3 t5 d
) A4 O* {5 w% X/ I7 n自定义在RichEdit中插入对象的图标. B8 N3 O- K' @. k+ X. p( z# Y
http://www.blogcn.com/user3/jiangsheng/blog/1319738.html# B" I+ ~) S: X, u; q
方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control" l9 G/ ]" x) E* ^
只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片$ @+ Q* [3 m) g! r: e) l
$ u. K1 `$ z0 ?* a F1 K使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。
2 ~ d1 R( t2 F0 j2 m) }: s0 Z/ s另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。
! O' A% P0 e, ?5 j6 s c
7 T6 S$ f) a! ~: @) o' Rc.显示GIF动画
5 H0 q5 C7 O, v# }常用的是通过qq的imageole.dll(也有用Gif89.dll的)
1 v/ j% e j) ^1 S8 Q$ Thttp://www.xiaozhou.net/cooldog/blogview.asp?logID=823 z5 d: [6 |1 G# T5 R) a2 u4 m
http://www.codeproject.com/richedit/AnimatedEmoticon.asp, X H5 R% P: y9 ?# ^
+ {+ K! y* Y1 {; R* ~; C
在richedit控件中插入动态GIF (Native C++版)$ \ _; A0 F/ ?% X8 m/ N ^0 [
http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx0 I5 {& j/ x$ S4 b
8 _8 }2 q/ |. Ud.IRichEditOleCallback的使用 w7 {9 [ z" }8 Z- e
http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022, ^6 V2 H* V- q" V0 a
' Y# P1 J& r8 Z" `! A) ^
类似 MSN 信息发送框的制作(上)+ n1 E6 M" p& {9 T* A7 ~, L. s
http://www.vckbase.com/document/viewdoc/?id=10872 v3 A' @" `+ ]2 `& @& ~
内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串/ d: p; h% [+ F2 Q; u8 y: n! V1 f3 @
7 B" P# K: L% x8 |9 W0 U& [' Y自定义 CRichEditCtrl 控件
1 U7 c' Q4 X" w1 E ^! Q0 H8 l# jhttp://www.vckbase.com/document/viewdoc/?id=328
: x! s- R2 P; s内容包含:鼠标右键消息,消息映射,字体变换" X/ Z8 e) ^9 m& w; A* o1 x
7 W. T! ~- s6 E: a% J0 g- w h2 B9 b
PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母. E- S1 a1 D' N
是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778
* k" l3 `, s+ L( Q----------------------
1 x2 r& D2 g+ D h8 C" j比我想象中还要花时间,所以最后潦草了点,见谅 |
|