首 页 ┆ 源码下载 ┆ IT学院 ┆ 字体下载 ┆ 模板下载 ┆ 源码发布 ┆ 广告合作 ┆ 网站地图 ┆ 虚拟主机 ┆ 中文域名
► 设为首页
► 加入收藏
► 联系我们
源码下载 >> ASP源码 | PHP源码 | ASP.net源码 | JSP源码 | CGI源码 | VC/C++源码 | VB源码 | Delphi源码 | Flash源码
文章学院 >> 网络编程 | 网页设计 | 图形图象 | 数据库 | 服务器 | 网络媒体 | 网络安全 | 操作系统 | 办公软件 | 软件开发 | 黑客知识
字体下载 >> 精制字体 | 非英字体 | 艺术字体 | 著名字体 | 哥特式 | 简单字体 | 手写体 | 节假日 | 图案字体 | 精度像素 | 中文字体
模板下载 >> 企业门户 | 数码网络 | 休闲娱乐 | 影视音乐 | 旅游名胜 | 文化艺术 | 电子商务 | 个性展示 | 登陆导航 | Flash模板
►►您当前的位置:源码园 → IT学院 → 软件开发 → VC编程 → 文章内容

类似 MSN 信息发送框的制作(上)

作者:佚名  来源:网上收集  发布时间:2007-3-27 10:14:27

类似 MSN 信息发送框的制作(上)


作者:北方工业大学 阙荣文 (querw)


下载源代码

一、引言
  用 MSN 和 QQ 等聊天的时候,当用户输入特定意义的字符串时,系统回自动用一张小图片替代.比如输入" : ) "系统
会用一个小笑脸代替。我要实现的就是这样一个信息输入框 。这个信息输入框由两部分组成:图案选择器和多功能文本框。本篇介绍多功能文本框。

二、原理简介

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 objectsc = ::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("\n\n\nThe following file, created in\n""Simulation->Plot, may be missing due\n""to not doing a File->Save Workspace:\n\n" );msg += szFileName;AfxMessageBox( msg, MB_OK );::LocalFree( lpMsgBuf );return;}// m_lpObject is currently an IUnknown, convert to IOleObjectif (m_lpObject != NULL){LPUNKNOWN lpUnk = m_lpObject;m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);lpUnk->Release();if (m_lpObject == NULL)AfxThrowOleException(E_OUTOFMEMORY);}// cache the IViewObject interfacem_lpViewObject = QUERYINTERFACE(m_lpObject, IViewObject2);if (m_lpViewObject == NULL)return;// setup for advises; we assume that OLE cleans them up properlyLPADVISESINK lpAdviseSink =(LPADVISESINK)GetInterface(&IID_IAdviseSink);// set up view adviseVERIFY(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 sizereo.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 handlestgm.hBitmap = hBitmap;stgm.pUnkForRelease = NULL; // Use ReleaseStgMediumFORMATETC fm;fm.cfFormat = CF_BITMAP;    // Clipboard format = CF_BITMAPfm.ptd = NULL;       // Target Device = Screenfm.dwAspect = DVASPECT_CONTENT;   // Level of detail = Full contentfm.lindex = -1;       // Index = Not applicaplefm.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的OLEClientSiteLPOLECLIENTSITE 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 )实现逆过程。具体代码参看本文附带的工程文件。

    三、到此,这个多功能文本框就已经基本能满足我的要求了。但是如何选择表情符号? 如何自动替换? 还是个问题。(待续)

    [] [返回上一页] [打 印]
    • 上一篇文章:类似 MSN 带转义字符的信息发送框的制作(下)
    • 下一篇文章:多功能标签CLabelEx

    • 相关文章:
    • [图文]类似 MSN 信息发送框的制作(上)
    • [图文]类似 MSN 带转义字符的信息发送框的制作(下)
    • [组图]菜鸟绝技把老板搞“懵” 工作上网两不误--快把...
    • 类似 MSDN CSDN 左边导航树效果的实现
    关于本站 - 网站帮助 - 广告合作 - 下载声明 - 友情连接 - 网站地图 - 源码发布
    Copyright © 2003-2009 Ymyasp.Com. All Rights Reserved .
    备案序号:粤ICP备07029071号