CRichEditCtrl 超文本編輯

 
一.常見問題
a.可以編譯,不能執行的
AfxInitRichEdit(); //此句不要忘了加

b.升級默認的Riched版本(默認的有一些bug),如
可在InitInstance中添加
LoadLibrary("RICHED20.DLL")
最後注意 FreeLibrary

如果是CRichEditView基類的可用
BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)
{
//裝入rich edit version 2.0
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;//for 2.0 class

return CRichEditView::PreCreateWindow(cs);
}

c.最後追加行
richeditctrl.SetSel(-1, -1);
richeditctrl.ReplaceSel( (LPCTSTR)str );

d.字數限制
CRichEditCtrl::LimitText(long nChars)

e.換行切換
CRichEditView的OnInitialUpdate()函數中加入下面兩句:
m_nWordWrap = WrapNone;
WrapChanged();
WrapChanged實際上也是調用
ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone
ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow
還有不常用的 m_nWordWrap == WrapToTargetDevice
ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
如果是在Dialog中,可使用SetTargetDevice,注意在屬性裏面加上want return

f.有時候不希望帶格式的數據粘貼,可通過PasteSpecial選擇性粘貼
pmyRichEditCtrl->PasteSpecial(CF_TEXT);

g.隨着輸入隨着自動滾動條滾動到最後一行
int nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();
if (nFirstVisible > 0)
{
   pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);
}

m_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);


h.設置UNDO的次數(只能用在RICHED20以上,即默認不支持,必須升級)
SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);
TM_MULTILEVELUNDO 支持多取消(默認值).可通過EM_SETUNDOLIMIT設置最大次數
SendMessage(EM_SETUNDOLIMIT,100,0);

i.響應OnChange
EM_SETEVENTMASK 設置 ENM_CHANGE
long lMask = GetEventMask();
lMask |= ENM_CHANGE;
lMask &= ~ENM_PROTECTED;
SetEventMask(lMask);

j.設置只讀
CRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );
通過設置PROTECTED實現選中的文本只讀,參見
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/

二.函數應用
a.設置字體(主要是通過SetSelectionCharFormat)
CHARFORMAT cf;
rich.GetSelectionCharFormat(cf);
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("隸書"));//設置字體
rich.SetSelectionCharFormat(cf);

b.設置字體的行間距
要用richedit2.0以上
試試
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 才起作用,項目符號,默認用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 才起作用,行間距

c.設置CRichEditCtrl(2.0)背景透明
long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
style &= WS_EX_TRANSPARENT;
::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);
或 CreateEx,然後把WS_EX_TRANSPARENT樣式加上

e.得到內容有三種
1)GetWindowText
2)使用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)&gt,(LPARAM)text);
3)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

f.查找字符串
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);

g.以html格式保存
目前做法可先轉爲rtf格式,再通過rtf-to-html converter
http://www.codeguru.com/cpp/controls/richedit/conversions/article.php/c5377/

h.重載onprotected函數得到對應的消息,如粘貼等
void cmyicheditorview::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;
}

三.聊天常用
a.link 鏈接功能
1. loadlibrary(_t("riched20.dll"));
2. 創建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);
3. 設定選中的文字爲鏈接顯示
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);
4.支持鏈接的點擊響應
m_crichedit.seteventmask(enm_link);
5.響應鏈接的點擊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);//這是鏈接文字
//後面是你的處理過程
......
}
}

b.插入位圖
http://www.codeguru.com/cpp/controls/richedit/article.php/c2417/
http://www.codeguru.com/cpp/controls/richedit/article.php/c5383/

自定義在richedit中插入對象的圖標
http://www.blogcn.com/user3/jiangsheng/blog/1319738.html
方法基本同knowledge base文章q220844 howto: insert a bitmap into an rtf document using the richedit control
只是在最後插入之前調用一下iolecache::setdata,用一個hglobal作爲參數,hglobal裏面的數據是一個metafilepict結構,包含自己提供的圖片

使用cricheditview::insertfileasobject就可以插入圖像。vc++帶有一個例子wordpad。
另外可以參考“insert any hbitmap (bitmap) in your richedit control”(
http://www.codeguru.com/richedit/richeditrc.html)。

c.顯示gif動畫
常用的是通過qq的imageole.dll(也有用gif89.dll的)
http://www.xiaozhou.net/cooldog/blogview.asp?logid=82
http://www.codeproject.com/richedit/animatedemoticon.asp

在richedit控件中插入動態gif (native c++版)
http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx

d.iricheditolecallback的使用
http://61.186.252.131/expert/topic/905/905844.xml?temp=.8379022

>http://www.vckbase.com/document/viewdoc/?id=1087
內容包含:實現右鍵菜單,圖片插入,讀取/寫入rtf格式字符串

自定義 cricheditctrl 控件
http://www.vckbase.com/document/viewdoc/?id=328
內容包含:鼠標右鍵消息,消息映射,字體變換

ps.richedit控件升級到2.0後,先把字體設爲楷體,輸入漢字沒有問題,但輸入字母時,字母自動跳轉爲arial字體,而1.0卻沒有這個文題,仍然是用楷體顯示字母
是一個專門的設計 dual-font, smart font apply, 參見 http://61.186.252.131/expert/topic/913/913807.xml?temp=.3753778


 

發佈了13 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章