|
|
一.常见问题
d/ D: N9 D$ Q: M) b za.可以编译,不能执行的
2 }, s" `5 n6 oAfxInitRichEdit();
9 J# ]! f8 X& p8 D% E. [) x+ K0 L6 \
b.升级默认的Riched版本(默认的有一些bug),如. i- v, U- m8 f3 j) _& X
可在InitInstance中添加) T0 O; _$ m( f# |1 a4 \
LoadLibrary("RICHED20.DLL")
& y# ~" `5 v& I9 h9 L( q) P& k最后注意 FreeLibrary8 X8 P0 x7 a. ?" u4 [! l$ \
. w! T" }5 U) o3 H* t% V- A
如果是CRichEditView基类的可用. H) l4 _9 s7 C( u/ G
BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)
, q" x) j! `5 b) W+ c) y{
. c8 X! Y. k: |' D" g# q7 T//装入rich edit version 2.0) b. q8 |2 P% n: V& t( P a
if (LoadLibraryA("RICHED20.DLL") == NULL)
3 w& G0 x' Z9 M. p" R4 h{3 o5 g# D, D" Q
AfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);
0 v+ e. e' G' a0 E8 f8 f# k7 TPostMessage(WM_QUIT,0,0);
2 ~& ^5 d7 n. ~" \3 d/ a% I: h2 m* \return FALSE;
$ R O1 }4 Q2 ]# c/ s" O}
4 c- n$ n9 b8 {% ]4 e; V( f$ o9 j/ K0 r% D( T" w7 i
m_strClass = RICHEDIT_CLASSA;//for 2.0 class
: R$ s7 t% D3 @3 b0 @+ s
2 j5 z% t0 r( w3 |. M Zreturn CRichEditView::PreCreateWindow(cs);
# c2 @. {& K. ~: U2 S2 W}
4 l- L+ k! k, x4 j b* F' K' Y" X9 k* ?
c.最后追加行
! H R: [0 g X) [( G; |7 s/ ^richeditctrl.SetSel(-1, -1);
* t* m! O& g6 j9 y8 [! \richeditctrl.ReplaceSel( (LPCTSTR)str );
, f6 o, Q+ A1 ]
# u+ y- M% J; F4 Y6 t+ Sd.字数限制5 c; }) l1 t! v N
CRichEditCtrl::LimitText(long nChars)
; o5 ]( f. R. @' l$ G# Q
" M' B$ h6 Y/ d: I/ t1 ]# Ue.换行切换
& W+ Q, P. U: Z& U* \7 ]& ICRichEditView的OnInitialUpdate()函数中加入下面两句:
9 A# d1 m E2 V% u! Xm_nWordWrap = WrapNone;5 N" j% O1 O; ^/ k; }9 P. Y
WrapChanged(); $ j6 Z, y& d' h$ v9 Z1 E+ K
WrapChanged实际上也是调用2 }$ S! Z& S K0 `7 ]! B& d! H; s
ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone6 r" Y$ t5 R8 D5 ]2 G3 S# _" y
ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow
) P+ d9 Z8 k0 o还有不常用的 m_nWordWrap == WrapToTargetDevice
- W' a2 u, N$ L0 k3 I0 |! n$ O5 w* Actrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
# \7 y9 @7 j' s" r8 m$ E, P如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return
) G( v5 c$ u5 d( ], K
' e1 \3 s; Y0 v# g+ f' s" }$ af.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴$ ~4 u. O% F6 S( Q6 r
pmyRichEditCtrl->PasteSpecial(CF_TEXT);- K; r9 b7 V# j9 y2 l. \
' u7 F R; k9 r2 Dg.随着输入随着自动滚动条滚动到最后一行7 q( I4 l6 A4 u; g
int nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();
% H: X: U( e# s- i2 Hif (nFirstVisible > 0)0 s' {* X2 {# R: a7 i7 G0 |
{
* M+ u: w; q, u" W pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);
1 m9 {. Y% C7 ]7 F$ P" h1 T}' N& f. r6 m8 s9 P* G$ W$ _
或: r1 o3 c/ p* z: G4 z
m_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);! [, b5 d8 U) w6 k0 j9 f. g2 v! ~* q
0 {* {; j% H' R) j" ]
5 E* v. M5 ]; S' _h.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级)2 N- J& ?9 i9 v/ U: h, ~
SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);
& r: R: @1 ?' ]; @4 I$ }7 eTM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数
8 W7 \, t2 w9 o8 R! }4 ^2 ASendMessage(EM_SETUNDOLIMIT,100,0);
1 w* `! e: b5 H
- z+ M5 e |" n4 c6 g8 `/ Ki.响应OnChange( A5 z4 g/ b2 J: o7 |- M! p
EM_SETEVENTMASK 设置 ENM_CHANGE % `# W3 r2 T q W
long lMask = GetEventMask();
& X6 l0 d/ b; ylMask |= ENM_CHANGE;
+ T& e9 J6 i# T/ _. YlMask &= ~ENM_PROTECTED;4 h6 O$ {/ a+ {9 M
SetEventMask(lMask);
6 @+ s; o7 D) w3 F1 p9 r, |; I0 p) v& F
$ G1 M/ a& L4 T& sj.设置只读6 j2 H3 M+ d0 `+ P& R' v) e- k& K
CRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );# G$ p0 m, p; K1 q% {
通过设置PROTECTED实现选中的文本只读,参见
5 a) G5 F4 W P* K% H1 \http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/
8 t7 H* t$ E2 @( o9 x& ]' Q+ a. y$ b: r
二.函数应用
# }; `5 ?) g7 }8 ^3 U) ` p1 x0 Ma.设置字体(主要是通过SetSelectionCharFormat)) A/ {6 o6 j( I! C5 K7 _) W
CHARFORMAT cf;
+ g* G% q! y5 x rrich.GetSelectionCharFormat(cf);# }/ U3 S \+ P2 f
cf.dwMask|=CFM_BOLD;
" C6 T8 c9 k, D# S; |cf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;) z5 ~* o4 {0 j4 f- p0 N
cf.dwMask|=CFM_ITALIC;; j9 Y5 f: e3 t. |1 \* Y
cf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;. b/ R3 v) C/ X* Q1 h
cf.dwMask|=CFM_UNDERLINE;
: R% U' H$ ~8 C+ B7 J- Fcf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;3 T. a. Y# t' Q/ e+ c/ b2 G" z
cf.dwMask|=CFM_COLOR;
( G4 Q b" h2 Z! Y$ _; u6 M: \- d; ]$ Ccf.crTextColor = RGB(255,0,0);//设置颜色
! o( ^3 j0 G# j' tcf.dwMask|=CFM_SIZE;
, b+ N. |3 @/ U; u5 ?$ U- acf.yHeight =200;//设置高度 I, ]" M* _: E2 _ S* }
cf.dwMask|=CFM_FACE;
" w6 N+ G0 v2 z% u d/ W) g4 ystrcpy(cf.szFaceName ,_T("隶书"));//设置字体
5 m, G9 B6 g3 e) T. lrich.SetSelectionCharFormat(cf);4 I% T; l% O- P5 B# p
; z6 H" @8 ^# V% t2 tb.设置字体的行间距
4 [4 h0 w1 i' p* Q# d要用richedit2.0以上
* \( S! q# x0 ~! a试试
f7 h$ p p8 ]( }5 o; a3 NPARAFORMAT2 pf;
5 I" V# }3 ?: s% Q* e+ rpf.cbSize = sizeof(PARAFORMAT2); ] J+ f3 `( w
pf.dwMask = PFM_NUMBERING | PFM_OFFSET;1 b8 Y5 b5 F' P( ~5 \4 k. [
pf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING
; i* r' e1 Y; C) J6 }pf.dxOffset = 10;
" I. h# r* M. x3 i _3 WVERIFY(SetParaFormat(pf));
/ r5 V- d5 I" N% h常用的dwMask有
6 I, @7 a5 Y# ^PFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET, |) l1 p( [, Q% p, }! ~& {
2 使用阿拉伯数字 (1, 2, 3, ...). ; u3 t5 N* Y. _8 i
3 使用小写字母 (a, b, c, ...).
: T$ w/ q+ `7 Q2 x7 V6 m n! T3 R4 使用大写字母 (A, B, C, ...).
# }5 r+ K; q" y6 p5 使用小写罗马数字 (i, ii, iii, ...). % t5 Y' c; e% K$ |% ~# q$ V
6 使用大写罗马数字 (I, II, III, ...). ( R& ]% A/ e' @& l6 `
7 自定义,字符见成员 wNumberingStart. ( B$ u( |, X5 `6 \5 F$ V
PFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips
. Y2 N: s- G, \6 u( f& B FPFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进
- ? ^5 d+ c" QPFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距( Y+ ~! }/ g( R/ Q3 U8 x4 W$ h
PFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距
/ t* `5 {0 U4 D' y
( G. c: s( A& u9 `c.设置CRichEditCtrl(2.0)背景透明
8 u5 _$ `$ y$ w1 Y# I8 ^: Wlong style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);+ H: y+ k* N4 ~
style &= WS_EX_TRANSPARENT;
7 [6 M3 l8 G' O0 U% ?::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);! o& W% V6 X: k) h/ p
或 CreateEx,然后把WS_EX_TRANSPARENT样式加上
0 {+ D' b3 e% d8 @2 Z6 [
- L( t t2 ?0 A0 ?. d; d, l' _5 ve.得到内容有三种
6 v1 Z3 l6 J, `1)GetWindowText) P! d( w; F ^3 n7 P G. s
2)使用EM_GETTEXTEX
, U- @! r2 g- _GETTEXTEX gt;
" W, t& A0 \- y6 J, e' ?7 {gt.cb = 200;
8 Z/ h# U ~4 T& i F' B$ O( t- bgt.flags = GT_DEFAULT;
. D1 Z- O+ o: i5 C. h v* \" bgt.codepage = CP_ACP ;. ~8 Y+ W! ]; Y |+ Q! l% p/ c
gt.lpDefaultChar = NULL;
6 ?3 w# K5 o, R. Zgt.lpUsedDefChar = NULL;
. N$ y7 a, h' ]3 k( A pSendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);
: a j8 L% R: d8 N* k! {3 _+ ~5 o3)StreamOut(主要用于RTF等格式输出), w7 i5 g7 |8 R) {
static DWORD CALLBACK
0 |* y1 {$ c5 `; _) c7 c0 \MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
! P1 \ P" g+ B6 C( y/ C2 t{5 _8 y! m# v& m5 G+ J6 l" R
CFile* pFile = (CFile*) dwCookie;- W, Y4 y4 e3 H7 s) s: s& r3 C
( v2 b: s6 F8 G
pFile->Write(pbBuff, cb);4 t8 T9 a4 F" C# Y% C, L1 r
*pcb = cb;5 T% |# S$ D9 M, z7 O
" q4 ~# e; f0 k0 {& B* } return 0;8 m# E" c: D J" x$ S0 i
}
6 {/ F+ y: s1 m/ G! V. t
& \! W7 {. X/ K+ u" y; v7 ]8 F8 m' o' N" v Q, T
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);3 J: W2 p* L8 n; a6 a$ s) n m
EDITSTREAM es;
- s0 d- t X [! s& _ es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用
. l S7 L& p6 |' _! m5 s) _ es.pfnCallback = MyStreamOutCallback;
9 p& }# k+ q+ h6 {1 |: O3 R: T) i pmyRichEditCtrl->StreamOut(SF_RTF, es);# z( _' D) `, i9 P
读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn
/ _" a( p+ f0 h4 P
' s) B: `$ O, }6 Wf.查找字符串
$ |- q) q+ i; Z4 O! F. ~* L" {# P" `FINDTEXTEX ft;
$ @/ X/ T/ w/ K1 Y8 Yft.chrg.cpMin = 0;
" x1 ^1 E& ?" {1 uft.chrg.cpMax = -1;: Z2 F* m% y& O: N6 A3 J0 Y0 i5 a+ } {
ft.lpstrText = "|";
( W$ i1 |- Q1 [long lPos = FindText(0, &ft);
3 O, N( i, Z( x: ] Q; U0 h+ J" e& } |( y9 }+ }
如果要继续查找,修改cpMin,如: B2 U; ~$ p$ t9 ^' D: D- Z7 s
int nCount = 0;) m: v( ?, x, q. }" {
do/ O7 _9 h# B1 `0 L1 ]# ]
{
P: [3 K5 K! A long lPos = GetRichEditCtrl().FindText(0, &ft);3 I. z, g! W/ x' k3 B4 C
if( -1 == lPos) break;+ ] V( V! m$ O/ \/ F
ft.chrg.cpMin = lPos + strlen(ft.lpstrText);- m2 g9 }0 d( b) H
++nCount;
! p% u @$ |$ q% ]& W0 r- q8 F8 i}while(TRUE);
' Y" y( w) Y/ J8 i$ F" e# z
: |0 e; U5 ?4 O# Og.以Html格式保存- q ^ P* R# V$ y! h
目前做法可先转为RTF格式,再通过RTF-to-HTML Converter+ e; f8 H k w* y" R3 [3 J
http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/
( c! i8 D; P* h1 q; q+ m7 R3 N1 v) M+ q; i# B
h.重载OnProtected函数得到对应的消息,如粘贴等
/ i. a9 M3 Y7 W* K7 svoid CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
8 ] D; ~; D& c9 N% ]{ I3 c+ V% p7 o3 R+ y" R
ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
3 }; ~ w- d3 u$ j6 }0 B4 F" D+ @( U7 E4 j7 T
switch (pEP->msg) {, k- E3 k3 \0 f6 j: }3 ~, K
case WM_KEYDOWN://按键,判断pEP->wParam
9 H) x5 S& [( m2 D9 c case WM_PASTE://粘贴
8 R, ~5 N+ n" X8 N case WM_CUT://剪切
& S* I( k2 x R1 p9 l case EM_SETCHARFORMAT:
: c2 a' z+ `; h, S5 P$ m* _ default:8 g: n/ k0 v$ c- d8 Q2 H! a1 A
break;7 w# A( f! T* E
};
, H* h/ h, ^9 q4 M8 c& t0 l( h . G0 M6 \0 G8 y. ?
*pResult = FALSE;
/ m3 K+ i' |! |$ Q8 `}
# d# B# }4 ~3 P
" W) R; m1 g2 ]$ X2 A) J三.聊天常用
5 G5 f( ~7 J+ L' R7 fa.LINK 链接功能
+ j8 k& o4 g: E2 ^1. LoadLibrary(_T("Riched20.dll"));# T+ v3 t. b: g: M
2. 创建RichEdit2.0控件
8 |8 A( j6 L1 C/ O5 R1 K CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP
) ?% X3 v' M0 M0 |' k* Y|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,9 B: ^4 p" M \3 j2 J0 J
rect.left, rect.top, cx, cy,
: [% W5 A& [5 }- W5 B pParentWnd->m_hWnd, (HMENU)nID, NULL);
, i. B; O8 R5 [. m, M# k# X3. 设定选中的文字为链接显示
0 X% Q# N" K; VCHARFORMAT2 cf2;
% R7 D4 W0 x4 B% T5 BZeroMemory(&cf2, sizeof(CHARFORMAT2));//
: S4 x4 Z9 V+ J/ `; u$ r Ycf2.cbSize = sizeof(CHARFORMAT2);5 z3 [ f) Q6 T1 f* J( W. k6 [
cf2.dwMask = CFM_LINK;7 ] r( y7 U" q9 Q' ~5 p! y: x [
cf2.dwEffects |= CFE_LINK;
8 `* e9 Q ?; e: L, R( um_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);! L) {3 h* s) |+ C
4.支持链接的点击响应
/ M: X2 A+ W0 b, k" G6 N$ fm_cRichEdit.SetEventMask(ENM_LINK);( Z" F+ s6 ?! X4 O" R& E; c
5.响应链接的点击EN_LINK' [' h0 Z V& g
8 b3 z: t% Z2 M9 @9 ZBEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
5 c- M8 M7 m' k& K0 ^: F+ l. QON_NOTIFY_REFLECT(EN_LINK,OnURL)
4 ^& l& z. q( d# s# t' L9 lEND_MESSAGE_MAP()/ E9 k" ^' }) C3 f. v' b
....... T4 Q3 [1 h0 c
: U/ `) j! j# p" P, j4 ~
void CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
" c5 R4 h, K6 _{% Y3 c* s8 D/ C" {/ ~
TCHAR LinkChar[512];
1 Q: n5 n# y* x0 K" FENLINK *pLink = (ENLINK *)pNmhdr;- p0 h' r' @% t2 K/ F
if (pLink->msg == WM_LBUTTONUP)
( q( a% T0 i$ _{- |- o1 l$ |& [
SetSel(penLink->chrg);//这是链接的文字范围
, ` F0 k& V+ _( K; f) m& }long Res = GetSelText((char *)LinkChar);//这是链接文字
( d: s& V3 z1 a0 c" s9 @0 {' u //后面是你的处理过程+ O9 j# f, o3 q% v) l
......
& A7 z- A2 L5 s: B- F1 c }
" e) \0 V" _5 F) [3 l3 W, D}; N, v) S; _ d/ u
$ Q. f6 w1 W2 ?8 i
b.插入位图
! U, I( N3 [+ R: }0 ^http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/5 @' p# j$ j9 b
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
. C1 G, N% j |; D
/ T8 G5 o- V; X4 B+ z$ C自定义在RichEdit中插入对象的图标% X+ j/ I3 y) X0 b+ i7 Z
http://www.blogcn.com/user3/jiangsheng/blog/1319738.html/ @6 `" k. v q1 X' K
方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control+ n y) B8 R2 a7 u$ ?( y' c: m* X
只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片+ b1 K: z0 V& ?6 }
% T# u: K) G* S7 u9 X- m$ G0 Y' B使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。
/ V0 K# \6 i& j3 w, u8 ]7 |$ P9 p另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。
c0 u. {4 j( O" u0 n3 {& g* r
" m, e6 ~8 w; Q0 N% M0 r v- m+ dc.显示GIF动画
, u) {' B" h2 W! r0 P4 G常用的是通过qq的imageole.dll(也有用Gif89.dll的)
, ] W. S5 h7 U: |6 b! l- \" Nhttp://www.xiaozhou.net/cooldog/blogview.asp?logID=82
$ R1 W, a9 x/ `0 r. c$ h& D! lhttp://www.codeproject.com/richedit/AnimatedEmoticon.asp
+ ~ z5 m8 q3 i: b- ^# O# I. g% M$ r4 Q
/ U! M7 Y" o9 z5 I/ j w在richedit控件中插入动态GIF (Native C++版)
& S' I" f1 S0 d1 \7 `8 {" qhttp://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx
0 {1 N& ~9 X0 c$ X& O' Z+ q8 `8 v3 d) [9 d1 p( I* M ]
d.IRichEditOleCallback的使用
# u* f' J" A+ I+ Q+ mhttp://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022/ H% T/ `# {0 ?/ y' p0 _0 D# a
- ]* i E3 {3 u2 {% G# F2 e6 t类似 MSN 信息发送框的制作(上)/ b) N8 W6 P0 v" c- Q3 w
http://www.vckbase.com/document/viewdoc/?id=1087
2 F+ y R" ~8 T7 Z0 T0 W# i内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串8 p* C# ]1 q2 @
& @3 y3 `* o+ g+ k2 j# l自定义 CRichEditCtrl 控件
" [2 h4 o3 e0 |0 | Z1 E& K4 q' }http://www.vckbase.com/document/viewdoc/?id=328
3 {1 V1 W, @4 j4 j' H内容包含:鼠标右键消息,消息映射,字体变换
$ t! A( r5 i* x0 v6 s$ ?0 H6 s& Z! A7 G
PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母: Q! S1 M$ I, R4 e+ d3 j
是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778 + T9 Z4 e7 y; j# h( `
----------------------
J, [7 B) F) U. f, S$ c比我想象中还要花时间,所以最后潦草了点,见谅 |
|