|
一.常见问题
( B. Z& W( M4 A; q9 X, Ua.可以编译,不能执行的, V+ z2 M: W0 k3 ^
AfxInitRichEdit();+ H# _: r4 w/ ^+ ~% F; v
- Y/ ]7 s w3 p% V5 Jb.升级默认的Riched版本(默认的有一些bug),如
4 v! r3 F" O8 e8 a, j可在InitInstance中添加
. L4 G) E: V3 q# C/ w( i+ E+ ZLoadLibrary("RICHED20.DLL")
( B0 F5 `. q7 K- p8 t) v2 l最后注意 FreeLibrary2 |, y# u3 N" d/ H+ T
! }; Q* M% [- o. B: l7 r2 w
如果是CRichEditView基类的可用+ w0 }* q! [& G; ~
BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)
; j9 ?. H( Q/ y5 R( m2 a; v9 t{: v3 H! ?% S4 S
//装入rich edit version 2.03 P: @ W4 i/ T1 d
if (LoadLibraryA("RICHED20.DLL") == NULL), ^$ q& `: K. u2 {! D4 {8 a
{
B* k2 J5 ]$ Q& L# \/ B, kAfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);
9 O* k. x! h; S) u$ i' J- lPostMessage(WM_QUIT,0,0);; W) m( [8 _1 D2 ~. c& I2 q
return FALSE;, k+ D4 Y8 m" H4 ^1 V$ z/ p
}
8 R/ ~* G8 U, u4 n! E9 ?9 p- g
: n- _- g0 k! u I* u' X) xm_strClass = RICHEDIT_CLASSA;//for 2.0 class, g3 b1 a, j% x6 } F
% B+ Q& s& B" W f: d
return CRichEditView::PreCreateWindow(cs);
[. _# b( s- O* b( n1 R}
0 B8 D) z& c$ \( _
% x& d1 K7 V% Cc.最后追加行
e1 N) n: x! Y/ ~3 Uricheditctrl.SetSel(-1, -1);
) |4 g6 a1 \0 w z+ r, G/ sricheditctrl.ReplaceSel( (LPCTSTR)str );/ ?4 S* A4 ^1 v% q5 v" K0 `
N; K9 X2 f- g2 c% D9 Ed.字数限制
5 d& C1 N z) }) k& fCRichEditCtrl::LimitText(long nChars)# i" u7 j# ~$ w/ p) _5 q9 u
( i/ z* `/ M$ _# g, S+ u! l4 Se.换行切换
" b% O1 G4 a$ ~+ \! r ?9 mCRichEditView的OnInitialUpdate()函数中加入下面两句:0 x# I; \ y; J& R# S
m_nWordWrap = WrapNone;
! q6 F$ S( [) HWrapChanged(); , K& H. I% u' K
WrapChanged实际上也是调用0 D2 S/ c$ L2 l* T0 I8 [
ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone& n8 O. D# Z/ N7 H- C* m- t+ z
ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow
' k6 m) y7 E0 B8 E1 {. A还有不常用的 m_nWordWrap == WrapToTargetDevice5 p8 Z6 O8 ?7 n, _# [ b
ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
7 n2 w* y2 q* G: q5 i如果是在Dialog中,可使用SetTargetDevice,注意在属性里面加上want return' {7 G. R7 q9 \8 E" b& V
) M# u6 s: m- z- O4 ]f.有时候不希望带格式的数据粘贴,可通过PasteSpecial选择性粘贴
' L+ e( }7 o& P7 w+ CpmyRichEditCtrl->PasteSpecial(CF_TEXT);* x% N0 R9 N. ?; G) H/ S0 n8 R
# y' F* W& _% Z* A
g.随着输入随着自动滚动条滚动到最后一行
1 U/ B9 w# U. h6 s, ]int nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();* L' n* v2 q( u: J D% _! D3 [
if (nFirstVisible > 0)
& `% B0 m# U% f% |{
3 M3 k5 U+ ?9 C9 W4 ]; m2 @ P pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);/ w4 ]6 z; r' @% H o1 I
}
% [1 K- z& Q9 O) L( ?) `或: i: a9 a8 O+ z* }3 W; H4 v
m_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);
, ~* r1 n+ a- h4 \' b* X
& K/ B) `8 L8 K- y5 ]$ W+ R( M q0 u8 k. M3 J+ S) h7 k% Z- O/ C
h.设置UNDO的次数(只能用在RICHED20以上,即默认不支持,必须升级)( J2 _2 d$ V: O" z( G
SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);0 s s* b# J( H7 _) E8 F
TM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数
' U( f/ N b3 ]$ ]- a4 M& GSendMessage(EM_SETUNDOLIMIT,100,0);
, G+ x9 E& S' U1 a0 h; m$ u6 S0 ]! ?4 q1 V: l- t
i.响应OnChange8 E1 b2 B: S. s6 H2 q
EM_SETEVENTMASK 设置 ENM_CHANGE 8 m1 G" r T1 ]# _
long lMask = GetEventMask();
$ {* g% f2 z/ Z: j8 `lMask |= ENM_CHANGE;6 F. G$ ~% A0 F3 ^# M, ]3 S
lMask &= ~ENM_PROTECTED;
. M- r: Y4 K. D# N0 o# CSetEventMask(lMask);
9 w1 X3 T, Q- }. V0 y4 m% g! g$ r
8 ~2 r+ i- r9 gj.设置只读
, w9 \5 A! a8 C# ~% A) VCRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );" e2 T% x8 g- Z2 l
通过设置PROTECTED实现选中的文本只读,参见
3 `) K) _& ?4 T- ?# whttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/
0 c$ f, h5 C+ y) n1 Z/ M T( g; ]8 D% u: b1 l& V, B! B
二.函数应用
* o( R4 R% L5 V' R9 O3 _a.设置字体(主要是通过SetSelectionCharFormat)
2 }7 f7 O' l Y+ n# n" ]CHARFORMAT cf;# U/ h# X) R5 [( y
rich.GetSelectionCharFormat(cf);/ n4 k; L6 r Q& U: ~1 ?
cf.dwMask|=CFM_BOLD;
* K2 u6 q' P1 Y0 {3 o4 `cf.dwEffects|=CFE_BOLD;//设置粗体,取消用cf.dwEffects&=~CFE_BOLD;, e* Z; }9 }" e) G& q0 Y
cf.dwMask|=CFM_ITALIC;
- ~7 v v4 Z/ Q8 m2 d; b: ?! Gcf.dwEffects|=CFE_ITALIC;//设置斜体,取消用cf.dwEffects&=~CFE_ITALIC;) B& H* O3 d0 @( m- f
cf.dwMask|=CFM_UNDERLINE;3 V% v! T3 ]8 X+ B5 U* {
cf.dwEffects|=CFE_UNDERLINE;//设置斜体,取消用cf.dwEffects&=~CFE_UNDERLINE;
; z- j* p8 u$ n3 ~cf.dwMask|=CFM_COLOR;
' i U- s3 d) m$ Ecf.crTextColor = RGB(255,0,0);//设置颜色
7 k& P7 j5 N. x acf.dwMask|=CFM_SIZE;
T" m$ n/ S( ?+ M) O9 N- M' t+ Jcf.yHeight =200;//设置高度8 L* O4 a$ D! ^( D4 _. Q; n8 n# m
cf.dwMask|=CFM_FACE;
8 ~6 L2 ~! j9 n' D _5 @6 d% Zstrcpy(cf.szFaceName ,_T("隶书"));//设置字体
; J/ Y% _& W2 V; Erich.SetSelectionCharFormat(cf);/ ]0 h- n( ^2 v: n \2 O
. ]/ }" l% H m2 y4 w+ o* l. _b.设置字体的行间距
4 l0 W5 a" ?* e要用richedit2.0以上# Q( N6 A( C. c! i$ e% y* N
试试
" C \2 U! y! X% Q# h# nPARAFORMAT2 pf;& L( o7 s2 F! f. Q2 d3 k, V1 M
pf.cbSize = sizeof(PARAFORMAT2);% f& |* j- h. ]$ J+ @7 t
pf.dwMask = PFM_NUMBERING | PFM_OFFSET;
& v/ S5 f; v6 w' @9 w ypf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING
* T' K! p1 o+ q& o! b9 Mpf.dxOffset = 10;
& ~( A l3 f( v; L! n, `VERIFY(SetParaFormat(pf));
; z. e6 C& s6 |6 M3 C常用的dwMask有7 J: Q2 j* t) E5 y
PFM_NUMBERING 成员 wNumbering 才起作用,项目符号,默认用PFN_BULLET+ b# _' n# B/ X/ a7 _+ b Z
2 使用阿拉伯数字 (1, 2, 3, ...). ! j; b# z7 `$ }. i: A9 F) d; Z
3 使用小写字母 (a, b, c, ...).
& A" f+ _* o) c# T4 a' Y4 使用大写字母 (A, B, C, ...).
; ^9 D( C, I2 Q; Z% m; M5 使用小写罗马数字 (i, ii, iii, ...). , `) Q. f R5 Q6 d3 ] ?* u" s
6 使用大写罗马数字 (I, II, III, ...).
" N* c0 Q$ I/ ~# E; H1 q6 `7 自定义,字符见成员 wNumberingStart. 5 S. P! B- X8 ?
PFM_OFFSET 成员 dxOffset 才起作用,缩进,单位twips
$ A7 }/ W& @1 `3 NPFM_STARTINDENT 成员 dxStartIndent 才起作用,首行缩进0 `" ^% n3 a( A
PFM_SPACEAFTER 成员 dySpaceAfter 才起作用,段间距2 s& {' l# p! \( p+ k9 W
PFM_LINESPACING 成员 dyLineSpacing 才起作用,行间距6 B+ t+ w' P6 [9 B& m Y @
$ {: H- Q* q- qc.设置CRichEditCtrl(2.0)背景透明 5 J3 m3 s) j' I* n
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
. G. F' B2 w E6 v+ x' g1 f5 |style &= WS_EX_TRANSPARENT;/ S; c3 r. Y3 L% D* v! D
::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);4 R) I9 j9 g5 A/ s& ^* O
或 CreateEx,然后把WS_EX_TRANSPARENT样式加上2 x- E% k! o! I! o
' t5 R4 \+ V- K( I* u- ?0 V7 e) fe.得到内容有三种$ e* B" Z" p/ t4 {1 F& d' a
1)GetWindowText
4 w; u& \/ X$ y2)使用EM_GETTEXTEX, B& W2 M1 {2 s7 d: f- _; g
GETTEXTEX gt;
: y* f6 v: N1 q/ Vgt.cb = 200;# V A: q* S1 \; D5 u* V+ V
gt.flags = GT_DEFAULT;# D! f0 }: y: _
gt.codepage = CP_ACP ;/ n. j# k1 ~: V) c( U
gt.lpDefaultChar = NULL;
$ [) o! D+ l0 S3 O2 k3 \6 J0 N! qgt.lpUsedDefChar = NULL;
6 Y* S. B# w& x7 f" XSendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);
4 K, V% a( ~ `. D. e; _3)StreamOut(主要用于RTF等格式输出)" n! f. K3 v. M
static DWORD CALLBACK
6 g g8 I& l5 k7 J- z( kMyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
$ F* Y7 m6 O `! O4 y6 X( N{
' p* ]( M+ ]# z CFile* pFile = (CFile*) dwCookie;
1 R5 ^/ n5 s/ _6 b9 P4 N+ D
5 s+ W% s" y) k; D pFile->Write(pbBuff, cb);
5 a; ?2 j) D( B0 y/ ~( a, e) v/ \& R *pcb = cb;$ `2 B& @* s9 P! g7 O; R
/ W& k) r' v, V1 U4 F5 [6 [ return 0;
# `! S8 j% ]' D) m& I}
' x7 ?4 p& @: r7 G6 R4 L- H% F( x5 H. _9 L
) ~$ |! \. z/ D( h% b CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);
& s; @/ Y% f' A+ f EDITSTREAM es;/ c% N, n4 v8 [
es.dwCookie = (DWORD) &cFile;//设置用例参数,以便回调函数调用7 b7 W- f- j# ]% C4 @# B- L
es.pfnCallback = MyStreamOutCallback; 7 p: k( i3 z2 w, g# w; s
pmyRichEditCtrl->StreamOut(SF_RTF, es);! W% @ d9 @& r) \
读入可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn
3 `0 `7 O# o6 A8 q
* `0 @/ _$ f2 K- M* ~4 f% k- xf.查找字符串# D6 i7 J, M7 b. |+ ]: w4 R2 M% g: G
FINDTEXTEX ft;
7 [, C+ J' t" Gft.chrg.cpMin = 0;
* s4 \$ _2 ~( [9 R1 D2 s h5 xft.chrg.cpMax = -1;- H% J9 \2 B( I2 @
ft.lpstrText = "|";% d0 A1 ?# e2 j6 @3 @6 B
long lPos = FindText(0, &ft);! j! i% Q' U; c7 _ Y" }# K
) U- s, A2 s7 B7 j, k; T如果要继续查找,修改cpMin,如
! m- A4 C5 e* Y2 x' W1 _2 Pint nCount = 0;" M: M6 [ `& ~# f) w1 k/ m/ m
do: G) u$ s" a. M0 P2 G. i2 h
{
' G' r: [. l# X7 a long lPos = GetRichEditCtrl().FindText(0, &ft);
1 ~4 i$ W& s8 Q$ b) | if( -1 == lPos) break;) M3 _9 p! q0 ? d0 ^! w6 \
ft.chrg.cpMin = lPos + strlen(ft.lpstrText);- t* v4 J) C8 r; w
++nCount;
+ H; H6 r- D" u, x C' u( Z8 V}while(TRUE); i* h/ h) c# ^: ?( W A( `3 r! B
) [0 P) `, ~+ g9 ]g.以Html格式保存; b$ ~% ~) B; e {9 d
目前做法可先转为RTF格式,再通过RTF-to-HTML Converter8 f" ^7 J$ ~6 _2 Q9 v o, E8 l
http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/2 R! x( Y4 x8 @! u& Z, _# v
# ^' b% m6 @3 r8 h
h.重载OnProtected函数得到对应的消息,如粘贴等* j! {( c0 t1 n) L4 s- I. g
void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
2 r' n" {1 H, p( r{# S7 d) Y, I1 B0 M4 g! Q! g
ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
$ h) `& K, V7 G: C9 Q' h4 N3 L* r+ e/ C
switch (pEP->msg) {" B5 D; |8 u% r8 a
case WM_KEYDOWN://按键,判断pEP->wParam% v @, c& }1 ]/ ]9 Y' {$ _
case WM_PASTE://粘贴
. r. x; a6 a) ~6 m( \ case WM_CUT://剪切6 |' W) S$ O* x
case EM_SETCHARFORMAT:+ Q9 n* F" k- Q! L( |2 _; a
default:
1 H3 e- G+ i+ G* V2 G m& X break;
- r; N. e3 N1 p7 l% E1 ^ };% h" M+ ]5 j9 {# |+ O e0 y0 u
% [4 J V( u# a( t
*pResult = FALSE;
, d2 q: n6 n7 L" v6 i2 H( k}
9 Q& x9 u1 }+ N
1 c" T' I) T3 H* f! _三.聊天常用 4 C! J: }/ I; P; h
a.LINK 链接功能9 Z7 F1 D5 S5 Y9 y+ q9 G
1. LoadLibrary(_T("Riched20.dll"));+ m# j! S2 S4 ^* o3 I3 Q- K
2. 创建RichEdit2.0控件/ M* b0 [1 D3 g: H% j; g2 _& d/ u
CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP! Y! N$ s: P; i% O; X
|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,
6 l9 L d0 J: ]) ]3 Z4 C* [ rect.left, rect.top, cx, cy,
% c9 }+ y% _( b% { pParentWnd->m_hWnd, (HMENU)nID, NULL);, z+ ]+ G( Y Q9 ?
3. 设定选中的文字为链接显示6 f- l0 [; J6 W4 R5 e
CHARFORMAT2 cf2;& o- D7 |1 @) k3 q8 U1 m& |$ W
ZeroMemory(&cf2, sizeof(CHARFORMAT2));//5 u( B! X' g8 j3 T" F8 p% ?/ C; g
cf2.cbSize = sizeof(CHARFORMAT2);/ U" `4 b5 K$ x+ J2 h
cf2.dwMask = CFM_LINK;! A4 w- u8 M% N& g
cf2.dwEffects |= CFE_LINK;
/ B4 `( {" N" ]0 W! Vm_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
; W# c- O' B" P0 q! J& x! C$ I% Z4.支持链接的点击响应
+ Y5 B+ J7 L' i8 m- k. Mm_cRichEdit.SetEventMask(ENM_LINK);( w0 ^2 @$ y! R+ H
5.响应链接的点击EN_LINK
: z9 [" t7 x+ T, I" k( s8 r, Y8 R: M& T. ]
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)! O- \5 D8 X! f- x! A& T. t2 V
ON_NOTIFY_REFLECT(EN_LINK,OnURL)
% g5 k* }8 q! ^7 F2 E# k' J+ R$ nEND_MESSAGE_MAP()
5 `$ }3 @/ b1 Q4 w* O......8 Q3 {* u' H6 q6 R* _6 C
1 {% m8 H4 k9 |void CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
4 y/ _* ]1 ]& w9 X0 }{
; ?2 v& R6 p& B1 R( p/ G5 W e& BTCHAR LinkChar[512];6 ?4 o- `6 @: @8 _% v
ENLINK *pLink = (ENLINK *)pNmhdr;: f+ b3 `7 F# I9 c2 \9 q% E; O. I
if (pLink->msg == WM_LBUTTONUP)) ~3 J& y/ C0 K' @! T
{
% k0 c" j6 V g4 i5 `! nSetSel(penLink->chrg);//这是链接的文字范围& a7 V- T) E$ ^$ Q% F# j
long Res = GetSelText((char *)LinkChar);//这是链接文字
6 v& G6 f" R$ T/ H5 h+ G$ Q& { //后面是你的处理过程9 ^& S+ I5 X9 @
......* u7 V9 f+ O" r
}9 k. W6 J$ O( C- D% G( k
}9 T7 {, z# O; ]( u! B
6 Z8 ^) Y# J1 ?+ K# Qb.插入位图
% E5 }) h! r0 M& |& ^" A! g- T+ m* Rhttp://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/
: y; E/ O4 j6 Khttp://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/9 G7 h1 x+ F* W. ^- L1 a
+ d& V6 e$ q1 i& p. H8 n自定义在RichEdit中插入对象的图标3 D5 K# [, y) d9 z& Q
http://www.blogcn.com/user3/jiangsheng/blog/1319738.html
5 I( ]+ V. ~: Y# C( d# H方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control1 ~ T; X) o( ^1 V) n
只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数,HGLOBAL里面的数据是一个METAFILEPICT结构,包含自己提供的图片3 L3 t* Y+ z, c; s- ?% K
+ v7 y9 Y# o j9 v& [使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。" x9 R* a& y2 S5 A2 w
另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(http://www.codeguru.com/richedit/richeditrc.html)。
& l4 y' M9 v9 `, g- v, f4 x6 Z# G) T0 ~2 N
c.显示GIF动画
' U7 C {1 ^& n" `9 ~* {常用的是通过qq的imageole.dll(也有用Gif89.dll的)
& Y/ U% a; s0 R2 @6 Uhttp://www.xiaozhou.net/cooldog/blogview.asp?logID=82
g& V5 c2 A% O# X. o. v. h: f1 X$ jhttp://www.codeproject.com/richedit/AnimatedEmoticon.asp
% E" L3 h/ Q, D0 B* h/ ]0 f/ J4 |+ y8 O
在richedit控件中插入动态GIF (Native C++版)& z; j3 r6 B( A* R
http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx
V& I A( g2 `! u) {( ^0 ]! f( ^0 C+ Q) T$ k
d.IRichEditOleCallback的使用- C$ a; }" A4 `0 \
http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022
5 k! C6 Q) `! U" O- V% q. x9 C
. p: y9 P1 i% C6 K: q类似 MSN 信息发送框的制作(上)
" y: g. D. O/ U" U/ g4 Mhttp://www.vckbase.com/document/viewdoc/?id=1087: T) c* h# G, S/ O0 D
内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串; V% Z& K8 a8 H
* H, K( V4 n4 v, K
自定义 CRichEditCtrl 控件2 _( S* ~( r, L5 e( J' ]) z
http://www.vckbase.com/document/viewdoc/?id=328; G- Z, i% C7 T6 u# m6 p! @
内容包含:鼠标右键消息,消息映射,字体变换9 \4 x. Q1 N$ B+ n* Z; ]1 |
7 n% V$ b# S! C# ]PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母/ J/ |1 J" Z+ s5 U0 C& [( r4 C
是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778 & a" o3 ^1 ]1 a# O) f
----------------------" x' R/ P! [: m5 r6 l
比我想象中还要花时间,所以最后潦草了点,见谅 |
|