|
一.常见问题
* d3 c! }" Y: Z( U$ A& ca.可以编译,不能执行的& n2 V) U' H" U+ T( v
AfxInitRichEdit();
- { d, D% q' s( I0 A
# |8 B7 r) v; zb.升级默认的Riched版本(默认的有一些bug),如9 S6 S6 j o' o. \+ Q) h7 K
可在InitInstance中添加7 ?6 }7 ]" T% k
LoadLibrary("RICHED20.DLL")
8 y. j1 E. J: c/ w% J0 b最后注意 FreeLibrary
2 ]* N8 K% Z; M5 A5 X# v% Y* R5 O4 K" w6 k. d/ o, E4 E" |- c9 |; R' B
如果是CRichEditView基类的可用
4 V* ?7 w: w6 A) FBOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)
+ @, S7 J, W/ |) Y& l, Q; O" ~, X{
" I6 S0 {1 T2 l7 d7 X; I7 x//装入rich edit version 2.0
4 t. I6 ~; P* p5 nif (LoadLibraryA("RICHED20.DLL") == NULL)
; ]! l5 f+ _2 i{
8 t0 P8 I0 q8 Y% RAfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);
, ~' p; [+ F: a7 Z7 e% @: tPostMessage(WM_QUIT,0,0);
, E' e4 E0 c. v$ w/ [0 [9 b/ breturn FALSE;2 X: w9 t+ @7 ~
}) y0 C, h/ v* [+ j- g: j
4 ^: t+ }1 @4 O1 t3 l+ R
m_strClass = RICHEDIT_CLASSA;//for 2.0 class
" @. R4 d; A' x" j/ {$ h0 S; s/ _8 E0 c1 \5 b. a8 _! S9 x3 ]
return CRichEditView::PreCreateWindow(cs);
6 N3 f3 N3 O) C8 m* O! c& T}
+ J1 m9 @6 q9 m( M8 Y, u- k4 {8 v$ T8 V! S
c.最后追加行2 [6 n: k* V! P! V: {
richeditctrl.SetSel(-1, -1);
; N) j4 Z+ E" E4 s$ ~8 gricheditctrl.ReplaceSel( (LPCTSTR)str );
% k( S. \* a- L6 q& A$ ]" W; X$ E! U) w& Q( b7 w
d.字数限制: v* L2 m$ p3 P) _
CRichEditCtrl::LimitText(long nChars)
- O8 t ^: D+ W. ^) c" {# W8 ]
e.换行切换 z1 R/ c* b1 Z' b. a* L) W
CRichEditView的OnInitialUpdate()函数中加入下面两句:
0 k+ N, E. @4 \m_nWordWrap = WrapNone;
+ _1 z1 R2 @9 L' T0 p4 ?7 a% ]WrapChanged();
p% `3 |3 T" v; O9 W% o- R" R7 ZWrapChanged实际上也是调用
" v" R" B# D9 `, A% i0 v# ~6 dctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone( @, {0 [( m8 o( ^
ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow
7 |& e5 a' N+ B, R9 p/ X还有不常用的 m_nWordWrap == WrapToTargetDevice
4 K4 Q9 Y* o" u. S: O4 n" t5 g! i* e" D+ zctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());$ c2 D+ F: N5 U4 u1 c
如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return
: o" R: ~( t& ^% i- F( ?
5 |7 p3 y' n/ M7 df.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴
9 C" R/ ^/ s/ @+ L& L7 ?+ `( @pmyRichEditCtrl->PasteSpecial(CF_TEXT);- ~4 u# Y* K/ t6 w6 S4 n
* z+ q! _: [7 ]& C/ n. r
g.随着输入随着自动滚动条滚动到最后一行
: h3 R4 O( _8 M1 T' Rint nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();& c3 I/ R* J5 ?& h3 T
if (nFirstVisible > 0)2 E5 e6 @+ x, K1 H I
{: |9 A3 t8 n4 j3 V6 V; k1 n% D8 ^
pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);# K0 n5 o, E' g. i; ?0 l! Z4 z. y9 g
}+ F; _( Y ]0 L* z
或
1 Q6 h# H# d& W+ P: Mm_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);9 y) Z6 x! V. J+ M `+ k
3 u8 H" o" C R2 A; C) B/ z5 i. o6 E2 J( W0 \% j( R0 Z1 @
h.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级)
# g! K; g% A6 @+ i7 ?9 XSendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);
( W2 t! S9 R& }7 s: u, N$ UTM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数 * k+ s6 T# P8 P6 _
SendMessage(EM_SETUNDOLIMIT,100,0);
7 J: ?5 z/ R& \6 D/ t3 o
0 H) J% P) ]& }6 V4 [i.响应OnChange
- E! m) b, z- o0 D: ~# i3 p, ^8 vEM_SETEVENTMASK 设置 ENM_CHANGE 3 ^7 D+ {' B5 x+ k( i. O! u! L
long lMask = GetEventMask();
: W) `9 z. k6 N3 j+ D3 y: tlMask |= ENM_CHANGE;
- n" d: F1 B! P" V" ]) |lMask &= ~ENM_PROTECTED;) u- l3 l. \0 O; T
SetEventMask(lMask); f& g4 r$ H+ |
! W# S5 Y$ h7 ]/ u( D# Mj.设置只读+ ]* ^" D4 [8 g! m( h+ T
CRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );
* P: _2 a, [5 c通过设置PROTECTED实现选中的文本只读,参见) S Z7 J6 o( o
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/
0 w# q- f8 e6 y, d+ _6 T" J8 Z5 }3 ]! J8 p0 {
二.函数应用) i! i$ s. K) L! ?4 `0 p( t9 H: a
a.设置字体(主要是通过SetSelectionCharFormat)
* k$ F/ j. k7 |1 G3 TCHARFORMAT cf;
/ \5 S: i H/ n7 Drich.GetSelectionCharFormat(cf);0 J+ j& t" H- C5 ^1 S( P
cf.dwMask|=CFM_BOLD;
3 `+ U) H& [/ t$ n9 u) M" ]cf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;
; L: s- X* P+ Q: H) ^6 X- Bcf.dwMask|=CFM_ITALIC;2 v, |* q8 M/ C9 h
cf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;7 y6 F9 G% c2 z
cf.dwMask|=CFM_UNDERLINE;3 \& E, l" L4 P
cf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;0 s. o( ?8 h. c" n& X& a/ ^( o+ A
cf.dwMask|=CFM_COLOR; P- L( P9 n* [$ R/ A; Z. A
cf.crTextColor = RGB(255,0,0);//设置颜色2 f- J( U8 u, H% I- ]
cf.dwMask|=CFM_SIZE;
3 P# v8 g" j; b: w" u: q. Pcf.yHeight =200;//设置高度$ f1 c! S; \0 t8 A; o" h m# I
cf.dwMask|=CFM_FACE;& X5 ?; @0 |1 }5 K! I, w0 |9 Q
strcpy(cf.szFaceName ,_T("隶书"));//设置字体* ~( S1 Y6 a7 s( W! B
rich.SetSelectionCharFormat(cf);3 Q1 F6 @4 y6 r4 R6 o: z% Z( O
8 j" X) g. l9 v. R2 j3 D# rb.设置字体的行间距5 ]: }& h4 z6 {8 @; ?8 {
要用richedit2.0以上
+ l% v, {* O% f5 h. _- _6 b! N/ P- s试试
I& S/ T% K( {0 H. v( k% U YPARAFORMAT2 pf;
6 H5 f# |/ e) {( c- p: Dpf.cbSize = sizeof(PARAFORMAT2);
- q6 l8 H& C9 F9 F' xpf.dwMask = PFM_NUMBERING | PFM_OFFSET;
5 L' K7 q% J: o" ]: xpf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING
2 J3 k# G; y+ F' z8 r# j. u Ppf.dxOffset = 10;9 }" h3 |7 D) ]) v% }
VERIFY(SetParaFormat(pf));
- e: O6 x0 ~) m8 S& \# m+ Y常用的dwMask有
$ {' O2 B2 {& c( v( y$ I* u/ w9 ^' ^PFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET! @- z, O) Q9 _; o+ H; O
2 使用阿拉伯数字 (1, 2, 3, ...).
9 J* x4 \/ `( P n* D8 P0 s3 使用小写字母 (a, b, c, ...). ' g6 X: x; N- g8 `& S8 J( u
4 使用大写字母 (A, B, C, ...). / Z1 u( z, ~4 _3 J( q) e
5 使用小写罗马数字 (i, ii, iii, ...).
- }+ M) P( W# H# O4 e, S/ h. U, t0 E' T6 使用大写罗马数字 (I, II, III, ...). # l4 z5 H' z, { r9 a- b, `* Q
7 自定义,字符见成员 wNumberingStart. 5 `/ W/ S; R& d3 n1 f6 K: ?6 L
PFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips
" n3 b. A- `9 e! A/ p9 A: g; FPFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进* r) o4 b- Q! O" S: f9 J9 i( p+ Y
PFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距& M! p' |$ `) d9 {9 R
PFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距7 t# M3 i& i3 R( p. T
3 s! |7 F" G8 J1 o- |
c.设置CRichEditCtrl(2.0)背景透明 % K' Q( _, v6 I% j) ^# A1 {
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
9 Q: W- e6 G8 I9 l v9 jstyle &= WS_EX_TRANSPARENT;
- h: `! X- L2 D0 J/ M. k% z8 a::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);( p, [7 J* T0 ]% W8 P2 p& N. F+ f4 m
或 CreateEx,然后把WS_EX_TRANSPARENT样式加上- {/ ~- ^& M' C) ~- o" s! j( g' o
( \. M% V3 m0 B; z
e.得到内容有三种' x, d, E: n0 T, F+ ^& C$ V
1)GetWindowText
1 P7 t- r, S, v2)使用EM_GETTEXTEX. S7 R) R! H, {% v! x' R$ w- z
GETTEXTEX gt;
; q, d E8 f3 z: x8 v& |gt.cb = 200;
8 h6 c; }! {5 [" A7 u" G" ugt.flags = GT_DEFAULT;
9 Y3 q0 @& z! {, @1 t; L8 u7 @gt.codepage = CP_ACP ;
# b8 }8 _4 r$ T) z; J& xgt.lpDefaultChar = NULL; 9 a \3 @5 k9 \3 V) l$ Y& d% D/ i
gt.lpUsedDefChar = NULL;: P9 f' J( U$ D0 D& Z' }) |
SendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);! ]* x0 ]# k* x# q2 N
3)StreamOut(主要用于RTF等格式输出)
9 o# K1 A6 J& n8 w" M# x0 _static DWORD CALLBACK ' ?$ p( n% |' o4 f- T
MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
0 w2 c7 E0 f7 [$ a" V8 r* r{0 d' Y- V' Y6 W
CFile* pFile = (CFile*) dwCookie;# s. _% L/ I$ Z
6 E2 }6 d" j! T2 j" q% x& m6 Y6 O
pFile->Write(pbBuff, cb);
) o8 y, h4 ?5 i9 M' n7 z" w, j$ i *pcb = cb;1 f, e1 B0 o3 s+ y/ K. }* h
" D) w- @5 P- j% c& x5 A
return 0;
2 O8 F# }, T, I, N' o) m}' c+ S4 I5 b/ s
! l( F8 m+ y! {. ?1 s
# V4 ~) i1 D e( E3 J
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);
W1 l. l" o+ Z/ T1 ]% X4 _( X EDITSTREAM es; B4 c5 t* j4 N4 n* }& o$ N
es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用1 f& n& D1 Y1 S" E& M7 D
es.pfnCallback = MyStreamOutCallback;
) _% j* I; b6 S8 s! U* d pmyRichEditCtrl->StreamOut(SF_RTF, es);
) |7 k4 C W9 [' z; s8 q4 |读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn
9 z8 w( X/ {6 p, ]
: w" B% [* Y2 V1 O! U: v, \ f% Jf.查找字符串
' J: m, ?+ b3 E6 m+ _& tFINDTEXTEX ft;# v3 Q. | P$ ]
ft.chrg.cpMin = 0;
; s9 K4 p1 D1 h n& Eft.chrg.cpMax = -1;
$ R2 i8 r2 Z0 m# e1 T6 xft.lpstrText = "|";! O0 s- F6 J" o( O6 L
long lPos = FindText(0, &ft);% K( A+ J2 A# d. l. `6 N" r
: u- a& z8 i O
如果要继续查找,修改cpMin,如# A/ u5 R" O1 p+ y/ m! \
int nCount = 0;8 j1 @, _- i: F0 Y" ^
do# t# }. {: ]; f3 D$ y# f7 Q: b
{+ D9 H7 f( N- }
long lPos = GetRichEditCtrl().FindText(0, &ft);
3 X0 V7 s3 R: f" m5 P if( -1 == lPos) break;1 b% Z5 n$ y; Q; O* o" c8 a9 B" n, g
ft.chrg.cpMin = lPos + strlen(ft.lpstrText);1 O$ j+ x4 T8 [* ^
++nCount;: B- p$ I. T* Y2 H1 j8 L2 y
}while(TRUE);
, o6 r3 L" S* T/ f! w8 \9 Z* X: S) q% d% B/ W4 k( F! \. c
g.以Html格式保存6 x8 a: _5 Z6 }' q; K; E5 q
目前做法可先转为RTF格式,再通过RTF-to-HTML Converter
$ T5 V& Q l& ohttp://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/& Q9 q" _/ S+ k; L
; t* ?0 B O$ P. l" M) q/ Dh.重载OnProtected函数得到对应的消息,如粘贴等 z5 ~" B6 V; J' a0 b8 E
void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
- f8 g4 p8 f ^{% s4 }: A" n5 k8 I4 d& _
ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
: O A, t+ y, Q, e+ N
* A* Z9 o: s5 k: ` switch (pEP->msg) {
! N/ }' Z5 D8 i U$ ?0 x case WM_KEYDOWN://按键,判断pEP->wParam1 x* c. j3 I+ N' i
case WM_PASTE://粘贴
- a: M% w, ~; z case WM_CUT://剪切: W6 W1 Q) F7 E( P2 g
case EM_SETCHARFORMAT:! V/ |( H9 M2 O' y
default:3 K- I" n$ S; S+ O. `8 A& Q% x6 k
break;) h. T( l6 l6 H( a, G2 \
};
- m& {4 {- `, t' h5 o7 H
! |1 }) E2 J% e. i2 y3 | *pResult = FALSE;# E2 u9 M6 E ?' ] M! D
}
, T# D( Q' i; V+ h8 K6 {# W9 O' Z; b4 y9 E) x
三.聊天常用 , _" s9 B& V# |# A: N, f
a.LINK 链接功能) H/ T8 l% G" l6 U' c8 p' r. l# y4 _
1. LoadLibrary(_T("Riched20.dll"));
/ `, ~" G1 u. h! H+ j0 S2. 创建RichEdit2.0控件
! A. q, [4 @. T1 H0 ?) t2 h0 | CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP
3 [$ c/ }! q5 Y# r4 D9 h( m|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,' D1 C( `1 N% x0 f3 u: Q
rect.left, rect.top, cx, cy,
& n M0 f1 E: M5 X pParentWnd->m_hWnd, (HMENU)nID, NULL);
9 n/ d/ }+ ~& T5 T3. 设定选中的文字为链接显示4 `( t( U$ S1 ~0 }% o, i- s
CHARFORMAT2 cf2;
) Q0 O' e/ u; U% ^ZeroMemory(&cf2, sizeof(CHARFORMAT2));//
8 Q% p% u8 H/ I& z( w3 v. }cf2.cbSize = sizeof(CHARFORMAT2);0 V; p0 _% H" l5 I5 F3 O
cf2.dwMask = CFM_LINK;
4 f P' V5 d `8 l' fcf2.dwEffects |= CFE_LINK;! ]! x W9 l9 r- {
m_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
5 ^$ B. V2 w5 O4 V4.支持链接的点击响应
% `9 q$ _( u, [5 Lm_cRichEdit.SetEventMask(ENM_LINK);
. O( K3 {. d$ o! @9 x# ?5 U$ E5.响应链接的点击EN_LINK
. p. ^- t: x1 c, _6 H
: y$ }+ A1 N& y* D0 n. R4 p0 }BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)% V4 j* w% l7 A+ H0 p% @8 @
ON_NOTIFY_REFLECT(EN_LINK,OnURL)) t f+ [9 ?" e- Z( j% |7 R
END_MESSAGE_MAP()0 F! ?1 O/ x6 P
......- A" x6 S/ G& Z' E0 P
+ R4 ^0 g* w9 M9 pvoid CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)5 z2 X1 y. ^$ I+ V
{1 a6 `/ o5 K$ T) H6 h w; b
TCHAR LinkChar[512];
`" z8 z% f$ _: ^5 FENLINK *pLink = (ENLINK *)pNmhdr;
g! H' g- @. S% Q% @1 s, Kif (pLink->msg == WM_LBUTTONUP)$ r0 W4 h4 V0 r; v* |
{
4 w) @) K: s6 e2 b8 qSetSel(penLink->chrg);//这是链接的文字范围
* B. A$ y$ d% _4 S% o7 X+ Xlong Res = GetSelText((char *)LinkChar);//这是链接文字; R3 `- y9 e4 _; |$ y
//后面是你的处理过程
- L, w" j) h X1 K) p ......
8 \( u7 e, n" g" J/ H$ A7 J }
, W" r% |4 w- ~ c2 ^}# w% a' _/ u& s1 C! C B- m$ X
' j: P$ \" h/ a. D8 O/ G
b.插入位图
5 q& `- a. _. y, Lhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/9 x$ |! ~2 [$ }/ U9 [
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
8 |4 ^* P' I$ p2 D( x# ?8 J9 i7 Z( U6 q! R0 Z7 t2 `
自定义在RichEdit中插入对象的图标
7 n( H9 B9 s" P% N4 Fhttp://www.blogcn.com/user3/jiangsheng/blog/1319738.html: L! w( F7 ~% h( r& A
方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control$ P, T3 c* b' A' P3 k
只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片
& c: Y1 L4 X* ?$ k# G" l: d1 B: _: \) k; r/ d1 g0 y" y
使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。
, X5 M& D" `* B0 S6 `另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。
+ `) i) N9 W6 c5 U$ E, m* Q6 _ _" K2 A+ k
c.显示GIF动画7 \$ V( O0 V/ u, e% t* \
常用的是通过qq的imageole.dll(也有用Gif89.dll的) B6 B% g2 _6 \( g/ I
http://www.xiaozhou.net/cooldog/blogview.asp?logID=821 t3 `: d: z8 z- n3 P3 z( \
http://www.codeproject.com/richedit/AnimatedEmoticon.asp0 ?# l% C' j, }( d
) F, k: s/ K) E7 M
在richedit控件中插入动态GIF (Native C++版)( a; J- Q8 i5 _) o! D& ?
http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx
5 Y% Z; t! {( S0 i- T' G2 S) w$ m8 F
d.IRichEditOleCallback的使用6 e2 d* k0 G6 z& B3 O, [5 g0 B
http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022
( f4 W; j% n& B5 t6 d$ w% p) D; B5 F5 K* f/ ?+ ^+ P
类似 MSN 信息发送框的制作(上)
2 K! @# p4 v' ahttp://www.vckbase.com/document/viewdoc/?id=1087
" ?" N# g7 A: ~; [5 T内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串
( y. d* A; D; o$ U E5 M1 b u3 u2 }( R
自定义 CRichEditCtrl 控件! v2 q1 _- v7 B! r$ Q) j1 v
http://www.vckbase.com/document/viewdoc/?id=328! U- q7 n4 ~' N5 z# D' @! W$ |; `6 _
内容包含:鼠标右键消息,消息映射,字体变换/ {1 S# c d) }' R1 Y
$ K. z0 U, D$ z( S. m
PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母
5 D1 P9 W, q6 t) j! J5 @ R3 S/ l是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778 + y; H& X( W6 n) M) O* o: {7 M/ P
----------------------
4 _: K W5 i& U比我想象中还要花时间,所以最后潦草了点,见谅 |
|