文本版|topic 高级搜索
   名人堂 帮助 论坛制度 意见反馈 | 首页 博客 周新贴 专题 求职 读书
RSS 底部
 
社区导航: 专家门诊   网络技术   操作系统   数据库   程序设计   系统应用   考试认证   CIO及信息化   站长交流   综合交流   下载基地  51CTO产品服务 设为首页 | 收藏本站
51CTO技术论坛» C/C++ » c++新手求助:如何用richedit输入表情或图片       [ 打印]  [ 订阅]  [ 收藏]  [ 推荐给朋友]   [ 本帖文本页]

论坛跳转:
     
标题: c++新手求助:如何用richedit输入表情或图片  ( 查看:570  回复:6 )   
 该主题悬赏的20无忧币已被全部领完 
 
bone3360
技术员  点击可查看详细



十二生肖之狗   水瓶座   行业勋章   技术勋章   诚信兄弟  
帖子 86
精华 0
无忧币 158
积分 205
阅读权限 30
来自 (保密)
注册日期 2006-11-10
最后登录 2008-10-8 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2008-1-23 11:45   标题:c++新手求助:如何用richedit输入表情或图片
上一帖 |
一个初学C++ 的人诚心求教,我是个仅了解C++基本语法的人,公司现在要求我实现一个程序,要求:实现一个HTML的编辑控件,可以设置字体/颜色,可以输入表情/图片。
就是类似QQ的聊天对话框那种。公司要我这周末给出完整程序。貌似要用到richedit这个玩意。哪位大侠帮忙下啊,贴点代码或者类似代码都可以,让我参考下,或者提供点思路也行啊!

[ 本帖最后由 bone3360 于 2008-1-23 11:48 编辑 ]



论坛活动:测测你对IT技术大会的了解指数(赠微软礼品、无忧币)
2008-1-23 11:451楼
[ 顶部 ]
 
hagejid
副版主  点击可查看详细


十二生肖之猴   金牛座   行业勋章   技术勋章   诚信兄弟  
帖子 408
精华 0
无忧币 2144
积分 494
阅读权限 140
注册日期 2007-4-3
最后登录 2008-10-10 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2008-1-23 13:02  该回复被 bone3360 奖励 20 点无忧币
此回复于2008-02-05 17:43被 ribut9225 评为最佳答案

LPUNKNOWN AFXAPI _AfxQueryInterface(LPUNKNOWN lpUnknown, REFIID iid)
{
        ASSERT(lpUnknown != NULL);

        LPUNKNOWN lpW = NULL;
        if (lpUnknown->QueryInterface(iid, (LPLP)&lpW) != S_OK)
                return NULL;

        return lpW;
}

void CSimulationReportView::InsertPlotBitmap()
{
        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);
        }

        CWorkSpace * pWorkSpace = GetDocument()->GetWorkSpace();
    if ( !pWorkSpace )
      return;
        CString plotName;
        plotName.LoadString( IDS_PLOT_FILENAME );
    CString szFileName( pWorkSpace->GetWkspTempDirectory() +
                                                _T("\\") + plotName );

        // 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("\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 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(GetDocument()->GetTitle()));

        // 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;
        m_reportCtrl.GetSel( cr );
        cr.cpMin = cr.cpMax -1;
        m_reportCtrl.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;
        m_reportCtrl.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 = m_reportCtrl.GetIRichEditOle()->InsertObject(&reo);
}



附件(查看下载说明): [别人的代码,只是做BMP的,改改应该可以显示其他的.] rtfbitmap.zip (2008-1-23 13:02,大小:37.45 K)
该附件被下载 5 次     您下载该主题帖内所有附件同时将被扣掉2点无忧币  查看分数政策说明




C到底该不该学,看看这个就明白
2008-1-23 13:022楼
[ 顶部 ]
 
bone3360
技术员  点击可查看详细



十二生肖之狗   水瓶座   行业勋章   技术勋章   诚信兄弟  
帖子 86
精华 0
无忧币 158
积分 205
阅读权限 30
来自 (保密)
注册日期 2006-11-10
最后登录 2008-10-8 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2008-1-23 14:08 
多谢了!想问下,能不能稍作解释下呢?有些看不大懂那!不好意思哦!我是个菜鸟!



论坛活动:测测你对IT技术大会的了解指数(赠微软礼品、无忧币)
2008-1-23 14:083楼
[ 顶部 ]
 
hagejid
副版主  点击可查看详细


十二生肖之猴   金牛座   行业勋章   技术勋章   诚信兄弟  
帖子 408
精华 0
无忧币 2144
积分 494
阅读权限 140
注册日期 2007-4-3
最后登录 2008-10-10 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2008-1-23 21:14 
先尝试编译一下吧,我看了一下,里边

BOOL CRTFBitmapDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
}
// Set the icon for this dialog.  The framework does this automatically
//  when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE);   // Set big icon
SetIcon(m_hIcon, FALSE);  // Set small icon

RECT rect;
GetClientRect( &rect );
m_reportCtrl.Create( WS_VISIBLE | WS_CHILD | ES_MULTILINE |
       ES_WANTRETURN | WS_HSCROLL | WS_VSCROLL |
       ES_AUTOHSCROLL | ES_AUTOVSCROLL,
       rect, this, RTF_CTRL_ID );
m_reportCtrl.ReplaceSel( _T("Here is a line of text.\n\n\n") );
InsertPlotBitmap();
m_reportCtrl.ReplaceSel( _T("\n\nHere is another line of text.") );

return TRUE;  // return TRUE  unless you set the focus to a control
}
最后三个函数调用就是插入文字和图片的,你可以试一下用什么方法来修改成自己的.
还有一个就是在RICHEDIT里边使用OLE
以上信息都是用百度搜到的
像我这种三脚猫程序员,搜索和盗用别人的代码是很重要的工作,呵呵
下面再给你一些资料,就是QQ,MSN等显示表情图片有关的
压缩文件里的AxImageDemoBin.RAR只有 ImageOle.dll 有用
配合里边的英文的网页,应该就可以做出显示表情图片

附件(查看下载说明): ole显示图片.rar (2008-1-23 21:14,大小:709.71 K)
该附件被下载 4 次     您下载该主题帖内所有附件同时将被扣掉2点无忧币  查看分数政策说明




C到底该不该学,看看这个就明白
2008-1-23 21:144楼
[ 顶部 ]
 
basset
新新人类  点击可查看详细



帖子 163
精华 0
无忧币 -2
积分 155
阅读权限 20
注册日期 2007-12-19
最后登录 2008-8-1 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2008-2-2 09:02 
ddddddddddddddddddddddddddddddddddddddddddddd



论坛活动:测测你对IT技术大会的了解指数(赠微软礼品、无忧币)
2008-2-2 09:025楼
[ 顶部 ]
 
ribut9225
主版主  点击可查看详细


开坛元老   内阁大臣   诚信兄弟   主版主专用   巨蟹座  
帖子 3113
精华 1
无忧币 5989
积分 4101
阅读权限 150
来自 (保密)
注册日期 2006-6-22
最后登录 2008-10-10 离线

[查看资料]  [发短消息]  [Blog
  QQ       
发表于:2008-2-2 09:58 
转自:http://www.vckbase.com/document/viewdoc/?id=1290

一个在RichEdit中添加表情图象的类

作者:中原工学院 刘翔

下载源代码

说明
  本文根据VC知识库《在线杂志》的第30期的一篇文章:《类似 MSN 信息发送框的制作》,介绍了一个可以在RichEdit中添加表情图象的类CFaceEdit。 以下是使用这个类的程序截图:


一个在RichEdit中添加表情图象的类

作者:中原工学院 刘翔

下载源代码

说明
  本文根据VC知识库《在线杂志》的第30期的一篇文章:《类似 MSN 信息发送框的制作》,介绍了一个可以在RichEdit中添加表情图象的类CFaceEdit。 以下是使用这个类的程序截图:


图一 CFaceEdit类的使用

使用方法
  我们可以先看一下它的使用方法:

//将对话框类成员变量由CRichEditCtrl改为CFaceEdit
CFaceEdit m_FaceEdit;

//自定义一组表情
CString pSymbol[] = {"", "", ";)", ":0", ";-)"};

//表情对应的图象ID
UINT nIDBmp[] =  {    IDB_BITMAP1, IDB_BITMAP2, IDB_BITMAP3, IDB_BITMAP4, IDB_BITMAP5};
m_FaceEdit.Init(5, pSymbol, nIDBmp);
......
m_FaceEdit.SetText("Visual Studio 包括许多示例,用以说明开发人员为.NET 平台;)创建的应用程序:-) 。");

也可以以位图文件的形式导入位图:CString sBmpFile[] = {"res\\kid.bmp", "res\\sad.bmp", "res\\showoff.bmp", "res\\quip.bmp", "res\\maze.bmp"};
m_FaceEdit.Init(5, pSymbol, sBmpFile);
...
m_FaceEdit.SetText("Visual Studio 包括许多示例,用以说明开发人员为.NET 平台;)创建的应用程序:-) 。");

  插入图象的主要原理,是由《类似 MSN 信息发送框的制作》一文中提供的InsertBitmap()函数实现的。该函数可以通过指定图象的ID插入图象,或通过图象文件的路径来插入图象。

  那么如何将文本中的字符表情,如::)、;-) 等翻译成图象呢?例如,对于字符串:
"Visual Studio 包括许多示例:),用以说明开发人员为.NET 平台;)创建的应用程序:-)。"

翻译之后,变成:
"Visual Studio 包括许多示例,用以说明开发人员为.NET 平台创建的应用程序。"

如何实现呢?
  在使用InsertBitmap()函数插入图象时,我发现只要先将RichEdit中的某一段文本内容选中,然后再调用InsertBitmap()函数,便可实现将选定内容替换成图象。如:
"Visual Studio 包括许多示例:),用以说明开发人员为.NET 平台;)创建的应用程序:-)。"

再调用InsertBitmap()函数:
"Visual Studio 包括许多示例,用以说明开发人员为.NET 平台;)创建的应用程序:-)。"

  后面的符号只要使用相同的方法处理即可。明白了这一点,想要实现转换图象的功能也就不难了。我们可以使用CRichEditCtrl::SetSel()来实现,不过在此之前,要对各表情字符的一些信息,如位置、表情类型、长度等进行保存,以下是翻译文本的函数的代码: /*-----------------------------------------------------------------------------
*     函数名     :SetTextWithFace
*
*     功能 :实现插入图象的算法函数。
*     实现原理:
                假设:CString pSymbol[] = {":)", "", "#", "AK47", ":-)"};
                先将包括表情符号的文本( 如:"haha:)" )直接显示到CRichEditCtrl中,
                然后选定其中的表情符号( 如:":)" ),再调用InsertBitmap函数
                实现插入,详见注释
-----------------------------------------------------------------------------*/
void CFaceEdit::SetTextWithFace(CString str)
{
       CString *pstr = new CString[m_nfaceCount];
       for(int n = 0; n<m_nfaceCount; n++)
       {
              pstr[n] = m_pSymbol[n];
       }

       SetWindowText(str);

       int nFaceCount = 0;           //str中共有多少个表情。
       stFace faceNode;        //faceNode中存储的是在哪个位置插入,插入哪一个表情。
       vector <stFace> vecFace;  //vecFace[0]表示第一个表情的位置和型号、vecFace[1]表示第二的位置和型号…

       /* ************************************************************************
       *           第一步:
       *           在str中查找表情字符(pstr)。
       *
       *           如str = "我们的:-)明天更美好AK47,一定:-)非常美好#。"。那么以下操作将生成四个
       *           stFace(定义见FaceEdit.h)结点,它们的值分别为{3, 3, 3}, {15, 3, 4}, {10, 1, 3}, {21, 0, 1}。
       *           使用vector数组vecFace进行存储。
       *
       * *************************************************************************/
       for(int i=0, m = -1; i<m_nfaceCount; i++)
       {
              //关键的一步:查找宽字符,汉字算一个字符。放在循环中,就可以查找重复的字符。
              while(1)
              {
                     m = (int)str.Find(pstr, m + 1);       //循环搜索
                     if(m != -1)
                     {
                            faceNode.nPos = m;
                            faceNode.nFaceIndex = i;
                            faceNode.nLength = (int)pstr.GetLength();

                            vecFace.push_back(faceNode);
                            nFaceCount++;
                     }
                     else
                     {
                            break;
                     }
              }
       }     //查找完毕
       if(nFaceCount==0)             //在str中没找到一个表情,下面就无需插入表情了。
              return;

       delete []pstr;
       /* ************************************************************************
       * 第二步:
       * 使用泛型算法sort进行排序。
       *
       * 上面的四个结点:A:{3, 3, 3}, B:{15, 3, 4}, C:{10, 1, 3}, D:{21, 0, 1},显然这不是按照
       * 顺序排的,这里应该按表情在文本中出现的次序依次替换,否则替换算法将会非常麻烦。
       *
       * *************************************************************************/
       bool less_than(stFace &face1, stFace &face2);     //声明排序的"条件"函数
       //详见我的ObjectSort工程中的说明。可参见《Essential C++》P84
       sort(vecFace.begin(), vecFace.end(), less_than);


       /* ***********************************************************************
       * 第三步:
       * 调整各表情字符位置(nPos)。
       *
       * 排序之后各结点:A:{3, 3, 3}, C:{10, 1, 3}, B:{15, 3, 4}, D:{21, 0, 1}。
       * 经过摸索,发现这样一个规律:
       * 本结点应该向前挪的值(prev) = 上一个表情的长度(prevLength) - 1 + 上一个结点应该向前挪的值(prev)
       *
       * 如:
                     CString pSymbol[] = {":)", "", "#", "AK47", ":-)"};
                     序号:?                    0     1?    2?  ?3?   ?4

                     "我们的:-)明天更美好AK47,一定:-)非常美好#。"
                     位置: 3            11        18         25

                     "#"(25, 2, 1)    "AK47"(11, 3, 4)  ":-)"(3, 4, 3)   ":-)"(18, 4, 3)
                         ~~                      ~~                ~~                  ~~
                     排序后:
                     ":-)"(3, 4, 3)   "AK47"(11,3, 4)   ":-)"(18, 4, 3)    "#"(25, 2, 1)
                           ~~                     ~~                ~~                  ~~
                     处理后:
                     ":-)"(3, 4, 3)   "AK47"(9, 3, 4)   ":-)"(13, 4, 3)    "#"(18, 2, 1)
                           ~~                     ~~                ~~                  ~~
                          少了0                  少了2            少了5          少了7
                                                 3-1+0            4-1+2          3-1+5
       *
       *
       * *********************************************************************/
       for(int t = 0, prevLength = 0, prev = 0; t<nFaceCount; t++)
       {
              vecFace[t].nPos -= prev;
              prevLength = vecFace[t].nLength;
              prev = prevLength - 1 + prev;
       }

       /* ********************************************************************
       * 第四步:
       * 下面插入表情。
       *
       * 调用InsertBitmap插入各处理完成的各结点A:{3, 3], C:{9, 1}, B:{13, 3}, D:{18, 0}。
       *
       * *********************************************************************/
       try
       {
              for(int j=0; j<nFaceCount; j++)
              {
                     stFace faceNode = vecFace[j];
                     InsertBitmap(faceNode);
              }
       }

       catch(char *sError)
       {
              MessageBox(sError, "HBITMAP", MB_OK | MB_ICONERROR);
       }
}               
注意事项
  本类有两个版本,一个是针对RichEdit 1.0的,另一个是针对RichEdit 2.0的。它们的区别是,前者把一个汉字作为两个字节处理,而后者把一个汉字作为一个字节处理。请读者区分使用。



用户必读,51CTO积分系统调整通知
2008-2-2 09:586楼
[ 顶部 ]
 
bone3360
技术员  点击可查看详细



十二生肖之狗   水瓶座   行业勋章   技术勋章   诚信兄弟  
帖子 86
精华 0
无忧币 158
积分 205
阅读权限 30
来自 (保密)
注册日期 2006-11-10
最后登录 2008-10-8 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2008-2-2 10:51 
谢谢!但这个也现在也还达不到我的要求,位图的我已经实现了,但是插入gif或者是jpg等格式的话,就只有一个框在那,图片无法显示。我现在想实现的是这样:可以插入各种图片,包括gif,jpg等,当然,gif不一定要有动画效果就是了!



论坛活动:测测你对IT技术大会的了解指数(赠微软礼品、无忧币)
2008-2-2 10:517楼
[ 顶部 ]
     
论坛跳转:  

| | |

| | |

| | |

标记已读 · 删除论坛Cookies · 文本版 · WAP
 
| 诚征版主 | 版主堂 | 意见建议 | 大史记 | 论坛地图
Copyright©2005-2008 51CTO.COM  Powered by Discuz!
本论坛言论纯属发布者个人意见,不代表51CTO网站立场!如有疑义,请与管理员联系。
京ICP备05051492号