• Richedit使用大全


    原文地址:http://blog.csdn.net/pcseye/article/details/3903333

    一.常见问题
    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

     

    好文章,收藏先,向作者致敬!

    一.常见问题
    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却没有这个文题,仍然是用楷体显示字母

  • 相关阅读:
    AS将一个项目导入到另一个项目中
    Android Studio出现:Cause: unable to find valid certification path to requested target
    小米手机Toast带app名称
    PopupWindow 点击外部区域无法关闭的问题
    EditText inputType类型整理
    Fragment通过接口回调向父Activity传值
    Android selector一些坑
    Installation failed with message Failed to commit install session 634765663 with command cmd package
    旷视上海研究院机器人方向招聘
    语义SLAM的数据关联和语义定位(四)多目标测量概率模型
  • 原文地址:https://www.cnblogs.com/redrainblog/p/4136198.html
Copyright © 2020-2023  润新知