下面链接可以下载全文:

https://download.csdn.net/download/h3974/42496015

一.多格式编辑控件

Rich Edit编辑控件可以为文本设置字符和段落格式,并且可以嵌入组件对象模型(COM对象)。使用户能够输入,编辑,打印和保存文本。

Rich Edit编辑控件的版本:

RichEdit编辑控件版本    DLL                 窗口类
1.0                                  Riched32.dll    RICHEDIT_CLASS
2.0                                  Riched20.dll    RICHEDIT_CLASS
3.0                                  Riched20.dll    RICHEDIT_CLASS
4.1                                  Msftedit.dll       MSFTEDIT_CLASS

RichEdit编辑控件快捷键:

快捷键                           说明
Shift + Backspace         生成LRM / LRM
Ctrl+Tab                         插入一个水平制表符。
Ctrl+A                            全选。
Ctrl+E                            居中。
Ctrl+R                            右对齐。
Ctrl+L                            左对齐。
Ctrl+C                            复制。
Ctrl+V                            粘贴。
Ctrl+X                            剪切。
Ctrl+Z                            撤消。
Ctrl+Y                            重做。
Ctrl+Shift+"="                上标。
Ctrl+"="                         下标。
Ctrl+1                            行距= 1行。
Ctrl+2                            行距= 2行。
Ctrl+5                            行距= 1.5行。
Ctrl+Insert                     复制。
Shift+Insert                    粘贴。
Ctrl+左箭头键                将光标向左移动一个单词。
Ctrl+右箭头键                将光标向右移动一个单词。
Ctrl+Home                     移到文档的开头。
Ctrl+End                        移至文档末尾。
Ctrl+Page Up                移动至当前显示文本的第1行的起始位置。
Ctrl+Page Down            移动至当前显示文本的最后一行的起始位置。
Ctrl+Delete                     删除下一个单词。
Shift+Delete                   剪切所选字符。
Esc                                停止拖放。在拖放文本时。
Alt+Esc                          更改活动的应用程序。将另一个程序的窗口,且该窗口最接近顶层,置于前台。
Alt+X                              将插入点之前的Unicode十六进制值转换为相应的Unicode字符。
Alt+Shift+X                     将插入点之前的Unicode字符转换为相应的Unicode十六进制值。
Ctrl+Shift+A                   将选中的所有字符转换为大写。
Ctrl+Shift+L                    在行首添加伪圆点。

二.用代码创建多格式编辑控件

1.声明CRichEditCtrl类的成员变量:
    CRichEditCtrl richedit;

2.在对话框OnCreate函数中,创建RichEdit控件:
int CMFCApplication2Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialogEx::OnCreate(lpCreateStruct) == -1)
        return -1;
    richedit.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL| ES_DISABLENOSCROLL|ES_MULTILINE | ES_WANTRETURN| ES_SAVESEL,CRect(10, 10, 350, 400), this, IDD_RICHEDITCTRL);
    //
    richedit.CreateEx(WS_EX_ACCEPTFILES,
        WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE|ES_WANTRETURN,
        CRect(10, 10, 300, 400), this, IDD_RICHEDITCTRL);
    //创建扩展样式RichEdit编辑控件,可接受拖放文件
    return 0;
}

3.在资源头文件中定义标识:
    #define IDD_RICHEDITCTRL          1001

4.在对话框DoDataExchange函数中,添加如下代码:
void CMFCApplication2Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDD_RICHEDITCTRL, richedit);
}

创建Rich Edit版本4.1控件
1.在对话框头文件中,声明CRichEditCtrl类指针,声明RichEdit控件窗口句柄:
public:
    CRichEditCtrl  richedit;

2.添加对话框的OnCreate函数,在函数中创建Rich Edit版本4.1控件:
int CMFCApplication1Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialogEx::OnCreate(lpCreateStruct) == -1)
        return -1;
    LoadLibrary(TEXT("Msftedit.dll"));
    HWND hwndEdit = CreateWindowEx(0, MSFTEDIT_CLASS, TEXT(""),
        ES_MULTILINE | ES_WANTRETURN | WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
        10, 10, 400, 300,GetSafeHwnd(), NULL, theApp.m_hInstance, NULL);
    if (hwndEdit != NULL)
        richedit.SubclassWindow(hwndEdit);
    return 0;
}

3.打开资源头文件,定义标识:
    #define IDD_RICHEDITCTRL                                1000

4.在对话框DoDataExchange函数中,添加如下代码:
void CMFCApplication2Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDD_RICHEDITCTRL, richedit);
}

三.多格式编辑控件的初始化

设置多格式编辑控件的背景色:
     SetBackgroundColor(FALSE,RGB(255,193,132));//参数1为TRUE时,将背景颜色设置为系统值,忽略参数2;为FALSE时,参数2指定背景色

设置多格式编辑控件的显示矩形:
    CRect rect;
    richedit.GetRect(&rect);//获取当前的显示矩形
    rect.DeflateRect(20,0,20,0);//将矩形左右各收缩20像素
    richedit.SetRect(&rect);//设置多格式编辑控件新的显示矩形

设置多格式编辑控件的默认字符格式:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    cf.dwMask = CFM_FACE | CFM_SIZE | CFM_COLOR | CFM_WEIGHT | CFM_CHARSET;
    wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("微软雅黑"), LF_FACESIZE);//设置字体名称为微软雅黑
    cf.yHeight = 14 * 20;//设置字体大小为14点
    cf.crTextColor = RGB(255, 0, 0);//设置字体颜色为红色
    cf.bCharSet = GB2312_CHARSET;//设置中文字符集
    cf.wWeight = 400;//设置字体粗细为正常
    cf.dwEffects = 0;
    richedit.SetDefaultCharFormat(cf);//设置RichEdit编辑控件默认字符格式

如果为多行多格式编辑控件添加了水平滚动条,还需为编辑控件指定行的宽度:
    CDC* pDC = richedit.GetDC();
    richedit.SetTargetDevice(pDC->m_hDC, MulDiv(500, 1440, pDC->GetDeviceCaps(LOGPIXELSX)));
    //设置编辑控件行的宽度为500像素。GetDeviceCaps(LOGPIXELSX)函数获取编辑控件在水平方向每英寸的像素数
    //只在设置的编辑控件行宽度大于显示矩形时,水平滚动条方可显示
    ReleaseDC(pDC);
    或
    CRect rect;
    richedit.GetRect(rect);//获取显示矩形
    CDC* pDC = richedit.GetDC();
    richedit.SetTargetDevice(pDC->m_hDC, MulDiv(rect.Width()+100, 1440, pDC->GetDeviceCaps(LOGPIXELSX)));
    //设置编辑控件行宽度为,比显示矩形大100像素
    ReleaseDC(pDC);

设置多格式编辑控件自动检测链接:
    richedit.SetAutoURLDetect(TRUE);//打开自动检测链接
    关闭自动检测链接:
    richedit.SetAutoURLDetect(FALSE);//关闭自动检测链接
    自动检测链接的多格式编辑控件,对于带有以下前缀的文本显示为链接:
        http:    file:   mailto:    ftp:    https:    gopher:    nntp:    prospero:    telnet:    news:    wais:

四.设置字符格式

注:windows8.1 windows10 RichEdit4.1 设置字体格式需指定字符集。
1.指定字体名称,字体大小,字体颜色,字体粗细:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    cf.dwMask = CFM_FACE | CFM_SIZE | CFM_COLOR | CFM_WEIGHT | CFM_CHARSET;
    wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("微软雅黑"), LF_FACESIZE);//设置字体名称为微软雅黑
    cf.yHeight = 12 * 20;//设置字体大小为12点
    cf.crTextColor = RGB(255, 0, 0);//设置字体颜色为红色
    cf.wWeight = 400;//400为正常字体
    cf.dwEffects = 0;//字符效果设置为0
    cf.bCharSet = GB2312_CHARSET;//设置中文字符集
    richedit.SetWordCharFormat(cf);//设置当前字符格式
    SetWordCharFormat函数将选中文本设置为指定的字符格式,如果没有选中文本,设置插入符位置的字符格式。

2.设置字体为斜体:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    cf.dwMask = CFM_FACE | CFM_SIZE | CFM_COLOR | CFM_WEIGHT| CFM_ITALIC | CFM_CHARSET;
    wcsncpy_s(cf.szFaceName, LF_FACESIZE, _T("微软雅黑"), LF_FACESIZE);//设置字体名称为微软雅黑
    cf.yHeight = 12 * 20;//设置字体大小为12点
    cf.crTextColor = RGB(255, 0, 0);//设置字体颜色为红色
    cf.wWeight = 400;//400为正常字体
    cf.dwEffects = CFE_ITALIC;//设置字体为斜体
    cf.bCharSet = GB2312_CHARSET;//设置中文字符集
    richedit.SetWordCharFormat(cf);//设置当前字符格式

3.将所选文本显示为大写:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    richedit.GetSelectionCharFormat(cf);//获取所选文本的字符格式
    cf.dwEffects |= CFE_ALLCAPS;//添加CFE_ALLCAPS标志(以大写显示字符)
    richedit.SetSelectionCharFormat(cf);//设置所选文本的字符格式

4.为所选文本添加删除线:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    richedit.GetSelectionCharFormat(cf);//获取所选文本的字符格式
    cf.dwEffects |= CFE_STRIKEOUT;//添加CFE_STRIKEOUT标志(删除线)
    richedit.SetSelectionCharFormat(cf);//设置所选文本的字符格式

5.为所选文本添加下划线:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    richedit.GetSelectionCharFormat(cf);
    cf.dwEffects |= CFE_UNDERLINE;
    richedit.SetSelectionCharFormat(cf);

6.将所选文本设置为受保护的文本:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    richedit.GetSelectionCharFormat(cf);
    cf.dwEffects |= CFE_PROTECTED;
    richedit.SetSelectionCharFormat(cf);
    更改受保护的文本,会导致RichEdit编辑控件发送EN_PROTECTED通知。
    要使RichEdit编辑控件发送EN_PROTECTED通知,必须为RichEdit编辑控件设置事件掩码:
    LONG nMask=richedit.GetEventMask();
    nMask |= ENM_PROTECTED;
    richedit.SetEventMask((DWORD)nMask);

7.为选中文本添加背景色:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    richedit.GetSelectionCharFormat(cf);//获取所选文本的字符格式
    cf.dwMask |= CFM_BACKCOLOR;
    cf.dwEffects = 0;
    cf.crBackColor = RGB(200, 105, 50);//指定背景色
    richedit.SetSelectionCharFormat(cf);//设置所选文本的字符格式

五.设置段落格式

1.在每行的开头添加行号:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_NUMBERING| PFM_NUMBERINGSTYLE;
    pf.wNumbering = PFN_ARABIC;//PFN_ARABIC行号为阿拉伯数字
    pf.wNumberingStyle = PFNS_PERIOD;//行号后面加句点
    richedit.SetParaFormat(pf);

2.设置首行缩进,下面代码将段落的第一行缩进30像素:
    CDC* pDC = richedit.GetDC();
    int indent = MulDiv(30, 1440, pDC->GetDeviceCaps(LOGPIXELSX));//将30像素转换为以1440分之一英寸为单位的值
    ReleaseDC(pDC);
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_STARTINDENT| PFM_OFFSET;
    pf.dxStartIndent = indent;//设置缩进量为30像素
    pf.dxOffset = -indent;//从第2行开始,恢复到缩进前的位置
    richedit.SetParaFormat(pf);

3.段落左对齐:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_ALIGNMENT;
    pf.wAlignment = PFA_LEFT;
    richedit.SetParaFormat(pf);

4.段落右对齐:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_ALIGNMENT;
    pf.wAlignment = PFA_RIGHT;
    richedit.SetParaFormat(pf);

5.段落居中对齐:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_ALIGNMENT;
    pf.wAlignment = PFA_CENTER;
    richedit.SetParaFormat(pf);

6.指定行间距:
    单倍行间距:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_LINESPACING;
    pf.dyLineSpacing = 0;
    pf.bLineSpacingRule = 0;
    richedit.SetParaFormat(pf);
    1.5倍行间距:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_LINESPACING;
    pf.dyLineSpacing = 0;
    pf.bLineSpacingRule = 1;
    richedit.SetParaFormat(pf);
    2倍行间距:
    PARAFORMAT2 pf;
    pf.cbSize = sizeof(PARAFORMAT2);
    pf.dwMask = PFM_LINESPACING;
    pf.dyLineSpacing = 0;
    pf.bLineSpacingRule = 2;
    richedit.SetParaFormat(pf);

六.在多格式编辑控件中查找文本

CHARRANGE SelRange;
    richedit.GetSel(SelRange);//获取Rich Edit控件的当前选择
    FINDTEXTEX ft;
    ft.lpstrText = _T("要查找的文本");//指定要查找的文本
    ft.chrg.cpMin = SelRange.cpMax;//指定查找的起始位置,为当前选择的结束位置的下一个字符
    ft.chrg.cpMax = -1;//查找的结束位置,为控件中文本的末尾
    LONG find = richedit.FindText(FR_DOWN, &ft);//进行查找。参数1指定查找方向
    if (find != -1)//如果查找到
    {
        richedit.SetSel(ft.chrgText);//选中查找到的文本
        richedit.HideSelection(FALSE, TRUE);
    }

七.为多格式编辑控件添加右键菜单

1.以CRichEditCtrl为基类,添加派生类CMyRichEditCtrl类;在CMyRichEditCtrl类中添加OnContextMenu函数,在函数中创建弹出菜单:
void CMyRichEditCtrl::OnContextMenu(CWnd* pWnd, CPoint point)
{
    CMenu menu;
    menu.LoadMenu(IDR_MENU1);
    CMenu* pmenu = menu.GetSubMenu(0);
    pmenu->TrackPopupMenu(TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, GetParent());
    //在Win8,win10系统下,不可指定菜单父窗口为多格式编辑控件(this),因为菜单弹出后会更改插入符的位置
    //本示例指定菜单父窗口为多格式编辑控件的父对话框
}

或在CMyRichEditCtrl类中添加OnRButtonDown函数,在函数中创建弹出菜单:
void CMyRichEditCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
    CMenu menu;
    menu.LoadMenu(IDR_MENU1);
    CMenu* pmenu = menu.GetSubMenu(0);
    ClientToScreen(&point);//需将point转换为屏幕坐标
    pmenu->TrackPopupMenu(TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, GetParent());
    CRichEditCtrl::OnRButtonDown(nFlags, point);
}

2.在RichEdit编辑控件的父对话框头文件中,包含CMyRichEditCtrl类头文件,修改RichEdit编辑控件的变量声明:
#include "MyRichEditCtrl.h"

CMyRichEditCtrl richedit;

八.将多格式编辑控件内容输出到磁盘文件

1.声明回调函数:
    DWORD CALLBACK MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb);

2.定义回调函数:
DWORD CALLBACK MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
    CFile* pFile = (CFile*)dwCookie; pFile->Write(pbBuff, cb);
    *pcb = cb;
    return 0;
}

3.将多格式编辑控件内容输出到文件:
    CFile file(_T("D:\\1.rtf"),CFile::modeCreate|CFile::modeWrite);  //声明文件对象
    EDITSTREAM es;
    es.pfnCallback = MyStreamOutCallback;//指定流输出使用的回调函数
    es.dwCookie = (DWORD)&file;//将文件指针传递给dwCookie参数
    richedit.StreamOut(SF_RTF, es);//以RTF格式输出

将多格式编辑控件内容输出到内存文件

1.声明字节数组,它为全局变量:
    BYTE m_byte[10000000];//声明使用的内存,要求从RichEdit输出的文件小于声明的内存大小(10M字节)

2.声明回调函数:
    DWORD CALLBACK MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb);

3.定义回调函数:
DWORD CALLBACK MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
    CFile* pFile = (CFile*)dwCookie;
    if ((pFile->GetPosition()+cb) > 10000000)return 1;
    //如果从RichEdit输出的文件大于预先声明的内存大小(10M字节),返回1,报告错误并终止输出
    pFile->Write(pbBuff, cb);
    *pcb = cb;
    return 0;
}

4.将多格式编辑控件内容输出到内存文件:
    CMemFile F;//声明内存文件对象
    memset(m_byte, 0, 10000000);//将内存数组每个字节设置为0
    F.Attach(m_byte, 10000000);//将内存附加到内存文件对象
    EDITSTREAM es;
    es.pfnCallback = MyStreamOutCallback;//指定流输出使用的回调函数
    es.dwCookie = (DWORD)&F;//将内存文件指针传递给dwCookie参数
    es.dwError=0;
    richedit.StreamOut(SF_RTF, es);//以RTF格式输出
    if (es.dwError)//dwError是回调函数的返回值,如果不为0,报告错误
        MessageBox(_T("文件过大,写入失败!"));

九.读取磁盘文件输入到多格式编辑控件

1.声明回调函数:
    DWORD CALLBACK readFunction(DWORD dwCookie, LPBYTE lpBuf, LONG nCount, LONG* nRead);

2.定义回调函数:
DWORD CALLBACK readFunction(DWORD dwCookie, LPBYTE lpBuf, LONG nCount, LONG* nRead)
{
    CFile* fp = (CFile*)dwCookie;
    *nRead = fp->Read(lpBuf, nCount);
    return 0;
}

3.读取磁盘文件输入到RichEdit编辑控件:
    CFile file(_T("D:/1.rtf"), CFile::modeRead);
    EDITSTREAM es;
    es.pfnCallback = readFunction;
    es.dwCookie = (DWORD)&file;
    richedit.StreamIn(SF_RTF, es);

读取内存文件输入到多格式编辑控件

1.声明回调函数:
    DWORD CALLBACK readFunction(DWORD dwCookie, LPBYTE lpBuf, LONG nCount, LONG* nRead);

2.定义回调函数:
DWORD CALLBACK readFunction(DWORD dwCookie, LPBYTE lpBuf, LONG nCount, LONG* nRead)
{
    CFile* fp = (CFile*)dwCookie;
    *nRead = fp->Read(lpBuf, nCount);
    return 0;
}

3.读取内存文件输入到RichEdit编辑控件:
    CMemFile file;
    file.Attach(m_byte, Len);//m_byte为BYTE*类型,Len为内存文件的长度(字节)
    EDITSTREAM es;
    es.pfnCallback = readFunction;
    es.dwCookie = (DWORD)&file;
    richedit.StreamIn(SF_RTF, es);

十.打印多格式编辑控件内容

CPrintDialog dlg(FALSE);
    if (dlg.DoModal() == IDCANCEL)return;
       HDC hdc = dlg.GetPrinterDC();//获取所选打印机DC

CRect rect;
    rect.Left=左边距;rect.top=上边距;rect.right=右边距;rect.bottom=下边距;//单位毫米
    CDC ThePrintDC;
    ThePrintDC.Attach(hdc);

long lPageWidth = ::MulDiv(ThePrintDC.GetDeviceCaps(PHYSICALWIDTH),
        1440, ThePrintDC.GetDeviceCaps(LOGPIXELSX));
    long lPageHeight = ::MulDiv(ThePrintDC.GetDeviceCaps(PHYSICALHEIGHT),
        1440, ThePrintDC.GetDeviceCaps(LOGPIXELSY));

CRect r1(0, 0, lPageWidth, lPageHeight);//页面矩形
    int l, t, r, b;
    l = (int)((rect.left * 1440) / 25.4); t = (int)((rect.top * 1440) / 25.4); r = (int)((rect.right * 1440) / 25.4); b = (int)((rect.bottom * 1440) / 25.4);
    CRect r2(r1.left + l, r1.top + t, r1.right - r, r1.bottom - b);//打印矩形

int ErrorStatus = 0;
    long CharRange = richedit.GetTextLength();
    long LastChar = 0;

DOCINFO di;
    ::ZeroMemory(&di, sizeof(DOCINFO));
    di.cbSize = sizeof(DOCINFO);
    di.lpszDocName = _T("");

ThePrintDC.StartDoc(&di);

FORMATRANGE fr;
    ::ZeroMemory(&fr, sizeof(FORMATRANGE));
    fr.hdc = hdc;
    fr.hdcTarget = hdc;
    fr.rcPage = r1;
    fr.rc = r2;

CHARRANGE cr;
    cr.cpMin = 0;
    cr.cpMax = CharRange;
    fr.chrg = cr;

LONG m = 0;
    do
    {
        fr.rcPage = r1;
        fr.rc = r2;
        ThePrintDC.StartPage();
        LastChar = richedit.FormatRange(&fr, TRUE);
        ErrorStatus = ThePrintDC.EndPage();
        cr.cpMin = LastChar;
        cr.cpMax = CharRange;
        fr.chrg = cr;
        m = richedit.FormatRange(&fr, FALSE);
    } while (m > LastChar);

switch (ErrorStatus)
    {
    case SP_ERROR:
    {
        ThePrintDC.AbortDoc();
        AfxMessageBox(_T("打印意外终止。"),MB_OK | MB_ICONEXCLAMATION);
        return 0;
    }
    case SP_APPABORT:
    {
        ThePrintDC.AbortDoc();
        return 0;
    }
    case SP_USERABORT:
    {
        ThePrintDC.AbortDoc();
        return 0;
    }
    case SP_OUTOFDISK:
    {
        ThePrintDC.AbortDoc();
        AfxMessageBox(_T("打印后台处理程序磁盘空间不足,释放一些磁盘空间并再试一次。"),MB_OK | MB_ICONEXCLAMATION);
        return 0;
    }
    case SP_OUTOFMEMORY:
    {
        ThePrintDC.AbortDoc();
        AfxMessageBox(_T("您的计算机内存不足,关闭某些应用程序和/或某些窗口,然后重试。"),MB_OK | MB_ICONEXCLAMATION);
        return 0;
    }
    default:
    {
        ThePrintDC.EndDoc();
        ThePrintDC.Detach();
    }

十一.多格式编辑控件显示图片

1.以CRichEditCtrl为基类,派生COleRichEditCtrl类;改写OleRichEditCtrl.h文件为:
#pragma once
#include <afxcmn.h>

#include <richole.h>

class COleRichEditCtrl : public CRichEditCtrl
{
public:
    COleRichEditCtrl();
    virtual ~COleRichEditCtrl();

interface IExRichEditOleCallback;

IExRichEditOleCallback* m_pIRichEditOleCallback;
    BOOL m_bCallbackSet;

interface IExRichEditOleCallback : public IRichEditOleCallback
    {
    public:
        IExRichEditOleCallback();
        virtual ~IExRichEditOleCallback();
        int m_iNumStorages;
        IStorage* pStorage;
        DWORD m_dwRef;

virtual HRESULT STDMETHODCALLTYPE GetNewStorage(LPSTORAGE* lplpstg);
        virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
        virtual ULONG STDMETHODCALLTYPE AddRef();
        virtual ULONG STDMETHODCALLTYPE Release();
        virtual HRESULT STDMETHODCALLTYPE GetInPlaceContext(LPOLEINPLACEFRAME FAR* lplpFrame,
            LPOLEINPLACEUIWINDOW FAR* lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo);
        virtual HRESULT STDMETHODCALLTYPE ShowContainerUI(BOOL fShow);
        virtual HRESULT STDMETHODCALLTYPE QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp);
        virtual HRESULT STDMETHODCALLTYPE DeleteObject(LPOLEOBJECT lpoleobj);
        virtual HRESULT STDMETHODCALLTYPE QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR
            * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict);
        virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
        virtual HRESULT STDMETHODCALLTYPE GetClipboardData(CHARRANGE FAR* lpchrg, DWORD reco,
            LPDATAOBJECT FAR* lplpdataobj);
        virtual HRESULT STDMETHODCALLTYPE GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD
            pdwEffect);
        virtual HRESULT STDMETHODCALLTYPE GetContextMenu(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR
            * lpchrg, HMENU FAR* lphmenu);
    };

protected:
    virtual void PreSubclassWindow();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

DECLARE_MESSAGE_MAP()
};

2.改写OleRichEditCtrl.cpp文件为:
#include "pch.h"
#include "COleRichEditCtrl.h"

COleRichEditCtrl::COleRichEditCtrl()
{
    m_bCallbackSet = FALSE;
}

COleRichEditCtrl::~COleRichEditCtrl()
{
}

BEGIN_MESSAGE_MAP(COleRichEditCtrl, CRichEditCtrl)
    ON_WM_CREATE()
END_MESSAGE_MAP()

int COleRichEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CRichEditCtrl::OnCreate(lpCreateStruct) == -1)
        return -1;
    ASSERT(m_pIRichEditOleCallback != NULL);
    if (!m_bCallbackSet)
    {
        SetOLECallback(m_pIRichEditOleCallback);
    }
    return 0;
}

void COleRichEditCtrl::PreSubclassWindow()
{
    CRichEditCtrl::PreSubclassWindow();

m_pIRichEditOleCallback = NULL;
    m_pIRichEditOleCallback = new IExRichEditOleCallback;
    ASSERT(m_pIRichEditOleCallback != NULL);
    m_bCallbackSet = SetOLECallback(m_pIRichEditOleCallback);
}

COleRichEditCtrl::IExRichEditOleCallback::IExRichEditOleCallback()
{
    pStorage = NULL;
    m_iNumStorages = 0;
    m_dwRef = 0;
    HRESULT hResult = ::StgCreateDocfile(NULL, STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE
        | STGM_CREATE, 0, &pStorage);
    if (pStorage == NULL || hResult != S_OK)
    {
        AfxThrowOleException(hResult);
    }
}

COleRichEditCtrl::IExRichEditOleCallback::~IExRichEditOleCallback()
{
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetNewStorage(LPSTORAGE* lplpstg)
{
    m_iNumStorages++;
    WCHAR tName[50];
    swprintf(tName, 50, L"REOLEStorage%d", m_iNumStorages);
    HRESULT hResult = pStorage->CreateStorage(tName,
        STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg);
    if (hResult != S_OK)
    {
        ::AfxThrowOleException(hResult);
    }
    return hResult;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::QueryInterface(REFIID iid, void** ppvObject)
{
    HRESULT hr = S_OK;
    *ppvObject = NULL;
    if (iid == IID_IUnknown || iid == IID_IRichEditOleCallback)
    {
        *ppvObject = this;
        AddRef();
        hr = NOERROR;
    }
    else
    {
        hr = E_NOINTERFACE;
    }
    return hr;
}

ULONG STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::AddRef()
{
    return ++m_dwRef;
}

ULONG STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::Release()
{
    if (--m_dwRef == 0)
    {
        delete this;
        return 0;
    }
    return m_dwRef;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetInPlaceContext(LPOLEINPLACEFRAME FAR* lplpFrame,
    LPOLEINPLACEUIWINDOW FAR* lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::ShowContainerUI(BOOL fShow)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::DeleteObject(LPOLEOBJECT lpoleobj)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR* lpcfFormat,
    DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::ContextSensitiveHelp(BOOL fEnterMode)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetClipboardData(CHARRANGE FAR* lpchrg, DWORD reco, LPDATAOBJECT FAR* lplpdataobj)
{
    return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE
COleRichEditCtrl::IExRichEditOleCallback::GetContextMenu(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR* lpchrg,
    HMENU FAR* lphmenu)
{
    return S_OK;
}

十二.在多格式编辑控件中插入图片

#include "richole.h"

HBITMAP hBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), _T("D:\\1.bmp"), IMAGE_BITMAP, 0, 0, 
        LR_LOADFROMFILE | LR_DEFAULTCOLOR);

STGMEDIUM stgm;
    stgm.tymed = TYMED_GDI;
    stgm.hBitmap = hBitmap;
    stgm.pUnkForRelease = NULL;

FORMATETC fm;
    fm.cfFormat = CF_BITMAP;
    fm.ptd = NULL;
    fm.dwAspect = DVASPECT_CONTENT;
    fm.lindex = -1;
    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);

LPOLECLIENTSITE  lpClientSite;
    richedit.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);
    long lStart, lEnd;
    richedit.GetSel(lStart, lEnd);
    reobject.clsid = clsid;
    reobject.cp = REO_CP_SELECTION;
    reobject.dvaspect = DVASPECT_CONTENT;
    reobject.poleobj = pOleObject;
    reobject.polesite = lpClientSite;
    reobject.pstg = pStorage;
    reobject.dwUser = 0;

richedit.GetIRichEditOle()->InsertObject(&reobject);

delete pDataSource;
    ::SendMessage(richedit.m_hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);

十三.在RichEdit版本4.1控件中插入表格

下面代码在多格式编辑控件中插入2行3列的表格:
    int hangN = 2;//行数
    int lieN = 3;//列数
    CDC* pDC = richedit.GetDC();
    int wT1 = MulDiv(150, 1440, pDC->GetDeviceCaps(LOGPIXELSX));//将150像素的列宽度转换为以缇为单位的列宽度,第1列以缇为单位的宽度
    int wT2 = MulDiv(150, 1440, pDC->GetDeviceCaps(LOGPIXELSX));//第2列以缇为单位的宽度
    int wT3 = MulDiv(150, 1440, pDC->GetDeviceCaps(LOGPIXELSX));//第3列以缇为单位的宽度
    ReleaseDC(pDC);
    CStringA w_str[3];//以缇为单位的右边框位置值数组
    w_str[0].Format("%d", wT1);//将第1列右边框位置值转换为字符串
    w_str[1].Format("%d", wT1 + wT2);//将第2列右边框位置值转换为字符串
    w_str[2].Format("%d", wT1 + wT2 + wT3);//将第3列右边框位置值转换为字符串
    CStringA ss = "{\\rtf1\\ansi\\ansicpg936{\\fonttbl{\\f0\\fnil\\fcharset0{\\*\\panose 02040503050406030204}Cambria;}{\\f1\\fnil\\fprq12\\fcharset134 \\'ce\\'a2\\'c8\\'ed\\'d1\\'c5\\'ba\\'da;}} {\\colortbl;\\red255\\green0\\blue0;\\red0\\green255\\blue0; \\red0\\green0\\blue255; \\red0\\green0\\blue0; }";
    CStringA color_str[2][3];//记录单元格使用的背景色颜色,为RTF格式字符
    color_str[0][0] = "\\clcbpat1"; color_str[0][1] = "\\clcbpat2"; color_str[0][2] = "\\clcbpat3";   
    color_str[1][0] = "\\clcbpat1"; color_str[1][1] = "\\clcbpat2"; color_str[1][2] = "\\clcbpat3";   //设置单元格背景色
    for (int i = 0; i < hangN; i++)
    {
        ss += "\\trowd\\trgaph10\\trbrdrl\\brdrs\\brdrw10\\trbrdrt\\brdrs\\brdrw10 \\trbrdrr\\brdrs\\brdrw10 \\trbrdrb\\brdrs\\brdrw10 ";
        for (int j = 0; j < lieN; j++)
        {
            ss += color_str[i][j] + "\\clbrdrl\\brdrw10\\brdrs\\clbrdrt\\brdrw10\\brdrs\\clbrdrr\\brdrw10\\brdrs\\clbrdrb\\brdrw10\\brdrs \\cellx" + w_str[j];
        }
        ss += "\\pard\\intbl\\brdrl\\brdrs\\brdrw10 \\brdrt\\brdrs\\brdrw10 \\brdrr\\brdrs\\brdrw10 \\brdrb\\brdrs\\brdrw10 \\li100\\ri100\\f0\\fs24";
        for (int k = 0; k < lieN; k++)
        {
            ss += "\\cell";
        }
        ss += "\\row";
    }
    ss += "}";
    SETTEXTEX st;
    st.codepage = CP_ACP;
    st.flags = ST_SELECTION | ST_KEEPUNDO;
    richedit.SendMessage(EM_SETTEXTEX, (WPARAM)&st, (LPARAM)(LPCSTR)ss);//插入多格式编辑控件

十四.多格式编辑控件样式

样式常量                               16进制值     10进制值    说明
ES_DISABLENOSCROLL    00002000    8192           始终显示滚动条。
ES_EX_NOCALLOLEINIT    00000000    0                 防止控件在创建时调用OleInitialize函数。
ES_NOIME                           00080000    524288       禁用IME操作。
ES_NOOLEDRAGDROP      00000008    8                 禁用对OLE对象拖放的支持。
ES_SAVESEL                       00008000    32768         当控件失去焦点时保留选择。
ES_SELECTIONBAR           01000000    16777216   在左边距中添加空间,在此空间点击可以整行选择。
ES_SELFIME                        00040000    262144       允许应用程序处理所有IME操作。
ES_SUNKEN                        00004000    16384          控件带有凹陷的边框。
ES_VERTICAL                      00400000    4194304      垂直显示文本。

多格式编辑控件还支持以下编辑控件(CEdit)样式:
受支持的CEdit样式常量       16进制值      10进制值      说明
ES_AUTOHSCROLL            0080             128              在行尾键入字符时,文本自动向左滚动。
ES_AUTOVSCROLL             0040             64               在最后一行按回车键时,文本自动向上滚动。
ES_CENTER                         0001             1                 水平居中文本。
ES_LEFT                               0000             0                  文本左对齐。
ES_MULTILINE                     0004             4                  多行。
ES_NOHIDESEL                   0100             256              控件失去焦点时,不隐藏选择。
ES_NUMBER                        2000             8192            仅允许在编辑控件中输入数字。编者注:此样式不起作用。
ES_PASSWORD                   0020             32                将编辑控件中的每个字符显示为星号(*)。
ES_READONLY                    0800             2048             只读。
ES_RIGHT                             0002             2                 文本右对齐。
ES_WANTRETURN              1000             4096            接收回车键。

十五.多格式编辑控件事件

EN_CHANGE​​​​​​​

当多格式编辑控件的内容更改时,发送此通知到父窗口。此通知以WM_COMMAND消息的形式发送。
要使多格式编辑控件发送此通知,须指定ENM_CHANGE掩码。
    LONG Mask =richedit.GetEventMask();
    Mask |= ENM_CHANGE;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnChangeRichedit21();
消息映射:
    ON_EN_CHANGE(IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnChangeRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnChangeRichedit21()
{
}

返回值
此通知不返回值。

EN_DRAGDROPDONE

通知多格式编辑控件的父窗口拖放操作已完成。控件以WM_NOTIFY消息的形式发送此通知。
要使多格式编辑控件发送此通知,须指定ENM_DRAGDROPDONE掩码。
    LONG Mask =richedit.GetEventMask();
    Mask |= ENM_DRAGDROPDONE;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnDragDropDoneRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_DRAGDROPDONE, IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnDragDropDoneRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnDragDropDoneRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pNMHDR->code;//UINT 通知代码,为EN_DRAGDROPDONE
    pNMHDR->hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
参数*pResult
忽略此参数。

EN_ERRSPACE

编辑控件无法分配足够的内存以满足特定请求时发送。编辑控件的父窗口通过WM_COMMAND消息接收此通知代码。
处理函数声明:
    afx_msg void OnEnErrspaceRichedit21();
消息映射:
    ON_EN_ERRSPACE(IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnErrspaceRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnErrspaceRichedit21()
{
    // TODO: 在此添加控件通知处理程序代码
}

EN_HSCROLL

用户单击编辑控件的水平滚动条时发送。编辑控件的父窗口通过WM_COMMAND消息接收此通知代码。在更新屏幕之前通知父窗口。
要使控件发送此通知,须指定ENM_SCROLL掩码。
    LONG Mask =richedit.GetEventMask();
    Mask |= ENM_SCROLL;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnHscrollRichedit21();
消息映射:
    ON_EN_HSCROLL(IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnHscrollRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnHscrollRichedit21()
{
    // TODO:  在此添加控件通知处理程序代码
}
备注
此通知在以下情况下发送:单击水平滚动条的箭头按钮或在箭头按钮和拖动块之间单击。但是,单击滚动条拖动块本身时不会发送通知代码。当键盘事件导致编辑控件的视图区域发生更改时,也会发送通知代码,例如,按HOME,END,左箭头键或右箭头键。

EN_KILLFOCUS

编辑控件失去键盘焦点时发送。编辑控件的父窗口通过WM_COMMAND消息接收此通知代码。
处理函数声明:
    afx_msg void OnEnKillfocusRichedit21();
消息映射:
    ON_EN_KILLFOCUS(IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnKillfocusRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnKillfocusRichedit21()
{
    // TODO: 在此添加控件通知处理程序代码
}

EN_LINK

当鼠标指针悬停在具有CFE_LINK效果的文本上时发送此通知。控件的父窗口通过WM_NOTIFY消息接收此通知代码。
要使多格式编辑控件发送此通知,须指定ENM_LINK掩码。
    LONG Mask =richedit.GetEventMask();
    Mask |= ENM_LINK;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnLinkRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_LINK, IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnLinkRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnLinkRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    ENLINK* pEnLink = reinterpret_cast<ENLINK*>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pEnLink->nmhdr;//NMHDR 结构
    pEnLink->nmhdr.code;//UINT 通知代码,为EN_LINK
    pEnLink->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pEnLink->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pEnLink->msg;//UINT 导致多格式编辑控件发送EN_LINK通知代码的消息
    pEnLink->chrg;//CHARRANGE结构 指示具有CFE_LINK效果的连续字符范围
参数*pResult 
*pResult = 0;
返回零以使控件继续其对消息的正常处理。
*pResult = 1;
返回一个非零值,以防止控件处理该消息。
*pResult = EN_LINK_DO_DEFAULT;
Windows 8:返回EN_LINK_DO_DEFAULT以指示多格式编辑控件执行默认操作。

示例
此示例在点击链接文本时,获取链接文本。
void CMFCApplication2Dlg::OnEnLinkRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    ENLINK* pEnLink = reinterpret_cast<ENLINK*>(pNMHDR);
    *pResult = 0;
    switch (pEnLink->msg)
    {
        default: {}
               break;
        case WM_LBUTTONDOWN://如果鼠标左键被点击
        {
            CString strURL;
            CHARRANGE crCharRange;
            COleRichEditCtrl* pTempEdit;
            pTempEdit = (COleRichEditCtrl*)COleRichEditCtrl::FromHandle(pEnLink->nmhdr.hwndFrom);
            pTempEdit->GetSel(crCharRange);//获取原来的选择范围
            pTempEdit->SetSel(pEnLink->chrg);//设置链接文本被选中
            strURL = pTempEdit->GetSelText();//得到链接文本
            pTempEdit->SetSel(crCharRange);//恢复原来的选择范围。如果控件没有选择字符,恢复插入符的原来位置
            //在此处添加:获取链接文本后处理代码
            *pResult = 1;
            break;
        }
    }
}

EN_LOWFIRTF

通知父窗口,多格式编辑控件收到了不支持的RTF关键字。控件以WM_NOTIFY消息的形式发送此通知。
要使多格式编辑控件发送此通知,须指定ENM_LOWFIRTF掩码。
    LONG Mask =richedit.GetEventMask();
    Mask |= ENM_LOWFIRTF;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnLowFiRTFRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_LOWFIRTF, IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnLowFiRTFRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnLowFiRTFRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    ENLOWFIRTF* pENLowFiRTF = reinterpret_cast<ENLOWFIRTF*>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pENLowFiRTF->nmhdr;//NMHDR结构
    pENLowFiRTF->nmhdr.code;//UINT 通知代码,为EN_LOWFIRTF
    pENLowFiRTF->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pENLowFiRTF->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pENLowFiRTF->szControl;//CHAR* 不支持的RTF关键字。
参数*pResult
忽略返回值。

EN_MAXTEXT

当输入超过限定数量的字符时,发送此通知到父窗口。此通知以WM_COMMAND消息的形式发送。
处理函数声明:
    afx_msg void OnEnMaxtextRichedit21();
消息映射:
    ON_EN_MAXTEXT(IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnMaxtextRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnMaxtextRichedit21()
{
}

EN_MSGFILTER

将多格式编辑控件的键盘或鼠标事件通知给父窗口。此通知以WM_NOTIFY消息的形式发送。
要使控件发送此通知,须指定下面的一个或多个掩码。
ENM_KEYEVENTS         接收键盘事件
ENM_MOUSEEVENTS         接收鼠标事件
ENM_SCROLLEVENTS         接收鼠标滚轮事件
    LONG Mask =richedit.GetEventMask();
    Mask |= ENM_KEYEVENTS;
    richedit.SetEventMask(Mask);

处理函数声明:
    afx_msg void OnEnMsgfilterRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_MSGFILTER, IDC_RICHEDIT21, &CMFCApplication2Dlg::OnEnMsgfilterRichedit21)
处理函数定义:
void CMFCApplication2Dlg::OnEnMsgfilterRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    MSGFILTER* pMsgFilter = reinterpret_cast<MSGFILTER*>(pNMHDR);
    // TODO:  在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pMsgFilter->nmhdr;//NMHDR结构
    pMsgFilter->nmhdr.code;//UINT 通知代码,为EN_MSGFILTER
    pMsgFilter->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pMsgFilter->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pMsgFilter->msg;//UINT 键盘或鼠标消息
参数*pResult
*pResult = 0;
返回0,控件应处理键盘或鼠标事件。
*pResult = 1;
返回非零,控件应忽略键盘或鼠标事件。

EN_PROTECTED

通知父窗口,用户正在更改受保护的文本。多格式编辑控件以WM_NOTIFY消息的形式发送此通知。
要使控件发送此通知,须指定ENM_PROTECTED掩码。
    LONG Mask=richedit.GetEventMask();
    Mask |= ENM_PROTECTED;
    richedit.SetEventMask(Mask);
将选中的文本设置为受保护的文本代码:
    CHARFORMAT2 cf;
    cf.cbSize = sizeof(CHARFORMAT2);
    richedit.GetSelectionCharFormat(cf);
    cf.dwEffects |= CFE_PROTECTED;
    richedit.SetSelectionCharFormat(cf);
处理函数声明:
    afx_msg void OnEnProtectedRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_PROTECTED, IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnProtectedRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnProtectedRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    ENPROTECTED* pEnProtected = reinterpret_cast<ENPROTECTED*>(pNMHDR);
    // TODO:  在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pEnProtected->nmhdr;//NMHDR结构
    pEnProtected->nmhdr.code;//UINT 通知代码,为EN_PROTECTED
    pEnProtected->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pEnProtected->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pEnProtected->chrg;//CHARRANGE结构 
    //如果是在受保护的文本中插入字符,此参数为插入字符的索引
    //如果是在受保护的文本中插入字符串,此参数为插入字符串的第1个字符的索引
    //如果是在受保护的文本中删除字符,此参数为删除字符的下一个字符的索引
    //如果是在受保护的文本中删除多个字符,此参数指示删除字符的范围
    pEnProtected->msg;//UINT 键盘或鼠标消息
    //如果值为256,消息为WM_KEYDOWN 按下了某键
    //如果值为768,消息为WM_CUT
    //如果值为769,消息为WM_COPY  
    //如果值为770,消息为WM_PASTE
    //如果值为771,消息为WM_CLEAR
    //如果值为772,消息为WM_UNDO
参数*pResult
*pResult = 0;
返回零以允许该操作。
*pResult = 1;
返回一个非零值以阻止该操作。

EN_REQUESTRESIZE

通知父窗口,多格式编辑控件的内容小于或大于控件的窗口大小。此通知以WM_NOTIFY消息的形式发送。
要使多格式编辑控件发送此通知,须指定ENM_REQUESTRESIZE掩码。
    LONG Mask=richedit.GetEventMask();
    Mask |= ENM_REQUESTRESIZE;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnRequestresizeRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_REQUESTRESIZE, IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnRequestresizeRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnRequestresizeRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    REQRESIZE* pReqResize = reinterpret_cast<REQRESIZE*>(pNMHDR);
    // TODO:  在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pReqResize->nmhdr;//NMHDR结构
    pReqResize->nmhdr.code;//UINT 通知代码,为EN_REQUESTRESIZE
    pReqResize->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pReqResize->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pReqResize->rc;//RECT结构 要求的新大小
参数*pResult
忽略返回值。

EN_SAVECLIPBOARD

通知父窗口,多格式编辑控件正在关闭并且剪贴板包含信息。此通知以WM_NOTIFY消息的形式发送。
关闭多格式编辑控件代码:
    richedit.SendMessage(WM_CLOSE);
处理函数声明:
    afx_msg void OnEnSaveclipboardRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_SAVECLIPBOARD, IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnSaveclipboardRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnSaveclipboardRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    ENSAVECLIPBOARD* pEnSaveClipboard = reinterpret_cast<ENSAVECLIPBOARD*>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pEnSaveClipboard->nmhdr;//NMHDR结构 
    pEnSaveClipboard->nmhdr.code;//UINT 通知代码,为EN_SAVECLIPBOARD
    pEnSaveClipboard->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pEnSaveClipboard->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pEnSaveClipboard->cObjectCount;//LONG 剪贴板上的对象数量
    pEnSaveClipboard->cch;//LONG 剪贴板上的字符数量
参数*pResult
*pResult = 0;
如果保留剪贴板数据,返回零值。
*pResult = 1;
如果不保留剪贴板数据,返回非零值。

EN_SELCHANGE

通知父窗口,多格式编辑控件选择已更改(包括更改插入符的位置)。此通知以WM_NOTIFY消息的形式发送。
要使控件发送此通知,须指定ENM_SELCHANGE掩码。
    LONG Mask=richedit.GetEventMask();
    Mask |= ENM_SELCHANGE;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnSelchangeRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(EN_SELCHANGE, IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnSelchangeRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnSelchangeRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{
    SELCHANGE* pSelChange = reinterpret_cast<SELCHANGE*>(pNMHDR);
    // TODO:  在此添加控件通知处理程序代码
    *pResult = 0;
}
参数
    pSelChange->nmhdr;//NMHDR结构 
    pSelChange->nmhdr.code;//UINT 通知代码,为EN_SELCHANGE
    pSelChange->nmhdr.hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pSelChange->nmhdr.idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识
    pSelChange->chrg;//CHARRANGE结构 新的选择范围。
    pSelChange->seltyp;//WORD 新选择内容的类型
    //可以是以下值的一个或多个:
    SEL_TEXT         文本
    SEL_OBJECT         至少一个COM对象。
    SEL_MULTICHAR     多个文本字符。
    SEL_MULTIOBJECT     多个COM对象。
参数*pResult
忽略返回值。

EN_SETFOCUS

通知父窗口,多格式编辑控件获得焦点。此通知以WM_COMMAND消息的形式发送。
处理函数声明:
    afx_msg void OnEnSetfocusRichedit21();
消息映射:
    ON_EN_SETFOCUS(IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnSetfocusRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnSetfocusRichedit21()
{
    // TODO: 在此添加控件通知处理程序代码
}

EN_UPDATE

多格式编辑控件显示更新前,发送此通知到父窗口。此通知以WM_COMMAND消息的形式发送。
处理函数声明:
    afx_msg void OnEnUpdateRichedit21();
消息映射:
    ON_EN_UPDATE(IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnUpdateRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnUpdateRichedit21()
{
    // TODO:  在此添加控件通知处理程序代码
}

EN_VSCROLL

当用户单击多格式编辑控件的垂直滚动条或用户在多格式编辑控件上滚动鼠标滚轮时,发送此通知到父窗口。此通知以WM_COMMAND消息的形式发送。

要使控件发送此通知,须指定ENM_SCROLL掩码。
    LONG Mask=richedit.GetEventMask();
    Mask |= ENM_SCROLL;
    richedit.SetEventMask(Mask);
处理函数声明:
    afx_msg void OnEnVscrollRichedit21();
消息映射:
    ON_EN_VSCROLL(IDC_RICHEDIT21, &CMFCApplication1Dlg::OnEnVscrollRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnEnVscrollRichedit21()
{
    // TODO: 在此添加控件通知处理程序代码
}

NM_THEMECHANGED

通知父窗口,多格式编辑控件的主题已更改。 此通知以WM_NOTIFY消息的形式发送。
处理函数声明:
    afx_msg void OnNMThemeChangedRichedit21(NMHDR* pNMHDR, LRESULT* pResult);
消息映射:
    ON_NOTIFY(NM_THEMECHANGED, IDC_RICHEDIT21, &CMFCApplication1Dlg::OnNMThemeChangedRichedit21)
处理函数定义:
void CMFCApplication1Dlg::OnNMThemeChangedRichedit21(NMHDR* pNMHDR, LRESULT* pResult)
{    
    *pResult = 0;
}
参数
    pNMHDR->code;//UINT 通知代码,为NM_THEMECHANGED
    pNMHDR->hwndFrom;//HWND 发送通知的多格式编辑控件的窗口句柄
    pNMHDR->idFrom;//UINT_PTR 发送通知的多格式编辑控件的标识

参数*pResult 
忽略返回值。
​​​​​​​

下面链接可以下载全文:

CRichEditCtrl多格式编辑控件.rar-C/C++文档类资源-CSDN下载

CRichEditCtrl 多格式编辑控件的使用相关推荐

  1. VCL组件之编辑控件

    VCL组件之编辑控件 Note 以后将用两种方式提及组件,以组件的名称或定义组件的VCL类的名称.可以说"Label组件用于--"或说"TLabel用于--", ...

  2. Silverlight 信息显示与编辑控件 示例

    Silverlight 真是一个不错的开发平台,想到即将发布的Silverlight 4 更是增加了像去学习他的兴趣. 信息显示控件 TextBlock 信息显示第一个要说的一定是TextBlock, ...

  3. BCGControlBar Pro for MFC v13.3现已发布:着重改进图表、属性/编辑控件等,打造全面、易上手的MFC库

    亲爱的BCGSoft用户,我们非常高兴地宣布BCGControlBar Professional for MFC v31.3正式发布啦! BCGControlBar Pro for MFC v31.3 ...

  4. silverlight之How To:设置ComboBox控件的数据源当ComboBox用来作为DataGrid的某列的编辑控件时...

    DataGrid是个可编辑的列表控件,而且可以用已有的输入控件来作为某一列的编辑控件,比如用ComboBox控件来作为某列的编辑控件供用户选择数据,这个时候就要先设置好ComboBox控件的下拉列表项 ...

  5. WinForm界面开发之“HTML内容编辑控件”

    做过了很多Winform的共享软件,对界面的设计有了一定的经验和积累,准备开一个"WinForm界面开发"系列文章,介绍下相关的Winform界面设计和相关控件的使用,促进相互交流 ...

  6. ExtJs4 笔记(8) Ext.slider 滚轴控件、 Ext.ProgressBar 进度条控件、 Ext.Editor 编辑控件...

    本篇要登场的有三个控件,分别是滚轴控件.进度条控件和编辑控件. 一.滚轴控件 Ext.slider 1.滚轴控件的定义 下面我们定义三个具有代表意义滚轴控件,分别展示滚轴横向.纵向,以及单值.多值选择 ...

  7. C# Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面...

    个人理解,开发应用程序的目的,不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景也最为复杂,包括但不限于:表格记录查询.报表查询.导出文件查询等等 ...

  8. mfc c语言 编辑器,语法高亮编辑控件Scintilla在MFC中的简单使用

    项目中要使用代码编辑器,搜索之后,发现了强大的编辑器控件Scintilla. 1.简介 Scintilla是一款开源的语法高亮编辑器控件,官方网站:http://www.scintilla.org/. ...

  9. (转)基于MVC4+EasyUI的Web开发框架经验总结(5)--使用HTML编辑控件CKEditor和CKFinder...

    http://www.cnblogs.com/wuhuacong/p/3780356.html Web开发上有很多HTML的编辑控件,如CKEditor.kindeditor等等,很多都做的很好,本文 ...

最新文章

  1. amd的处理器能兼容idea么_250元就能买到16GB内存 这背后究竟是道德的沦丧还是人性的扭曲?...
  2. canvas 将图形设置为button_将Excel设置为存放文件的文件夹:自动提醒直观摘要免压缩发微信...
  3. PTA浙大版python程序设计题目集--第2章-2 计算分段函数[1] (10 分)
  4. Spring源码:AOP(1)
  5. 数学建模之图论——图与网络模型(一)(基本概念和最短路问题,附MATLAB源码)
  6. uva 10562 - Undraw the Trees
  7. 如何用PyTorch训练图像分类器
  8. Vite ---- 创建Vue3.0+TS项目
  9. 基于微信小程序的二手交易平台源码
  10. Linux下安装Eclipse的PHP插件(PHPEclipse)
  11. 论文阅读 (54):DeepFool: A Simple and Accurate Method to Fool Deep Neural Networks
  12. 社会生活中的著名法则- -
  13. MySQL轻快入门2021.3.18(事务)
  14. 在Visio中快速的画一个虚线框
  15. bcc钱包地址生成linux,从Bcc到xdp原理分析
  16. Oracle中Blob和Clob类型的区别
  17. 关于设立“链改青岛链湾综合试验区”的复函
  18. vue3组合式Composition API之setup函数的具体用法
  19. Flask Web实战-新闻资讯项目
  20. JAVA递归函数示例 - 阶乘计算

热门文章

  1. 使用Python生成Micro QRCode(微二维码)
  2. Yeti雪人计划:纯IPv6域名根服务器系统试验床
  3. 什么时候黎明觉醒服务器不维护,黎明觉醒火种测试什么时候开启_火种测试开启时间介绍_3DM手游...
  4. 数据分析方法论3:综合指标分析法
  5. 4K/8K的雷电(thunderbolt)解决方案
  6. BaseActivity的封装思想及YzsBaseActivity详解
  7. Wampserver64位官网下载以及安装配置
  8. keep2share 购买的激活码但激活不了
  9. 云呐|动环监控网管软件有哪些
  10. C#通用类库--数字转为人民币汉字大写表示可负大写