C语言RichEdit控件如何初始化与文本操作?

99ANYc3cd6
预计阅读时长 33 分钟
位置: 首页 C语言 正文

目录

  1. 什么是 Rich Edit 控件?
  2. 准备工作:加载 Rich Edit 库
  3. 创建 Rich Edit 控件
  4. 发送消息:与 Rich Edit 交互
  5. 常用功能与代码示例
    • 设置文本内容
    • 获取文本内容
    • 设置字体、颜色
    • 换行与段落格式
    • 处理富文本格式 (RTF)
  6. 完整示例:一个简单的富文本编辑器
  7. 高级主题与注意事项

什么是 Rich Edit 控件?

Rich Edit 控件是一个标准的 Windows 窗口类,它比普通的 EDIT 控件功能强大得多。

c语言richedit
(图片来源网络,侵删)
  • 普通 Edit 控件 (EDIT):

    • 只能处理纯文本。
    • 功能有限:单行/多行、基本编辑。
  • Rich Edit 控件 (RICHEDIT):

    • 支持富文本格式,包括:
      • 多种字体 和字号
      • 字体样式 (粗体、斜体、下划线)
      • 字体颜色 和背景色
      • 段落对齐 (左对齐、居中、右对齐)
      • 项目符号和编号列表
      • 插入图片 (需要额外处理)
    • 可以加载和保存 RTF (Rich Text Format) 文件,这是一种通用的富文本格式。

在 Windows 中,有多个版本的 Rich Edit 控件,如 RichEdit20A, RichEdit20W, RichEdit50W 等,为了获得最佳兼容性和功能,我们通常使用 RichEdit50W


准备工作:加载 RichEdit 库

在创建 Rich Edit 控件之前,必须显式加载其对应的动态链接库 (DLL),对于 RichEdit50W,这个库是 riched32.dll

c语言richedit
(图片来源网络,侵删)

通常在程序初始化时(例如在 WinMain 函数中)调用 LoadLibrary

#include <windows.h>
#include <richedit.h> // 包含 Rich Edit 相关的消息和结构体定义
// 在 WinMain 函数开始处
HINSTANCE hRichEditDll = LoadLibrary(TEXT("RICHED32.DLL"));
if (hRichEditDll == NULL) {
    // 处理加载失败的情况
    MessageBox(NULL, TEXT("无法加载 RichEdit32.dll"), TEXT("错误"), MB_OK | MB_ICONERROR);
    return 1;
}

在程序结束时,记得使用 FreeLibrary 释放它。


创建 Rich Edit 控件

创建 Rich Edit 控件与创建其他标准控件(如按钮、文本框)类似,使用 CreateWindowEx 函数。

关键点:

  • 窗口类名: 必须使用 RICHEDIT_CLASS,注意,这通常需要调用 LoadLibrary 后才能使用。
  • 扩展样式: 可以使用 ES_MULTILINE (多行), WS_VSCROLL (垂直滚动条), WS_HSCROLL (水平滚动条) 等。
// 在 WM_CREATE 消息处理中
HWND hRichEdit = CreateWindowEx(
    0,                              // 扩展窗口样式
    RICHEDIT_CLASS,                 // 窗口类名
    TEXT("请输入文本..."),          // 窗口标题
    WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
    10, 10, 400, 300,              // 位置和大小
    hWnd,                           // 父窗口句柄
    (HMENU)IDC_RICHEDIT,           // 控件ID
    hInstance,                      // 应用程序实例句柄
    NULL                            // 创建参数
);
if (hRichEdit == NULL) {
    MessageBox(hWnd, TEXT("创建 Rich Edit 控件失败"), TEXT("错误"), MB_OK);
}

发送消息:与 Rich Edit 交互

与 Rich Edit 控件交互的主要方式是使用 SendMessage 函数发送特定的消息,每个消息通常对应一个特定的功能。

SendMessage 的原型:

LRESULT SendMessage(
  HWND   hWnd,
  UINT   Msg,
  WPARAM wParam,
  LPARAM lParam
);
  • hWnd: Rich Edit 控件的句柄。
  • Msg: 要发送的消息(EM_SETCHARFORMAT)。
  • wParam / lParam: 消息的附加参数。

常用功能与代码示例

使用 WM_SETTEXT 消息。

SendMessage(hRichEdit, WM_SETTEXT, 0, (LPARAM)L"这是设置的新文本。");

使用 WM_GETTEXT 消息,你需要一个足够大的缓冲区来存储文本。

wchar_t buffer[1024];
SendMessage(hRichEdit, WM_GETTEXT, (WPARAM)1024, (LPARAM)buffer);

设置字体、颜色

这是 Rich Edit 的核心功能,你需要使用 CHARFORMAT 结构体和 EM_SETCHARFORMAT 消息。

CHARFORMAT cf = {0};
cf.cbSize = sizeof(CHARFORMAT); // 结构体大小,必须设置
cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE; // 我们将要设置哪些属性
cf.crTextColor = RGB(255, 0, 0); // 设置字体颜色为红色
cf.dwEffects = 0; // 清除所有效果
wcscpy_s(cf.szFaceName, L"微软雅黑"); // 设置字体名称
cf.yHeight = 20 * 12; // 字号,单位是 1/20 个点,20 * 12 表示 12 号字体
// 发送消息
// SCF_SELECTION: 只对当前选中文本有效
// SCF_WORD: 如果没有选中文本,则对光标所在单词有效
SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);

换行与段落格式

使用 PARAFORMAT 结构体和 EM_SETPARAFORMAT 消息。

PARAFORMAT pf = {0};
pf.cbSize = sizeof(PARAFORMAT);
pf.dwMask = PFM_ALIGNMENT; // 我们将要设置对齐方式
pf.wAlignment = PFA_CENTER; // 设置为居中对齐
SendMessage(hRichEdit, EM_SETPARAFORMAT, SCF_SELECTION, (LPARAM)&pf);

处理富文本格式

Rich Edit 控件可以处理 RTF 格式的文本。

  • 设置 RTF 内容: 使用 EM_STREAMIN 消息,这比较复杂,通常需要提供一个回调函数。
  • 获取 RTF 内容: 使用 EM_STREAMOUT 消息,同样复杂。
  • 更简单的方法: 将 RTF 文件读入内存,然后通过 WM_SETTEXT 设置,但这会丢失格式信息,更标准的方法是使用 EditStreamIn 结构。

一个更简单的方法是利用剪贴板:

// 假设你有一个包含 RTF 的字符串
const char* rtf_data = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fnil\\fcharset0 Calibri;}}\n{\\colortbl;\\red0\\green0\\blue0;}\n\\viewkind4\\uc1\\pard\\f0\\fs20 这是 RTF 格式的文本,\\par\n}";
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, strlen(rtf_data) + 1);
LPVOID pGlobal = GlobalLock(hGlobal);
memcpy(pGlobal, rtf_data, strlen(rtf_data) + 1);
GlobalUnlock(hGlobal);
// 将数据放入剪贴板
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_RTF, hGlobal);
CloseClipboard();
// 从剪贴板粘贴到 Rich Edit
SendMessage(hRichEdit, WM_PASTE, 0, 0);
// 释放内存
GlobalFree(hGlobal);

完整示例:一个简单的富文本编辑器

这个例子创建一个窗口,包含一个 Rich Edit 控件和几个按钮,用于改变字体颜色。

#include <windows.h>
#include <richedit.h>
#include <commctrl.h> // 为 Common Controls 库
#pragma comment(lib, "comctl32.lib") // 链接 Common Controls 库
#define IDC_RICHEDIT 101
#define IDC_BTN_RED   102
#define IDC_BTN_BLUE  103
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitCommonControls();
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) {
    InitCommonControls(); // 初始化 Common Controls (为了 Rich Edit)
    // 加载 RichEdit DLL
    HINSTANCE hRichEditDll = LoadLibrary(TEXT("RICHED32.DLL"));
    if (!hRichEditDll) {
        MessageBox(NULL, L"无法加载 RichEdit32.dll", L"错误", MB_OK | MB_ICONERROR);
        return 1;
    }
    WNDCLASSW wc = {0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = L"MyRichEditWindow";
    RegisterClassW(&wc);
    HWND hWnd = CreateWindowW(L"MyRichEditWindow", L"简单 Rich Edit 示例",
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
                            NULL, NULL, hInstance, NULL);
    if (hWnd) ShowWindow(hWnd, nCmdShow);
    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    FreeLibrary(hRichEditDll); // 卸载 DLL
    return (int)msg.wParam;
}
void InitCommonControls() {
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&icex);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_CREATE: {
            // 创建 Rich Edit 控件
            HWND hRichEdit = CreateWindowExW(0, RICHEDIT_CLASS, L"",
                                            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
                                            10, 10, 560, 300,
                                            hWnd, (HMENU)IDC_RICHEDIT, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
            if (!hRichEdit) {
                MessageBox(hWnd, L"创建 Rich Edit 失败", L"错误", MB_OK);
                return -1;
            }
            // 创建按钮
            CreateWindowW(L"BUTTON", L"红色", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                         10, 320, 100, 30, hWnd, (HMENU)IDC_BTN_RED, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
            CreateWindowW(L"BUTTON", L"蓝色", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
                         120, 320, 100, 30, hWnd, (HMENU)IDC_BTN_BLUE, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
            break;
        }
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case IDC_BTN_RED: {
                    CHARFORMAT cf = {0};
                    cf.cbSize = sizeof(CHARFORMAT);
                    cf.dwMask = CFM_COLOR;
                    cf.crTextColor = RGB(255, 0, 0);
                    SendMessage(GetDlgItem(hWnd, IDC_RICHEDIT), EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
                    break;
                }
                case IDC_BTN_BLUE: {
                    CHARFORMAT cf = {0};
                    cf.cbSize = sizeof(CHARFORMAT);
                    cf.dwMask = CFM_COLOR;
                    cf.crTextColor = RGB(0, 0, 255);
                    SendMessage(GetDlgItem(hWnd, IDC_RICHEDIT), EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
                    break;
                }
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

高级主题与注意事项

  1. 版本兼容性: 不同的 Windows 版本默认支持不同版本的 Rich Edit。RichEdit20 是 Win98/NT4 时代的主流,RichEdit50 (来自 riched50.dll) 功能更强大,被 XP 及更高版本支持,为了确保你的程序在任何 Windows 系统上都能工作,最好的做法是使用 LoadLibrary 动态加载 riched32.dll,并检查加载是否成功,如果失败,可以尝试加载 riched50.dllmsftedit.dll (这是 RichEdit50 的另一个来源)。

  2. Unicode 支持: 在现代 Windows 编程中,强烈推荐使用宽字符版本 (W 版本) 的 API,如 CreateWindowExWCHARFORMATW,这样可以更好地支持国际化字符。

  3. 通知消息: Rich Edit 控件会向父窗口发送 EN_CHANGE (内容改变)、EN_SELCHANGE (选择改变) 等通知消息,你可以在 WM_NOTIFY 消息中处理它们,以实现更复杂的交互逻辑。

  4. 性能: 对于包含大量文本或复杂格式的文档,频繁地发送 EM_SETCHARFORMAT 等消息可能会影响性能,在需要批量修改格式时,可以考虑先锁定文本内容进行修改,然后再一次性应用格式。

  5. 替代方案: 如果你觉得直接使用 Win32 API 的 Rich Edit 控件过于繁琐,可以考虑使用更高层的 GUI 框架,

    • MFC (Microsoft Foundation Classes): 封装了 Win32,提供了 CRichEditCtrl 类,使用起来更方便。
    • Qt: 跨平台框架,其 QTextEdit 控件功能强大且易用。
    • wxWidgets: 另一个优秀的跨平台 C++ GUI 框架。

希望这份详细的指南能帮助你在 C 语言项目中成功使用 Rich Edit 控件!

-- 展开阅读全文 --
头像
dede问答模块如何正确调用?
« 上一篇 04-21
织梦忘记密码怎么办
下一篇 » 04-21

相关文章

取消
微信二维码
支付宝二维码

目录[+]