一般性问题
1.
代码编译通过了,运行后
RichEdit
控件不显示,在
InitInstance
中添加
BOOL CWinApp::InitInstance ()
{
…
AfxInitRichEdit(); - RichEdit 1.0
或
AfxInitRichEdit2(); - RichEdit 2.0
…
}
2.
升级默认的
RichEdit
版本,默认的版本有
BUG
,在
InitInstance
中添加
BOOL CWinApp::InitInstance ()
{
…
LoadLibrary("RICHED20.DLL");
…
FreeLibrary();
}
如果是
CRichEditView
基类的话,可用如下消息机制
:
BOOL CRichEditView::PreCreateWindow(CREATESTRUCT& cs)
{
if (LoadLibraryA("RICHED20.DLL") == NULL)
{
AfxMessageBox(_T("Fail to load /"riched20.dll/"."),MB_OK | MB_ICONERROR);
PostMessage(WM_QUIT,0,0);
return FALSE;
}
m_strClass = RICHEDIT_CLASSA;
return CRichEditView::PreCreateWindow(cs);
}
3.
在
RichEdit
控件的输入框中最后追加一行
CRichEditCtrl.SetSel(-1, -1);
CRichEditCtrl.ReplaceSel((LPCTSTR)str);
4.
限制
RichEdit
控件的
字数
CRichEditCtrl.LimitText(long nChars)
5.
设置
RichEdit
控件的
换行切换
如果是
CRichEditView
基类的话,可用如下消息机制
:
BOOL CRichEditView::OnInitialUpdate()
{
…
m_nWordWrap = WrapNone;
WrapChanged();
…
}
如果是在
Dialog
,可使用
SetTargetDevice
,并在
RichEdit
的属性里面加上
want return
CRichEditCtrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
WrapChanged
实际上也是调用
CRichEditCtrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow
CRichEditCtrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone
CRichEditCtrl.SetTargetDevice(NULL, 2);// m_nWordWrap == WrapToTargetDevice
6.
设置
RichEdit
控件不带格式的数据粘贴
CRichEditCtrl.PasteSpecial(CF_TEXT);
7.
设置
RichEdit
控件的滚动条自动随输入滚动到最后一行
int nFirstVisible = CRichEditCtrl.GetFirstVisibleLine();
if (nFirstVisible > 0)
{
CRichEditCtrl.LineScroll(-nFirstVisible, 0);
}
或
CRichEditCtrl.PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
8.
设置
RichEdit
控件的撤销输入
次数
(
只能用在
RICHED20
以上
)
SendMessage(EM_SETTEXTMODE, TM_MULTILEVELUNDO, 0);
SendMessage(EM_SETUNDOLIMIT, 100, 0);
TM_MULTILEVELUNDO
支持多取消
(
默认值
)
,
可通过
EM_SETUNDOLIMIT
设置最大次数
9.
设置
RichEdit
控件的
OnChange
事件
EM_SETEVENTMASK
设置
ENM_CHANGE
long lMask = GetEventMask();
lMask |= ENM_CHANGE;
lMask &= ~ENM_PROTECTED;
SetEventMask(lMask);
10.
设置
RichEdit
控件的只读属性
CRichEditCtrl::SetReadOnly(BOOL bReadOnly = TRUE );
通过设置
PROTECTED
实现选中的文本只读,参见如下文章:
函数应用
1.
设置
RichEdit
控件的显示
字体
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask|=CFM_BOLD;
cf.dwEffects|=CFE_BOLD; //
粗体,取消用
cf.dwEffects&=~CFE_BOLD;
cf.dwMask|=CFM_ITALIC;
cf.dwEffects|=CFE_ITALIC; //
斜体,取消用
cf.dwEffects&=~CFE_ITALIC;
cf.dwMask|=CFM_UNDERLINE;
cf.dwEffects|=CFE_UNDERLINE; //
斜体,取消用
cf.dwEffects&=~CFE_UNDERLINE;
cf.dwMask|=CFM_COLOR;
cf.crTextColor = RGB(255,0,0); //
设置颜色
cf.dwMask|=CFM_SIZE;
cf.yHeight =200; //
设置高度
cf.dwMask|=CFM_FACE;
strcpy(cf.szFaceName ,_T("
隶书
")); //
设置字体
CRichEditCtrl.SetSelectionCharFormat(cf);
2.
设置
RichEdit
控件的显示
字体的行间距(只能用在
RICHED20
以上)
PARAFORMAT2 pf;
pf.cbSize = sizeof(PARAFORMAT2);
pf.dwMask = PFM_NUMBERING | PFM_OFFSET;
pf.wNumbering = PFN_BULLET; //
注意
PFM_NUMBERING
pf.dxOffset = 10;
VERIFY(SetParaFormat(pf));
常用的
dwMask
有如下列表:
PFM_NUMBERING
成员
wNumbering
才起作用
1
项目符号,默认用
PFN_BULLET.
2
使用阿拉伯数字
(1, 2, 3, ...).
3
使用小写字母
(a, b, c, ...).
4
使用大写字母
(A, B, C, ...).
5
使用小写罗马数字
(i, ii, iii, ...).
6
使用大写罗马数字
(I, II, III, ...).
7
自定义,字符见成员
wNumberingStart.
PFM_OFFSET
成员
dxOffset
才起作用,缩进,单位
twips
PFM_STARTINDENT
成员
dxStartIndent
才起作用,首行缩进
PFM_SPACEAFTER
成员
dySpaceAfter
才起作用,段间距
PFM_LINESPACING
成员
dyLineSpacing
才起作用,行间距
3.
设置
RichEdit
控件的透明背景(只能用在
RICHED20
以上)
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
style &= WS_EX_TRANSPARENT;
::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);
或
CreateEx()
,然后把
WS_EX_TRANSPARENT
样式加上
4.
获取或者写入
RichEdit
控件的内容
Ø
GetWindowText
Ø
使用
EM_GETTEXTEX
GETTEXTEX gt;
gt.cb = 200;
gt.flags = GT_DEFAULT;
gt.codepage = CP_ACP ;
gt.lpDefaultChar = NULL;
gt.lpUsedDefChar = NULL;
SendMessage(EM_GETTEXTEX,(WPARAM)>,(LPARAM)text);
Ø
StreamOut(
主要用于
RTF
等格式输出
)
static DWORD CALLBACK
;
MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
CFile* pFile = (CFile*) dwCookie;
pFile->Write(pbBuff, cb);
*pcb = cb;
return 0;
}
CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);
EDITSTREAM es;
es.dwCookie = (DWORD) &cFile; //
设置用例参数
,
以便回调函数调用
es.pfnCallback = MyStreamOutCallback;
pmyRichEditCtrl->StreamOut(SF_RTF, es);
读入可以此类推,
SetWindowText, EM_SETTEXTEX, StreamIn
5.
查找
RichEdit
控件中的
字符串
FINDTEXTEX ft;
ft.chrg.cpMin = 0;
ft.chrg.cpMax = -1;
ft.lpstrText = "|";
long lPos = FindText(0, &ft);
如果要继续查找,修改
cpMin,
如
int nCount = 0;
do
{
long lPos = GetRichEditCtrl().FindText(0, &ft);
if( -1 == lPos) break;
ft.chrg.cpMin = lPos + strlen(ft.lpstrText);
++nCount;
}while(TRUE);
6.
以
Html
格式保存
RichEdit
控件中的内容
临时做法可先转为
RTF
格式,再通过
RTF-to-HTML Converter
,参考如下文章:
8.
重载
OnProtected
函数以得到
RichEdit
对应的消息,如粘贴等
void CRichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
{
ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
switch (pEP->msg)
{
case WM_KEYDOWN: //
按键,判断
pEP->wParam
case WM_PASTE: //
粘贴
case WM_CUT: //
剪切
case EM_SETCHARFORMAT:
default:
break;
};
*pResult = FALSE;
}
聊天常用
1.
设置
RichEdit
控件的
链接功能(只能用在
RICHED20
以上)
Ø
LoadLibrary(_T("Riched20.dll"));
Ø
创建
RichEdit2.0
控件
CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP |ES_READONLY|ES_WANTRETURN|ES_MULTILINE, rect.left, rect.top, cx, cy, pParentWnd->m_hWnd, (HMENU)nID, NULL);
Ø
设置选中的文字为链接显示
CHARFORMAT2 cf2;
ZeroMemory(&cf2, sizeof(CHARFORMAT2));//
cf2.cbSize = sizeof(CHARFORMAT2);
cf2.dwMask = CFM_LINK;
cf2.dwEffects |= CFE_LINK;
m_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
Ø
支持链接的点击响应
m_cRichEdit.SetEventMask(ENM_LINK);
Ø
响应链接的点击
EN_LINK
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
ON_NOTIFY_REFLECT(EN_LINK, OnURL)
END_MESSAGE_MAP()
......
void CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)
{
TCHAR LinkChar[512];
ENLINK *pLink = (ENLINK *)pNmhdr;
if (pLink->msg == WM_LBUTTONUP)
{
SetSel(penLink->chrg); //
这是链接的文字范围
long Res = GetSelText((char *)LinkChar); //
这是链接文字
…
}
}
Ø
自动识别链接
UINT nMask = SendDlgItemMessage(IDC_RICHEDIT_MESSAGE, EM_GETEVENTMASK, 0, 0);
SendDlgItemMessage(IDC_RICHEDIT_MESSAGE, EM_SETEVENTMASK, 0, nMask | NM_LINK);
SendDlgItemMessage(IDC_RICHEDIT_MESSAGE, EM_AUTOURLDETECT, TRUE, 0);
BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
NMHDR* pNmHdr = (NMHDR *)lParam;
if(pNmHdr->idFrom == IDC_RICHEDIT_MESSAGE && pNmHdr->code == EN_LINK)
{
ENLINK *pLink = (ENLINK *)lParam;
if (pLink->msg == WM_LBUTTONDOWN)
{
SendDlgItemMessage(IDC_RICHEDIT_MESSAGE, EM_EXSETSEL, 0, (LPARAM)&(pLink->chrg));
ShellExecute(GetSafeHwnd(), "open", m_wndREMessage.GetSelText(), 0, 0, SW_SHOWNORMAL);
}
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
2.
在
RichEdit
中
插入位图
Ø
参考如下文章:
Ø
自定义在
RichEdit
中插入对象的图标
3.
在
RichEdit
显示
GIF
动画
Ø
常用的是通过
QQ
的
imageole.dll(
也有用
Gif89.dll
的
)
Ø
在
richedit
控件中插入动态
GIF(Native C++
版
)
4.IRichEditOleCallback
的使用
5.
类似
MSN
信息发送框的制作
(
上
)
内容包含:实现右键菜单,图片插入,读取
/
写入
RTF
格式字符串
6.
自定义
RichEdit
控件
内容包含:鼠标右键消息,消息映射,字体变换