Richedit-
上传用户:ywjx168
上传日期:2022-02-02
资源大小:7k
文件大小:15k
-
-
- Richedit使用大全
-
- 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实现选中的文本只读,参见
- [color=#0000ff]http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/[/color] [size=4][color=sienna][/color][/color]
- [size=4][color=sienna][/color][/color][size=4][color=sienna]二.函数应用[/color][/color]
- 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
- [color=#0000ff]http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/[/color]
- 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;
- }
- [size=4][color=sienna]三.聊天常用[/color][/color]
- 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.插入位图
- [color=#0000ff]http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/[/color]
- [color=#0000ff]http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/[/color]
- 自定义在RichEdit中插入对象的图标
- [color=#0000ff]http://www.blogcn.com/user3/jiangsheng/blog/1319738.html[/color]
- 方法基本同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”([color=#0000ff]http://www.codeguru.com/richedit/richeditrc.html[/color])。
- c.显示GIF动画
- 常用的是通过qq的imageole.dll(也有用Gif89.dll的)
- [color=#0000ff]http://www.xiaozhou.net/cooldog/blogview.asp?logID=82[/color]
- [color=#0000ff]http://www.codeproject.com/richedit/AnimatedEmoticon.asp[/color]
- 在richedit控件中插入动态GIF (Native C++版)
- [color=#0000ff]http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx[/color]
- d.IRichEditOleCallback的使用
- [color=#0000ff]http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022[/color]
- 类似 MSN 信息发送框的制作(上)
- [color=#0000ff]http://www.vckbase.com/document/viewdoc/?id=1087[/color]
- 内容包含:实现右键菜单,图片插入,读取/写入RTF格式字符串 自定义 CRichEditCtrl 控件
- [color=#0000ff]http://www.vckbase.com/document/viewdoc/?id=328[/color]
- 内容包含:鼠标右键消息,消息映射,字体变换 PS.richedit控件升级到2.0后,先把字体设为楷体,输入汉字没有问题,但输入字母时,字母自动跳转为Arial字体,而1.0却没有这个文题,仍然是用楷体显示字母
- 是一个专门的设计 Dual-font, Smart font apply, 参见 [color=#0000ff]http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778[/color]
-
- 重写后的CRichEdit类可实现
- 1.右键菜单
- 2.能插入图片
- 3..RTF格式输入输出不够方便
- 二、原理简介
- 1、主要功能用CRichEditCtrl实现,像设置字体,设置字体颜色,字号等等CRichEditCtrl都提供了很完善的支持,我就不一一赘述了。
- CRichEditCtrl 主要的不足在于以下几个方面:
- (1).没有右键菜单
- (2).不能插入图片(这是实现转义字符显示的关键)
- (3).RTF格式输入输出不够方便(涉及到回调函数的递归调用)
- 我扩展了CRichEditCtrl类CRichEditCtrlEx实现了上述功能.参考了很多网上的文章,对所有公开源码的开发人员表示崇高的敬意!!
- 2、实现右键菜单:
- ///生成右键菜单
- void CRichEditCtrlEx::OnRButtonUp(UINT nFlags, CPoint point)
- {
- // TODO: Add your message handler code here and/or call default
- //设置为焦点
- SetFocus();
- //创建一个弹出式菜单
- CMenu popmenu;
- popmenu.CreatePopupMenu();
- //添加菜单项目
- popmenu.AppendMenu(0, ID_RICH_UNDO, "&Undo");
- popmenu.AppendMenu(0, MF_SEPARATOR);
- popmenu.AppendMenu(0, ID_RICH_CUT, "&Cut");
- popmenu.AppendMenu(0, ID_RICH_COPY, "C&opy");
- popmenu.AppendMenu(0, ID_RICH_PASTE, "&Paste");
- popmenu.AppendMenu(0, ID_RICH_CLEAR, "C&lear");
- popmenu.AppendMenu(0, MF_SEPARATOR);
- popmenu.AppendMenu(0, ID_RICH_SELECTALL, "Select &All");
- popmenu.AppendMenu(0, MF_SEPARATOR);
- popmenu.AppendMenu(0, ID_RICH_SETFONT, "Select &Font");
-
- //初始化菜单项
- UINT nUndo=(CanUndo() ? 0 : MF_GRAYED );
- popmenu.EnableMenuItem(ID_RICH_UNDO, MF_BYCOMMAND|nUndo);
-
- UINT nSel=((GetSelectionType()!=SEL_EMPTY) ? 0 : MF_GRAYED) ;
- popmenu.EnableMenuItem(ID_RICH_CUT, MF_BYCOMMAND|nSel);
- popmenu.EnableMenuItem(ID_RICH_COPY, MF_BYCOMMAND|nSel);
- popmenu.EnableMenuItem(ID_RICH_CLEAR, MF_BYCOMMAND|nSel);
-
- UINT nPaste=(CanPaste() ? 0 : MF_GRAYED) ;
- popmenu.EnableMenuItem(ID_RICH_PASTE, MF_BYCOMMAND|nPaste);
-
- //显示菜单
- CPoint pt;
- GetCursorPos(&pt);
- popmenu.TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this);
- popmenu.DestroyMenu();
- CRichEditCtrl::OnRButtonDown(nFlags, point);
- CRichEditCtrl::OnRButtonUp(nFlags, point);
- }3、关于如何把图片插入到RichEdit中,国外由很多文章介绍,都是(我看到的都是)通过插入OLE对象来实现.主要用两个函数,还涉及到了和多接口的调用。
- (1)从文件创建OLE对象OleCreateFromFile();
- void CRichEditCtrlEx::InsertBitmap(CString szFileName)
- {
- USES_CONVERSION;
- SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &m_lpLockBytes);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(m_lpLockBytes != NULL);
-
- sc = ::StgCreateDocfileOnILockBytes(m_lpLockBytes,
- STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage);
- if (sc != S_OK)
- {
- VERIFY(m_lpLockBytes->Release() == 0);
- m_lpLockBytes = NULL;
- AfxThrowOleException(sc);
- }
-
- // attempt to create the object
- sc = ::OleCreateFromFile(CLSID_NULL, T2COLE(szFileName),
- IID_IUnknown, OLERENDER_DRAW, NULL, NULL,
- m_lpStorage, (void **)&m_lpObject);
- if ( sc != S_OK )
- {
- TCHAR * lpMsgBuf;
- ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM, NULL,
- ::GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL );
- CString msg( lpMsgBuf );
- msg += _T("nnnThe following file, created inn"
- "Simulation->Plot, may be missing duen"
- "to not doing a File->Save Workspace:nn" );
- msg += szFileName;
- AfxMessageBox( msg, MB_OK );
- ::LocalFree( lpMsgBuf );
- return;
- }
-
- // m_lpObject is currently an IUnknown, convert to IOleObject
- if (m_lpObject != NULL)
- {
- LPUNKNOWN lpUnk = m_lpObject;
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
- }
-
- // cache the IViewObject interface
- m_lpViewObject = QUERYINTERFACE(m_lpObject, IViewObject2);
- if (m_lpViewObject == NULL)
- return;
-
- // setup for advises; we assume that OLE cleans them up properly
- LPADVISESINK lpAdviseSink =
- (LPADVISESINK)GetInterface(&IID_IAdviseSink);
-
- // set up view advise
- VERIFY(m_lpViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpAdviseSink)
- == S_OK);
-
- // the server shows these in its user-interface
- // (as document title and in File Exit menu)
- m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),
- T2COLE(_T("Test")));
-
- // all items are "contained" -- this makes our reference to this object
- // weak -- which is needed for links to embedding silent update.
- OleSetContainedObject(m_lpObject, TRUE);
-
- CHARRANGE cr;
- this->GetSel( cr );
- cr.cpMin = cr.cpMax -1;
- this->SetSel( cr );
-
- REOBJECT reo;
- memset( &reo, 0, sizeof( reo ) );
- reo.cbStruct = sizeof( reo );
- CLSID classID;
- if ( m_lpObject->GetUserClassID( &classID ) != S_OK)
- classID = CLSID_NULL;
- reo.clsid = classID;
- reo.cp = REO_CP_SELECTION;
- reo.poleobj = m_lpObject;
- reo.pstg = m_lpStorage;
- LPOLECLIENTSITE lpClientSite;
- this->GetIRichEditOle()->GetClientSite( &lpClientSite );
- reo.polesite = lpClientSite;
- SIZEL sizel;
- sizel.cx = sizel.cy = 0; // let richedit determine initial size
- reo.sizel = sizel;
- reo.dvaspect = DVASPECT_CONTENT;
- reo.dwFlags = REO_RESIZABLE;
- reo.dwUser = 0;
- HRESULT hr = this->GetIRichEditOle()->InsertObject( &reo );
-
- }
- (2)根据位图句柄创建OleCreateStaticFromData();用这个函数可以把资源中的图片插入到文本框中
- void CRichEditCtrlEx::InsertBitmap(HBITMAP hBitmap)
- {
- STGMEDIUM stgm;
- stgm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle
- stgm.hBitmap = hBitmap;
- stgm.pUnkForRelease = NULL; // Use ReleaseStgMedium
- FORMATETC fm;
- fm.cfFormat = CF_BITMAP; // Clipboard format = CF_BITMAP
- fm.ptd = NULL; // Target Device = Screen
- fm.dwAspect = DVASPECT_CONTENT; // Level of detail = Full content
- fm.lindex = -1; // Index = Not applicaple
- fm.tymed = TYMED_GDI;
- ////创建输入数据源
- IStorage *pStorage;
- ///分配内存
- LPLOCKBYTES lpLockBytes = NULL;
- SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(lpLockBytes != NULL);
- sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
- STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage);
- if (sc != S_OK)
- {
- VERIFY(lpLockBytes->Release() == 0);
- lpLockBytes = NULL;
- AfxThrowOleException(sc);
- }
- ASSERT(pStorage != NULL);
- COleDataSource *pDataSource = new COleDataSource;
- pDataSource->CacheData(CF_BITMAP, &stgm);
- LPDATAOBJECT lpDataObject =
- (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
- ///获取RichEdit的OLEClientSite
- LPOLECLIENTSITE lpClientSite;
- this->GetIRichEditOle()->GetClientSite( &lpClientSite );
- ///创建OLE对象
- IOleObject *pOleObject;
- sc = OleCreateStaticFromData(lpDataObject,IID_IOleObject,OLERENDER_FORMAT,
- &fm,lpClientSite,pStorage,(void **)&pOleObject);
- if(sc!=S_OK)
- AfxThrowOleException(sc);
- ///插入OLE对象
- REOBJECT reobject;
- ZeroMemory(&reobject, sizeof(REOBJECT));
- reobject.cbStruct = sizeof(REOBJECT);
- CLSID clsid;
- sc = pOleObject->GetUserClassID(&clsid);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- reobject.clsid = clsid;
- reobject.cp = REO_CP_SELECTION;
- reobject.dvaspect = DVASPECT_CONTENT;
- reobject.poleobj = pOleObject;
- reobject.polesite = lpClientSite;
- reobject.pstg = pStorage;
- HRESULT hr = this->GetIRichEditOle()->InsertObject( &reobject );
- }
- 4、读取/写入RTF格式字符串
- CRichEditCtrl 提供了两个函数StreamIn()和StreamOut()来实现这个功能,输出的内容包含文本信息和字体信息。我把这两个函数重新包装了一下 ,用GetRTF()把格式文本返回到一个CString变量中SetRTF(CString )实现逆过程。具体代码参看本文附带的工程文件。
-