|
|
一.常见问题5 v. R0 t- u; }. ^' W
a.可以编译,不能执行的
1 m' _& i8 }( g1 D d: ^ ]5 pAfxInitRichEdit();2 F7 q/ w1 R1 h8 ?" S
" P. @5 @2 W! I2 _6 l, I
b.升级默认的Riched版本(默认的有一些bug),如* M3 I) B0 n7 l1 A( a0 ~
可在InitInstance中添加
3 W9 v4 [$ z9 V/ O5 v5 jLoadLibrary("RICHED20.DLL") 5 j# v1 m$ I. c: E
最后注意 FreeLibrary* n `" K! r6 x
L/ t) W+ f4 f$ p( ?
如果是CRichEditView基类的可用
2 Y; K$ c, I( TBOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)
7 S( S! _) j% J+ J* h{" C6 l; C& ]" z, b+ e1 C7 N
//装入rich edit version 2.0( | y% \+ S, P1 C( x
if (LoadLibraryA("RICHED20.DLL") == NULL)) M2 m3 w( D; ]4 A8 F2 ^& v8 H
{
( ?; e% L+ ?- K7 m7 M( t( KAfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);! L Z$ F+ P- J. @( t
PostMessage(WM_QUIT,0,0);9 B$ o v! ~7 |5 k
return FALSE;
. g7 g9 ~7 }; z}. k% D1 S1 A: Z5 h% v
, w6 S( j1 E9 A7 t- Gm_strClass = RICHEDIT_CLASSA;//for 2.0 class. O8 m- ^! L6 ~
3 {: N2 A1 L# Z6 B' H5 V& {
return CRichEditView::PreCreateWindow(cs);6 a& |) P7 C9 a
}7 C$ z; t, a- B% F' Y8 l+ K( j
* ^- D5 l) I9 h9 c5 H) t) Cc.最后追加行
5 {/ y9 t9 I2 Z$ q; Fricheditctrl.SetSel(-1, -1);
$ n4 b- d% ^& }6 d: d; Aricheditctrl.ReplaceSel( (LPCTSTR)str );
( u0 ^4 ?2 Z6 p% \% I2 P; Z) ~- Z! Y- ]/ T" P4 r
d.字数限制- W3 y& F( t) Q1 i
CRichEditCtrl::LimitText(long nChars)
$ Q2 q. T3 U, E! q; h7 f9 c- o, d7 I( A7 v( ~) |5 I
e.换行切换
; Z+ a, r8 F8 VCRichEditView的OnInitialUpdate()函数中加入下面两句:* f+ X1 ^) R2 C4 V( D* Q
m_nWordWrap = WrapNone;
8 }% U; J. M4 d& i. N# kWrapChanged();
4 E9 v* j% I* ]' W4 pWrapChanged实际上也是调用
$ a/ l2 {1 j$ A- }+ R. qctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone
+ Z1 `6 a: P' o4 Mctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow* {5 \4 x! V# j! O" b
还有不常用的 m_nWordWrap == WrapToTargetDevice
$ r! k, N5 I# O1 ]5 A$ `$ octrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
; R; @" ~- p: s0 V. j如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return
. a/ b+ r1 j+ v# m: r( n5 T6 C |4 `0 J: i# x) y$ C
f.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴7 h5 o Z5 \) A, E
pmyRichEditCtrl->PasteSpecial(CF_TEXT);
6 H, L, {' V& }/ s8 [7 U) [7 n# V2 H; k M1 y7 J6 ~; D
g.随着输入随着自动滚动条滚动到最后一行6 |# y! F/ a1 {( l4 `! Z
int nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();: c8 \5 ]" j, x5 `/ T
if (nFirstVisible > 0): t! v+ k1 d% H
{
! {8 M. c' ^: p# T6 O pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);" n& Z7 \/ P; z
}
# R6 R) W# _: Y, @/ z- z: W0 P或
1 Y5 v& h, G- X( K: S* mm_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);
x }5 M7 r1 G; q- _% u& x+ y
4 ^& `7 X' N/ m5 q3 [" q& X) N
& f1 n W2 d* v+ {7 mh.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级)% {7 @, G. b( A2 V; S3 \3 i5 @; P
SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);2 |6 U) ^' }, Q
TM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数
& R) t$ N. }7 l+ F! z6 BSendMessage(EM_SETUNDOLIMIT,100,0);
8 I4 @. y; t9 W
; Z. l0 U; e7 n" A# U8 \6 {4 ni.响应OnChange$ Q6 ` s, R# R6 W& t9 k# X7 a4 Z2 h
EM_SETEVENTMASK 设置 ENM_CHANGE " h8 X) d# T7 z# E& q
long lMask = GetEventMask();/ S+ I- e' X' }' D" h
lMask |= ENM_CHANGE;' H( t X3 k% R- Q" G/ Z. u) y) ~
lMask &= ~ENM_PROTECTED;
" O" S# @) U4 l4 i4 }SetEventMask(lMask);
& g. K8 k- m, O' N# |# x. E- X* W2 V
j.设置只读
) r8 l. M# a$ ]6 x( wCRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );
& X" K9 ~( ~; r7 Q9 c% N, h t x通过设置PROTECTED实现选中的文本只读,参见
7 X1 F* u2 P( z, ?- q4 }http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/
* q3 O @' O; p% n4 P0 R% o7 F* T! k7 L
二.函数应用: Z. H' r) h- x8 W& w' R2 e% k
a.设置字体(主要是通过SetSelectionCharFormat)& t3 Q0 T6 S, w- w# o& u* P
CHARFORMAT cf;
' ?- ~: S7 v7 e# t+ _* mrich.GetSelectionCharFormat(cf);% \, d* d8 j) |1 f4 c
cf.dwMask|=CFM_BOLD;
( A) x }7 D2 t( X+ Ycf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;% ~) t5 y/ l# T& E; P
cf.dwMask|=CFM_ITALIC;
* y% M9 N- S$ b5 _9 ccf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;% A% G/ }8 A- p8 Y, @9 s
cf.dwMask|=CFM_UNDERLINE;
. U' N0 Z: V6 W7 Z7 fcf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;
/ o$ Q; W+ t' ^' ]( z( D0 qcf.dwMask|=CFM_COLOR;5 H6 Y+ [1 _/ m% v6 t
cf.crTextColor = RGB(255,0,0);//设置颜色; ?1 [/ b6 _3 y/ f% A' Z6 b
cf.dwMask|=CFM_SIZE;
1 e0 m) U' |. g$ m( acf.yHeight =200;//设置高度
! O1 t2 v- i2 w9 {+ K. ]cf.dwMask|=CFM_FACE;5 s) v, ^7 z& j' s1 x
strcpy(cf.szFaceName ,_T("隶书"));//设置字体* z( j0 L; {" X$ f4 E; @% g
rich.SetSelectionCharFormat(cf);
. r: _! ]) u& T! |' d3 O$ k+ _$ o5 O' }
b.设置字体的行间距
: ]. O& a; I' g' a. u要用richedit2.0以上$ d5 e; l) e. Y! A* @: E8 D! m$ O( f5 d
试试
! X) w8 S1 B: c, E" ~9 mPARAFORMAT2 pf;
* V$ {" {+ t: P [9 b, Mpf.cbSize = sizeof(PARAFORMAT2);
+ V( _3 v/ v" T* epf.dwMask = PFM_NUMBERING | PFM_OFFSET;$ S! @; p- m# v" m' n6 Q4 X4 p
pf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING + v5 q/ D; h* B" L2 s' K4 d* k
pf.dxOffset = 10;
9 j9 t2 l' n8 U( j" ?VERIFY(SetParaFormat(pf)); / i$ Z# l% o+ v8 q$ B. p
常用的dwMask有$ Y. m1 P/ h* N9 \1 @
PFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET
& r. F- W. S/ @5 [/ J$ x0 w+ V# D2 使用阿拉伯数字 (1, 2, 3, ...).
% _6 [# E5 I C* E2 ]$ G3 使用小写字母 (a, b, c, ...).
' Y& T' y; E, z4 使用大写字母 (A, B, C, ...). 6 ^. w- n9 V5 v% |
5 使用小写罗马数字 (i, ii, iii, ...). ' [- {+ g# J: n z; z9 S& A
6 使用大写罗马数字 (I, II, III, ...). 6 s6 l, W1 C! P# m. u
7 自定义,字符见成员 wNumberingStart.
# O* j+ f9 n5 ?4 W/ P. H# |PFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips
+ B( }; n/ F# f* g/ N: yPFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进
- |( [# d0 v7 G( ~# k7 k$ A7 SPFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距& P) T0 o) r* M$ Z9 t) i; o6 A
PFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距4 Y$ Q0 |5 ?4 j" Z( c6 @: M
; z) I) m6 E/ d6 @c.设置CRichEditCtrl(2.0)背景透明 3 `& o. p' B0 N
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);: o3 H( T" s& \. d6 o2 {
style &= WS_EX_TRANSPARENT;
' w' M- V6 Z/ {::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);
8 y8 x& Z7 J: x& ~7 S! S: f2 U1 t或 CreateEx,然后把WS_EX_TRANSPARENT样式加上7 c# M6 F$ r8 H3 W/ K! O) A* Y
7 J4 `8 i0 @# J, q3 D- v2 D
e.得到内容有三种
: J" W% m6 M! K- ^- y1)GetWindowText1 S2 y! V) `9 |7 q( u4 A4 a: F0 G* W
2)使用EM_GETTEXTEX8 J7 D- u* p, J& H
GETTEXTEX gt;* P3 S0 ^ b8 \( N: r
gt.cb = 200;
- r4 @; H5 W# {# y- Agt.flags = GT_DEFAULT;
. S6 @, c1 K! _, fgt.codepage = CP_ACP ;5 \) q; w3 h% m [( I
gt.lpDefaultChar = NULL;
1 ]! M& {& @2 _" [4 ~2 |7 Sgt.lpUsedDefChar = NULL;& \/ d" L6 l! n+ V1 {
SendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);$ U% ]4 v& y8 j7 L2 ^
3)StreamOut(主要用于RTF等格式输出)
+ q( M5 C% ~4 j$ n! p( rstatic DWORD CALLBACK # r1 M2 T* f9 B: W/ E' Y
MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb), A. y) t% O% u, p z
{
6 {3 A8 D$ w' F# k. o; W CFile* pFile = (CFile*) dwCookie; Q7 M+ \/ h3 \
4 S+ d. Y7 W7 J7 b) [
pFile->Write(pbBuff, cb);* ]: P) x" N; v
*pcb = cb;
" S# ~4 d7 @6 _* t5 X
. E2 z! d- R# w; t; Z; I* U return 0;
4 v1 X0 D8 o' h n: R3 X}
5 A8 t, R' z/ O7 A7 U1 B0 e! Z) w6 _: l+ u1 X% h! {4 z: n
5 ?4 M% J: j" E7 J; T4 a
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);
, u$ k; {# q5 p4 E9 g& C, L EDITSTREAM es;
) m% R _( U; V: J2 x& f- Y es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用
2 w5 n s6 D X4 @0 `8 x/ R es.pfnCallback = MyStreamOutCallback;
( _: z% L( j/ C4 J; L, p pmyRichEditCtrl->StreamOut(SF_RTF, es);1 d& h1 S9 D+ u: _6 _
读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn* o, R- O8 q& a# v, ^, N+ z' r
+ K6 p U: B, w4 N4 T/ ^3 ?4 Of.查找字符串( }$ W* h9 n9 P) X, ~2 [
FINDTEXTEX ft;
! t; T. F7 F$ Uft.chrg.cpMin = 0;8 D' c) I( R5 \6 k! `
ft.chrg.cpMax = -1;1 h; t' ~1 e" ^( _2 F" [4 O! l
ft.lpstrText = "|";+ g. u7 O' z% Y
long lPos = FindText(0, &ft);* v) D4 h5 {/ _2 J
8 u9 L6 n: d0 i/ C; W' e如果要继续查找,修改cpMin,如
5 O8 H8 f/ |9 y6 K& oint nCount = 0;
. m d2 R0 Y9 Z5 v# j8 _# J( Odo
: D" z! [" i- F' j. s. L( C{
1 Y$ J8 z$ |* j B. {9 i7 K long lPos = GetRichEditCtrl().FindText(0, &ft);
H k& z9 o' {3 O( @ if( -1 == lPos) break;" u4 D: Q2 z: `! m
ft.chrg.cpMin = lPos + strlen(ft.lpstrText);
~; E4 L# }9 {. e ++nCount;
2 M. L' ^ K4 C- x}while(TRUE);
& M' I( G! F- ~5 s. n
- E* ^* K5 M( g% i1 ]' Qg.以Html格式保存
8 ~5 `; j+ H& `. ?. d; T4 d目前做法可先转为RTF格式,再通过RTF-to-HTML Converter
( @6 ]# f- a6 {' E( Hhttp://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/
8 y7 ~ ]4 E# ^' `5 J9 a o: }& e; X
h.重载OnProtected函数得到对应的消息,如粘贴等' P, }; H, _! I) m6 h( b
void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
: ?: D/ ^0 b2 o8 m" g* S) N: B{
7 W. m3 _4 D) u+ B1 e& h ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
" J0 ]( ]. r( A7 A8 _. Z& e! u; u2 G8 E' R0 U% K
switch (pEP->msg) {
2 ]( H# Y; Z1 K& ]! L$ c* U case WM_KEYDOWN://按键,判断pEP->wParam }+ ]4 d/ U0 G% j. Y$ |7 l
case WM_PASTE://粘贴
; D9 K* S) d) L" t5 V3 s case WM_CUT://剪切0 A( V2 \" e/ M( c# f
case EM_SETCHARFORMAT:, J& c( T: F; t: X
default:
# ]% D% i% p+ t# z1 V7 I break;
7 j% ?+ R. s* S! M% \ };
6 D2 \* [) n1 k0 d% o
+ M' Y4 i0 w. d+ f" l+ P *pResult = FALSE;4 c, R0 t! e9 ?! v }, h7 j8 E
}
9 |' v7 w0 R1 ~+ \; ^) l. J" ?. i! s6 d6 }, o5 Z4 i+ ~
三.聊天常用
# s" t& g; s. j) `4 z" }; Ba.LINK 链接功能
: j5 e7 @0 M# q/ B' s1. LoadLibrary(_T("Riched20.dll"));* R% |" M+ l h) J Q
2. 创建RichEdit2.0控件; x4 P; F4 z/ x5 @ Z% W/ E
CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP
/ G7 }" z+ J) @|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,
/ @2 V+ u9 R4 G" B' E' x; | rect.left, rect.top, cx, cy,
' M8 N" D0 b% a' Z& H# o0 L pParentWnd->m_hWnd, (HMENU)nID, NULL);8 A8 W" r+ r3 M p
3. 设定选中的文字为链接显示
, ^( e: `/ `9 J0 ~CHARFORMAT2 cf2;
6 L3 I3 f! @$ m& l0 [, n% {: i2 vZeroMemory(&cf2, sizeof(CHARFORMAT2));//% Y' y- o$ L1 d5 [$ D5 {
cf2.cbSize = sizeof(CHARFORMAT2);
+ Q8 \/ @' Z8 Q9 m) M# \, p6 B6 qcf2.dwMask = CFM_LINK;
: G/ V% B U" ~: s3 k; _3 acf2.dwEffects |= CFE_LINK;2 _0 T. f v. r% t8 C
m_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
h* q. ^1 r4 A) d0 t) B7 L4.支持链接的点击响应) b' a4 ?& p6 A% ]# X% X; v, \; E
m_cRichEdit.SetEventMask(ENM_LINK);! j) ~) R; V, [ ~: `
5.响应链接的点击EN_LINK+ D& \7 M$ o% a
! L, |, e/ t6 N5 ~' @/ f" N1 |
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)* w* t! e) L/ h: s3 \
ON_NOTIFY_REFLECT(EN_LINK,OnURL)
( |7 x3 N' D+ @- x) [END_MESSAGE_MAP()& [& {7 d7 F" V
......; z6 q2 h8 \& K8 ^! n; E( v: B
n9 W* a5 i1 m/ a _8 X0 C8 Avoid CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
9 T& t4 T, ]3 U. |{# _7 s3 d" o, X/ _, ]6 K
TCHAR LinkChar[512];- V7 [7 K" @" W6 T% R1 _
ENLINK *pLink = (ENLINK *)pNmhdr;1 }: r" V1 A7 z
if (pLink->msg == WM_LBUTTONUP)- H: T; K' a) |4 P( U
{
1 r; v4 l, f: i" r3 s8 C+ K# ZSetSel(penLink->chrg);//这是链接的文字范围9 o8 _6 |5 i4 {/ D F
long Res = GetSelText((char *)LinkChar);//这是链接文字
- C7 J- G/ e1 D0 N; c; G3 s //后面是你的处理过程$ M1 U8 F g; |8 X2 D
......
, u3 X$ O6 Z. B }
* Y( n6 u. w! |* v}
9 C- a3 B2 q: s" B; F6 C! \* t
6 T9 l) a8 U% Q$ I" B8 N8 z- Pb.插入位图
. a( Y) [- v2 s a( G! bhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/6 N& _$ N8 M |% K
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/: X, {3 E0 f& q$ z% [
# T6 L* z7 v' n
自定义在RichEdit中插入对象的图标4 I1 d( ^1 r2 Y6 P
http://www.blogcn.com/user3/jiangsheng/blog/1319738.html
8 a' S& }$ k+ V方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control5 g0 A+ N+ g' Z) `
只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片
' g5 I6 K# f& S0 j: Z2 w& P0 d2 G# \7 q! v6 y7 u
使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。
" @- v. ^* g2 \. Y( i( M另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。
% `( x) n: P. v: n+ H) |) K) n3 B o+ X
c.显示GIF动画6 u P' r7 i+ y& [0 \! p& D# q9 W+ j l& Z
常用的是通过qq的imageole.dll(也有用Gif89.dll的)% p+ d+ @1 R9 d. S2 F0 i% j5 Z
http://www.xiaozhou.net/cooldog/blogview.asp?logID=82 X5 q0 [ j( p; D
http://www.codeproject.com/richedit/AnimatedEmoticon.asp
# D: k }$ M$ p$ e5 ], J) S
! T* u5 N3 @* v在richedit控件中插入动态GIF (Native C++版)
& K3 o/ e. K+ shttp://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx4 i& _+ u6 a' |+ x0 e. y
( U$ q- f: Y) g6 o9 y/ u6 |
d.IRichEditOleCallback的使用
1 W+ r, {% y' Ahttp://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022
" I' J/ _. U* Y, ?& N
2 u, E7 e! I u$ q2 h$ ?. X% V类似 MSN 信息发送框的制作(上)
( b$ y/ {& F! i2 _/ N7 O3 O! jhttp://www.vckbase.com/document/viewdoc/?id=1087& L# Z" i) R8 P2 E. S j
内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串
& \8 P- v3 ?/ L6 W6 B- P
. m5 @) \& u* f4 M6 E9 y" X' W# w自定义 CRichEditCtrl 控件
/ C5 I. F8 H& ]. @* Nhttp://www.vckbase.com/document/viewdoc/?id=328
5 P1 u% D0 m- {2 g内容包含:鼠标右键消息,消息映射,字体变换2 e- `3 _' w& ]& C# C7 d& ?
9 n9 r; z* R# j% q! c" ~( Q
PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母
! r' {8 c: @' H: D% H! L是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778 : A) T' }2 h! |3 O
----------------------
/ w! b; ]# @" w比我想象中还要花时间,所以最后潦草了点,见谅 |
|