一.常見問題
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;
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("隸書"));//設定字型
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)>,(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
類似 MSN 資訊發送框的製作(上)
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
註:
m_edit1代表ID為IDC_EDIT1的CEdit控制項的control類型的變數
m_richedit1代表ID為IDC_RICHEDIT1的CRichEditCtrl控制項的control類型的變數
--------------------------------------------------------------------------------
1.設定edit唯讀屬性
方法一:
m_edit1.SetReadOnly(TRUE);
方法二:
::SendMessage(m_edit1.m_hWnd, EM_SETREADONLY, TRUE, 0);
--------------------------------------------------------------------------------
2.判斷edit中游標狀態並得到選中內容(richedit同樣適用)
int nStart, nEnd;
CString strTemp;
m_edit1.GetSel(nStart, nEnd);
if(nStart == nEnd)
{
strTemp.Format(_T("游標在%d"), nStart);
AfxMessageBox(strTemp);
}
else
{
//得到edit選中的內容
m_edit1.GetWindowText(strTemp);
strTemp = strTemp.Mid(nStart) - strTemp.Mid(nEnd);
AfxMessageBox(strTemp);
}
註:GetSel後,如果nStart和nEnd,表明游標處於某個位置(直觀來看就是游標在閃動);
如果nStart和nEnd不相等,表明使用者在edit中選中了一段內容。
--------------------------------------------------------------------------------
3.在edit最後添加字串
CString str;
m_edit1.SetSel(-1, -1);
m_edit1.ReplaceSel(str);
--------------------------------------------------------------------------------
4.隨輸入自動滾動到最後一行(richedit同樣適用)
方法一:(摘自msdn)
// The pointer to my edit.
extern CEdit* pmyEdit;
int nFirstVisible = pmyEdit->GetFirstVisibleLine();
// Scroll the edit control so that the first visible line
// is the first line of text.
if (nFirstVisible > 0)
{
pmyEdit->LineScroll(-nFirstVisible, 0);
}
方法二:
m_richedit.PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
--------------------------------------------------------------------------------
5.如何限制edit輸入指定字元
可以從CEdit派生一個類,添加WM_CHAR訊息映射。下面一個例子實現了限定輸入16進位字元的功能。
void CMyHexEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if ( (nChar >= '0' && nChar <= '9') ||
(nChar >= 'a' && nChar <= 'f') ||
(nChar >= 'A' && nChar <= 'F') ||
nChar == VK_BACK ||
nChar == VK_DELETE) //msdn的virtual key
{
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
}
--------------------------------------------------------------------------------
6.如何使用richedit
添加AfxInitRichEdit();
CxxxApp::InitInstance()
{
AfxInitRichEdit();
.............
}
AfxInitRichEdit()功能:裝載 RichEdit 1.0 Control (RICHED32.DLL).
--------------------------------------------------------------------------------
7.如何使用richedit2.0 or richedit3.0
使用原因:由於RichEdit2.0A自動為寬字元(WideChar),所以它可以解決中文亂碼以及一些漢字問題
方法一:(msdn上的做法,適用於用VC.NET及以後版本建立的工程)
To update rich edit controls in existing Visual C++ applications to version 2.0,
open the .RC file as text, change the class name of each rich edit control from "RICHEDIT" to "RichEdit20a".
Then replace the call to AfxInitRichEdit with AfxInitRichEdit2.
方法二:以對話方塊為例:
(1) 增加一全域變數 HMODULE hMod;
(2) 在CxxxApp::InitInstance()中添加一句hMod = LoadLibrary(_T("riched20.dll"));
在CxxxApp::ExitInstance()中添加一句FreeLibrary(hMod);
(3) 在對話方塊上放一個richedit,文本方式開啟.rc檔案修改該richedit控制項的類名"RICHEDIT" to "RichEdit20a".
(4) 在對話方塊標頭檔添加 CRichEditCtrl m_richedit;
在OnInitDialog中添加 m_richedit.SubclassDlgItem(IDC_RICHEDIT1, this);
--------------------------------------------------------------------------------
8.改變richedit指定地區的顏色及字型
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE |
CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE;
cf.dwEffects = 0;
cf.yHeight = 12*12;//文字高度
cf.crTextColor = RGB(200, 100, 255); //文字顏色
strcpy(cf.szFaceName ,_T("隸書"));//設定字型
m_richedit1.SetSel(1, 5); //設定處理地區
m_richedit1.SetSelectionCharFormat(cf);
--------------------------------------------------------------------------------
9.設定行間距(只適用於richedit2.0)
PARAFORMAT2 pf;
pf2.cbSize = sizeof(PARAFORMAT2);
pf2.dwMask = PFM_LINESPACING | PFM_SPACEAFTER;
pf2.dyLineSpacing = 200;
pf2.bLineSpacingRule = 4;
m_richedit.SetParaFormat(pf2);
--------------------------------------------------------------------------------
10.richedit插入位元影像
Q220844:How to insert a bitmap into an RTF document using the RichEdit control in Visual C++ 6.0
http://support.microsoft.com/default.aspx?scid=kb;en-us;220844
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
--------------------------------------------------------------------------------
11.richedit插入gif動畫
http://www.codeproject.com/richedit/AnimatedEmoticon.asp
--------------------------------------------------------------------------------
12.richedit嵌入ole對象
http://support.microsoft.com/kb/141549/en-us
--------------------------------------------------------------------------------
13.使richedit選中內容唯讀
http://www.codeguru.com/cpp/controls/richedit/article.php/c2401/
--------------------------------------------------------------------------------
14.列印richedit
http://www.protext.com/MFC/RichEdit3.htm
--------------------------------------------------------------------------------
15.richeidt用於聊天訊息視窗
http://www.vckbase.com/document/viewdoc/?id=1087
http://www.codeproject.com/richedit/chatrichedit.asp
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2395/
--------------------------------------------------------------------------------
16.解決richedit的EN_SETFOCUS和EN_KILLFOCUS無響應的問題
http://support.microsoft.com/kb/181664/en-us
--------------------------------------------------------------------------------
17.richedit拼字檢查
http://www.codeproject.com/com/AutoSpellCheck.asp
--------------------------------------------------------------------------------
18.改變edit背景色
Q117778:How to change the background color of an MFC edit control
http://support.microsoft.com/kb/117778/en-us
--------------------------------------------------------------------------------
19.當edit控制項的父視窗屬性是帶標題列WS_CAPTION和子視窗WS_CHILD時,不能設定焦點SetFocus
Q230587:PRB: Can't Set Focus to an Edit Control When its Parent Is an Inactive Captioned Child Window
http://support.microsoft.com/kb/230587/en-us
--------------------------------------------------------------------------------
20. 在Edit中斷行符號時,會退出對話方塊
選中Edit的風格Want Return。
MSDN的解釋如下:
ES_WANTRETURN Specifies that a carriage return be inserted when the user presses the ENTER key while entering text into a multiple-line edit control in a dialog box. Without this style, pressing the ENTER key has the same effect as pressing the dialog box's default pushbutton. This style has no effect on a single-line edit control.
--------------------------------------------------------------------------------
21. 動態建立的edit沒有邊框的問題
m_edit.Create(....);
m_edit.ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_DRAWFRAME);
--------------------------------------------------------------------------------
22. 一個能顯示RTF,ole(包括gif, wmv,excel ,ppt)的例子
http://www.codeproject.com/richedit/COleRichEditCtrl.asp
轉載:http://bbs.chinavideo.org/viewthread.php?tid=1806
三、個人的一點東西(執行個體)
初始化:AfxInitRichEdit2();
視窗中兩個RichEditCtrl對應:
CRichEditCtrl m_rtdRecv; //接收視窗
CRichEditCtrl m_rtdSend; //發送視窗
//設定richEdit視窗屬性
void CDemoDlgMsg::SetRichEditStyle()
{
/*設定相關控制項的一些屬性*/
m_rtdRecv.SetAutoURLDetect(TRUE);
m_rtdRecv.SetEventMask(ENM_CHANGE);
USES_CONVERSION;
/*設定聊天編輯框和資訊顯示框的字型屬性*/
//m_cfDefault.cbSize = sizeof(CHARFORMAT);
//m_cfDefault.dwMask = CFM_BOLD|CFM_COLOR|CFM_FACE|CFM_ITALIC|CFM_UNDERLINE;
//m_cfDefault.dwEffects = CFE_BOLD|CFE_ITALIC|CFE_UNDERLINE;
//m_cfDefault.yHeight = 20*1440/96;
//m_cfDefault.yOffset = 0;
//m_cfDefault.crTextColor = RGB(255,0,0);
//m_cfDefault.bCharSet = 0;
//m_cfDefault.bPitchAndFamily = 0;
//strcpy(W2A(m_cfDefault.szFaceName), "宋體");
m_cfDefault.cbSize = sizeof(CHARFORMAT);
m_rtdRecv.GetDefaultCharFormat(m_cfDefault);
m_cfDefault.yHeight = 200;
m_cfDefault.dwEffects = 0;
m_cfDefault.crTextColor = RGB(0, 0, 255);
m_rtdRecv.SetDefaultCharFormat(m_cfDefault);
m_rtdRecv.LimitText(1024);
m_rtdSend.SetDefaultCharFormat(m_cfDefault);
m_rtdSend.LimitText(1024);
}
//顯示接收視窗訊息
void CDemoDlgMsg::ShowRecvText(CString str)
{
/*如果需要換行顯示*/
m_rtdRecv.ReplaceSel(str);
m_rtdRecv.SetSel(-1, -1);
m_rtdRecv.ReplaceSel(L"\r\n");
}