|
|
一.常见问题
" y$ m2 z9 b/ Ua.可以编译,不能执行的5 Q7 H$ z/ Q9 m( N7 ?
AfxInitRichEdit();, C8 i }+ ]* T% T+ r: N( X
8 E1 g. `* r0 u2 {3 u, q9 D+ yb.升级默认的Riched版本(默认的有一些bug),如* E9 f- h" i) V/ c7 Z/ F, G& B* T& }
可在InitInstance中添加8 \1 S9 G$ M# _( n* w
LoadLibrary("RICHED20.DLL") & G* }% A. |) K, p( t2 }' u( R0 w! p
最后注意 FreeLibrary7 G+ D0 J5 x0 i
, B. G" G5 H; f7 ~5 O如果是CRichEditView基类的可用
6 x0 d- L+ L1 E* J# DBOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)
4 ?0 o2 E9 E( @4 k{
" ~/ ]1 I Z: {% ]//装入rich edit version 2.0( M$ s: f- H0 i9 z) S3 n( o$ J
if (LoadLibraryA("RICHED20.DLL") == NULL)/ s& x' v7 M8 t# V6 H( V
{, c2 _0 @; I, ]- f- x, h) x
AfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);9 b! t9 P/ W1 a G2 X
PostMessage(WM_QUIT,0,0);
' O- {3 k& w R( ?return FALSE;
' o$ x; R8 ~6 i A6 i}5 F6 u- p1 z" }
' Y5 y ?% F2 W" |
m_strClass = RICHEDIT_CLASSA;//for 2.0 class4 F- n* S- t |6 o
; Z% z$ S( r8 S7 _5 T8 S `) Areturn CRichEditView::PreCreateWindow(cs);5 u# M9 E- b3 {/ R- Q
}8 k) q. r" W5 E/ h; a1 v' t
9 P/ w7 r; W6 [8 K8 Q% d( x
c.最后追加行0 d: Y. t k. A8 b
richeditctrl.SetSel(-1, -1);& O. m6 [8 M9 R5 B, S$ O4 ^
richeditctrl.ReplaceSel( (LPCTSTR)str );/ I) K J- u8 v* x* @' P* I: \+ ?5 A* O
# Z% e# ~* g) X( fd.字数限制
8 a& @( z9 a8 N8 T9 ECRichEditCtrl::LimitText(long nChars)
4 q+ y7 w( F9 Y6 t% G' K( d/ w% _: J, U1 p
e.换行切换' ?6 @, J9 r3 j# m' n8 n
CRichEditView的OnInitialUpdate()函数中加入下面两句:6 H8 |+ Z& P/ y' I& l* U
m_nWordWrap = WrapNone;
6 i9 t4 j; s# B/ f5 T' P; X) b, ~WrapChanged(); ) i' o2 K3 M' |9 J2 ?$ A
WrapChanged实际上也是调用$ s* w9 k( `* I4 Z# i
ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone9 h: Y; V, r& H$ T0 I/ a
ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow2 e- v( z- N6 k Z% W8 r
还有不常用的 m_nWordWrap == WrapToTargetDevice9 S$ Z; ]: C8 w* V6 |
ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());% [8 F2 s0 D8 M" V) B
如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return+ b# Z) u3 P9 z
* H3 O5 a/ B" u8 ~
f.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴
p- g" U/ D9 _& W! S# ZpmyRichEditCtrl->PasteSpecial(CF_TEXT);
2 l# |# q3 h8 ?+ q3 h( J6 z
! m+ L, I! c. q# T' `- J( Rg.随着输入随着自动滚动条滚动到最后一行
: O/ M5 M8 ]$ \; Z0 H/ p+ t# dint nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();( ]* h% Z2 x- n0 e& z" f* K) o3 l2 n
if (nFirstVisible > 0); k5 s6 b( b) b& g- t
{
7 `) q. V# O. d1 w/ ]+ J' I4 K pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);
: Z- C+ y& i" g- u' c6 `2 l- G}% T- A5 S3 _8 S+ A
或
9 g' ?' n' \" N$ dm_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);
+ L& Y3 N& i2 ~. ~7 W0 q4 e; ?! H- |3 d# l* [$ l; ]/ r* M; O9 o
W5 U. z" ~" l! q: Q, \( W& N i
h.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级)
3 }" A; y! q& W4 k( w' ESendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);9 W( J, S0 k, T1 _1 x u
TM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数 8 ~+ X. c& [+ |% C
SendMessage(EM_SETUNDOLIMIT,100,0);# ^# `* v8 U6 u+ m+ ^2 I6 O1 g/ y
& s2 w& D5 J2 h8 l Z% `& b9 bi.响应OnChange1 v; e9 @0 e. u+ R+ ^5 ?& G
EM_SETEVENTMASK 设置 ENM_CHANGE / N7 R) W3 V1 P! D* h
long lMask = GetEventMask();0 c9 i$ [* _% X z7 l8 @
lMask |= ENM_CHANGE;
% ~9 i! I9 W1 j, S% p- x* RlMask &= ~ENM_PROTECTED;+ F/ V8 J7 E! A1 {" H) [
SetEventMask(lMask);( k- J- A, ^1 n( O; _
& w& @+ n C, `8 L* |
j.设置只读! D ]) F5 l" Y7 q q- H
CRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );
& N L, v+ X: ?. j) @/ D通过设置PROTECTED实现选中的文本只读,参见, _: W1 x6 ~; J$ J
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/$ w9 G. \9 h4 b2 }8 f! P4 K) X7 P
6 N5 J1 L# A8 D% S t
二.函数应用' ~' g8 u( I! a" J% K1 e
a.设置字体(主要是通过SetSelectionCharFormat)
5 ?" B- `' p+ k* H5 L. JCHARFORMAT cf;! N) m: {: |$ R9 g0 J; v
rich.GetSelectionCharFormat(cf);& i0 O6 v9 n2 C9 {( u6 B1 e, _
cf.dwMask|=CFM_BOLD;' X+ D7 Q2 H3 ~+ V" S
cf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;
6 ^7 v5 Y, ]6 e+ O: h. `6 ]cf.dwMask|=CFM_ITALIC;
$ x2 b5 Q; V( c6 f' i" ^5 I3 ?cf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;. R0 z& @* l5 M& D D) ~
cf.dwMask|=CFM_UNDERLINE;
1 a) L9 b: m5 t4 r, M6 F/ R$ G8 I t/ ]cf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;
4 A5 ^6 K, O1 bcf.dwMask|=CFM_COLOR;( G1 L* s& R' k3 U# f3 Q1 h
cf.crTextColor = RGB(255,0,0);//设置颜色
0 k( t3 r3 c0 M+ @; F* Ycf.dwMask|=CFM_SIZE;/ b: e) U0 x* s+ f- F5 h( Y% d
cf.yHeight =200;//设置高度9 d0 E* y: d2 u, l2 D
cf.dwMask|=CFM_FACE;+ R- g$ I. b$ `. j' b! h/ b
strcpy(cf.szFaceName ,_T("隶书"));//设置字体
: l2 N4 s8 }+ U# u B: w. p/ qrich.SetSelectionCharFormat(cf);: w6 l6 k9 o, `2 w' p4 c2 F5 f% X
# h0 s, q6 D) L& o! c9 c
b.设置字体的行间距: s% `! Q" j1 C5 m5 r6 ?. d( \0 c( z
要用richedit2.0以上 k& e; { N7 s* I( V X4 `$ I4 G9 [2 U
试试
0 g. D! [5 E$ m# t- l3 N' JPARAFORMAT2 pf;
* B9 C0 ], Q- S6 `) z$ }( ^pf.cbSize = sizeof(PARAFORMAT2);- a7 o; P. I8 t( t# `. Z
pf.dwMask = PFM_NUMBERING | PFM_OFFSET;
% T; y5 [0 B5 l# v+ ]8 ~6 Wpf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING 1 L% ?/ b( X) N6 t$ E
pf.dxOffset = 10;
0 m' A" [$ U5 k) B% VVERIFY(SetParaFormat(pf)); & @6 L5 x0 E1 n- N" m/ N! x( X3 C. V
常用的dwMask有
* D* B' }1 g7 V" z( |- w4 FPFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET
1 p5 {! D9 z7 \2 使用阿拉伯数字 (1, 2, 3, ...).
4 I$ o( C$ E$ a) X6 a& _ C3 使用小写字母 (a, b, c, ...). 3 e& [, D& T; N( S0 {
4 使用大写字母 (A, B, C, ...).
_; m* h: f' ]7 B3 E4 o) z5 使用小写罗马数字 (i, ii, iii, ...).
5 h* e& G* n' T y2 m) U- n9 J6 使用大写罗马数字 (I, II, III, ...). . j; r7 l7 t# ]; H
7 自定义,字符见成员 wNumberingStart.
+ B! r7 p: n2 X0 a% F) j$ \* }PFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips
+ P0 X& \6 G) Q2 U% @PFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进7 [- U1 d# Y! Q
PFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距( e9 V/ T( S- A; P- S
PFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距" H/ q& ?+ d4 m3 c
1 \4 ] c; T# N; u0 x8 s" G
c.设置CRichEditCtrl(2.0)背景透明 ; U7 f, _! u1 Q4 Y
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);4 D3 K d6 ~ O }4 q
style &= WS_EX_TRANSPARENT;1 h; T t2 T( n L3 M
::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);
' ]" [: u. P5 J, p7 d或 CreateEx,然后把WS_EX_TRANSPARENT样式加上
% M/ {' Y0 A* w, l6 F6 s( o2 j$ l' D
: E4 z5 ]2 P1 N9 c8 o, Ne.得到内容有三种
4 S; B; N& a# v& x1)GetWindowText8 i7 g/ V q" v
2)使用EM_GETTEXTEX( O. P( V+ t3 W* [$ s( E9 a, Y
GETTEXTEX gt;
7 v3 l7 d* V, E3 Z; }) H2 @; vgt.cb = 200;! Y! r1 d8 z6 a
gt.flags = GT_DEFAULT;$ H0 I# w5 {1 @) S) b! a
gt.codepage = CP_ACP ;
/ Y+ r7 l7 k; _. x+ hgt.lpDefaultChar = NULL; 0 U% g6 D, P" w$ Y8 n" U
gt.lpUsedDefChar = NULL;
, V. R$ V1 I z8 @2 y0 U( pSendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);+ _6 Q* [: c7 P( ]; o6 U" i/ i
3)StreamOut(主要用于RTF等格式输出)
. g# L) t; E/ v8 e3 ystatic DWORD CALLBACK
) l& { J9 ~( K5 @$ \MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
2 B" z; l- E* f8 @* @{* x* u( Q" b( s/ f# E) s- w
CFile* pFile = (CFile*) dwCookie;
- E% z! Y0 N/ e- q; C* [+ K* _1 Q* Y, s j3 d
pFile->Write(pbBuff, cb);( M3 }/ b& E4 F+ y9 G. K
*pcb = cb;
+ g' [% a2 q& N& h) \; ?0 A/ t( Z! `$ w- t3 r9 H7 T
return 0;
" o) C* m8 p1 _" B}
! P& P! a) n! T
' Y! |0 \2 x1 D4 k2 l4 M" u* Z; _ y+ E. F) h5 e- J. a- J: L/ z
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);3 s8 d% g+ O, b y( s% u4 _
EDITSTREAM es;# V6 |7 Z. t2 W. r0 H' b) E
es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用
. n% S9 g! ?& l7 X, [" \ es.pfnCallback = MyStreamOutCallback; 4 T* N: ?) g" a
pmyRichEditCtrl->StreamOut(SF_RTF, es);
J! c' D, X3 c' T' y) X* |# w读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn) F+ `3 Y1 B& K2 Z- N
t* v& M! {! af.查找字符串+ A2 b( [: `3 ~ [: ]$ H- Y) ^
FINDTEXTEX ft;* |) W e2 B9 w3 l9 s
ft.chrg.cpMin = 0;0 `: ^( J, L" b& R
ft.chrg.cpMax = -1;
+ V8 g1 |% L3 H! U" S8 Vft.lpstrText = "|";& x7 D3 N" f- T
long lPos = FindText(0, &ft);- f6 g% o% a4 |: E0 M# ^$ _
1 f" O/ {8 B+ p# r" z如果要继续查找,修改cpMin,如
# \% Z0 M2 m; Z) @; gint nCount = 0;
: ^+ I: y" U h1 m5 X+ H# k$ ndo) o# E. w7 B- W* p+ U |5 m! O
{: Y, W, P0 `+ E6 e/ E8 P( ]
long lPos = GetRichEditCtrl().FindText(0, &ft); L$ G; b/ A' x9 k0 `. s
if( -1 == lPos) break;
0 g) Y8 V# z/ F- v) v ft.chrg.cpMin = lPos + strlen(ft.lpstrText);+ T# y' ]" O$ I+ M+ m0 v
++nCount;4 A! K7 L- Y* Y$ X5 m& Q4 {& _
}while(TRUE); g" x% \9 ~1 J$ i- `1 U
- Y) t7 {! C9 u: F6 e3 E" v
g.以Html格式保存9 K1 Y- ?6 ], _* K/ r v
目前做法可先转为RTF格式,再通过RTF-to-HTML Converter
' y! q3 [5 k# G+ hhttp://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/
+ b2 @) H$ Y! K0 y) E4 \9 B
( R, Q H$ g2 v5 Dh.重载OnProtected函数得到对应的消息,如粘贴等4 }. b$ q7 Q) R
void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
; G4 o d! D" C- s5 D7 D* D{
3 i* d' i4 q! T* G, |8 ]: e ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;) h) k& t% Z0 h- D
9 V7 n5 U, N! @$ k+ U switch (pEP->msg) {
* [# [+ Y; R' }0 |9 r case WM_KEYDOWN://按键,判断pEP->wParam
, h+ X+ Q) }9 r- G- [) L9 _* x case WM_PASTE://粘贴. [7 N( ~. h K! d# @ M* V6 Y/ j: V
case WM_CUT://剪切6 i( u5 m& @6 i& A
case EM_SETCHARFORMAT:
+ _ P' J( E. O x, I! m+ E! d default:
2 t% _! o4 e$ R, a. I. i break;
% r( u) B9 {1 a* X8 { };2 B( q! r5 y( k& j& i
- T; S( n8 P$ ~. E *pResult = FALSE;' e; E) Z/ U+ O) N, f8 _# f
}
( K8 W- V3 D! {! {
# g! H. w; z' [8 S2 y2 \三.聊天常用
( C$ a: B6 l; v6 W2 X: z2 @" |' f2 {a.LINK 链接功能
* Y0 l \9 L# s1. LoadLibrary(_T("Riched20.dll"));" H1 |. B8 J7 x2 ?9 Y6 W
2. 创建RichEdit2.0控件
# \3 A7 \2 G5 C, G6 r CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP7 Z( k$ U0 G. j" }" C b% x
|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,
! j- @/ v5 ^. G4 Q% p rect.left, rect.top, cx, cy,; J% f1 Q& x9 r2 B1 `/ w+ c
pParentWnd->m_hWnd, (HMENU)nID, NULL);8 D. I2 l2 R# J7 ^) R& |0 j
3. 设定选中的文字为链接显示2 Y- w( | m* [
CHARFORMAT2 cf2;& U8 l- O% c( O" X& l
ZeroMemory(&cf2, sizeof(CHARFORMAT2));//
7 I0 S% y5 B% u7 s' A: R) o0 Bcf2.cbSize = sizeof(CHARFORMAT2);; i' R+ |* h" [0 Y
cf2.dwMask = CFM_LINK;
) J4 F. l( |0 g4 |. O1 w+ Ccf2.dwEffects |= CFE_LINK;
" g) l! @6 h3 O2 I+ l, \0 [2 x5 n+ g$ om_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);; N3 t8 V1 q# e, L& w% V
4.支持链接的点击响应
0 D: H7 v/ K9 Am_cRichEdit.SetEventMask(ENM_LINK);
3 H3 r3 Y+ z6 G' X N5.响应链接的点击EN_LINK
' y1 v5 I/ t0 U' q
% }0 b6 g6 `$ N8 r3 [, |2 mBEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)' n( q6 d# G1 o
ON_NOTIFY_REFLECT(EN_LINK,OnURL)
: l- ~4 b2 n* n0 B( t& q9 g" x7 sEND_MESSAGE_MAP()
3 H6 H2 _/ N8 V- U- U......
# q7 t* I* A1 c2 n/ Y% c0 m
! y% Q; w2 A1 i8 Q! h4 \5 L# @void CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
# B; [4 I+ Z7 k1 {2 u/ {{
; O9 p* n- q: m' l9 a8 U' z4 NTCHAR LinkChar[512];( a) U- J! h7 H8 K
ENLINK *pLink = (ENLINK *)pNmhdr;1 ]% z f5 Y3 R: X
if (pLink->msg == WM_LBUTTONUP)
- K/ ^, x. V4 V( V: R{8 f" f* E# `. r1 N! R* Y& |3 R& |$ _
SetSel(penLink->chrg);//这是链接的文字范围
1 {5 P, S5 l9 j- c+ i) D) flong Res = GetSelText((char *)LinkChar);//这是链接文字% M) p" h6 X% L( U- L5 r8 q, i1 @( g
//后面是你的处理过程/ ]' A& D2 ?. ] G N7 \
......
7 p, c& Z+ V6 d8 O4 W7 O }
2 V8 A( S) C* j& L7 M2 z- j}& U4 S' Z8 l2 U1 w. z- S- i
' ^$ e: D$ W. K% S) L
b.插入位图9 j, w2 ]8 u1 t6 k2 ~8 n* W
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/
. f* b8 v( z$ C7 W5 a; s+ K) Vhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/9 R1 m' k4 k* b) ?
2 X7 f& m- ?' `& b) y2 `
自定义在RichEdit中插入对象的图标
) g8 o1 o0 P( c/ X3 `" Thttp://www.blogcn.com/user3/jiangsheng/blog/1319738.html
) V" @& v3 {$ ?" C$ l' |; W1 \方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control
: B# @1 }7 K" w/ S只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片# W# Z$ m* f, m4 z _- H
) l& g/ k( } `* L/ X使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。
: \$ X( w3 E) |& q8 U" P另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。 9 e0 T8 g7 H+ w% u* u5 U( O
& |% t( B( P& i' W0 x7 h
c.显示GIF动画' [1 _+ g) u6 w" }; r+ o
常用的是通过qq的imageole.dll(也有用Gif89.dll的). ?( t; t* ~1 L: o- Q, U
http://www.xiaozhou.net/cooldog/blogview.asp?logID=82& n9 T% j/ J }7 c2 X6 m
http://www.codeproject.com/richedit/AnimatedEmoticon.asp$ `8 F/ K: E$ U7 `8 E' P* \
* [5 \4 k# `+ x& Z在richedit控件中插入动态GIF (Native C++版)3 ^& S8 M7 ]0 i0 v/ Y) N
http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx
/ ^. @, Z! A: j+ ]8 s! [ e3 _
8 N0 ^/ o- z* p! c% bd.IRichEditOleCallback的使用
! l4 L7 P' _/ d& fhttp://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022: r0 E' ?8 t3 l
3 }; [5 a$ d. O* P类似 MSN 信息发送框的制作(上)
4 J: Z" X3 h5 Chttp://www.vckbase.com/document/viewdoc/?id=1087
" c% o" R ]7 p" U! L内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串
. M7 a' j$ A; }
5 o2 `/ P, W& u7 ~7 S自定义 CRichEditCtrl 控件+ U2 p# y$ X% X2 k
http://www.vckbase.com/document/viewdoc/?id=328( D; g' K3 D/ O% a4 h; O7 C$ i; t
内容包含:鼠标右键消息,消息映射,字体变换
4 ]+ N: D( P2 @0 q( X( n/ [, Y9 e1 y" z) K- p' ^
PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母
$ L% Y6 b! [( f' d2 [- y是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778
' ?' B, s+ c7 i# S----------------------
* |8 Y) z% g* z( |6 o比我想象中还要花时间,所以最后潦草了点,见谅 |
|