windows原生控件RichEdit使用梳理

语言开发 专栏收录该内容
22 篇文章 0 订阅

RichEdit富文本编辑框在实际开发中应用的比较多,现将在平时工作中使用到的做以梳理:

HMODULE     m_hRichEditDll = NULL;
HWND hRichEdit = NULL;

1. 初始化RICHED20.dll
BOOL InitRichEditCtrlModule()
{
    m_hRichEditDll = LoadLibrary_api_s(L"RICHED20.dll");
    return NULL != m_hRichEditDll;
}

2. 创建ReichEdit控件
if (!hRichEdit) 
{
    DestroyWindow(hRichEdit);
    hRichEdit = NULL;
}
    
{
    //创建控件
    hRichEdit = CreateWindowEx(
        WS_EX_CLIENTEDGE | WS_EX_TRANSPARENT | WS_EX_WINDOWEDGE, L"RichEdit20W", NULL,
        WS_CHILD | WS_VISIBLE | /*WS_VSCROLL | WS_HSCROLL |*/ ES_MULTILINE | ES_NOHIDESEL | ES_WANTRETURN, x,
        y, 10, 30, win->hwndCanvas, 0, NULL, 0);
    //设置控件需要响应的消息
    SendMessage(hRichEdit, EM_SETEVENTMASK, 0,
                ENM_SELCHANGE | ENM_MOUSEEVENTS | ENM_CHANGE | ENM_KEYEVENTS | ENM_SCROLL | ENM_DROPFILES |
                    ENM_REQUESTRESIZE);
    
    //设置控件字体样式
    CHARFORMAT cf;
    ZeroMemory(&cf, sizeof(CHARFORMAT));
    cf.cbSize = sizeof(CHARFORMAT);
    cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE;
    cf.dwEffects = 0;
    cf.yHeight = 18 * 18;                                                     //文字高度
    cf.crTextColor = RGB(255, 0, 0);                                          //文字颜色
    _tcscpy_s(cf.szFaceName, sizeof(cf.szFaceName) / sizeof(WCHAR), L"Helv"); //设置字体
    ::SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
    
    RECT winRect;
    // 获取RichEdit控件的屏幕矩形
    GetWindowRect(hRichEdit, &winRect);
    
    // 获取RichEdit控件的行数
    int iLineCount = (int)::SendMessage(hRichEdit, EM_GETLINECOUNT, 0, 0);
    
    // 分别遍历每行上面的文本
    int iRetLen = 0;
    TCHAR tmpItemContent[2048 + 1] = {0};
    for (int nIndex = 0; nIndex < iLineCount; nIndex++) {
        memset(tmpItemContent, 0x00, sizeof(tmpItemContent));
        *(LPWORD)tmpItemContent = (WORD)2048;
        // 获取指定行上的文本
        iRetLen = ::SendMessage(hRichEdit, EM_GETLINE, nIndex, (LPARAM)tmpItemContent);
    }
    
    // 分别遍历每行的字符位置
    int xMax = 0, yMax = 0;
    POINT pt;
    for (int iPosIndex = 0; iPosIndex < iRetLen; iPosIndex++) {
        ::SendMessage(hRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)iPosIndex);
        pt.x > xMax ? xMax = pt.x : 0;
        pt.y > yMax ? yMax = pt.y : 0;
        wsprintf(tmpBuf, L"nIndex[%d] iPosIndex[%d] [%c] (%d, %d) \n", nIndex, iPosIndex,
                 tmpItemContent[iPosIndex], pt.x, pt.y);
        OutputDebugString(tmpBuf);
    }
    
    获取焦点
    ::SetFocus(hRichEdit);
}

3. ReichEdit控件事件处理
3.1 实时获取控件大小,并修改控件大小(在父类消息处理函数中处理WM_NOTIFY消息)
LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        ...
        case WM_NOTIFY:
            {
                LPNMHDR nmhdr = (LPNMHDR)lParam;
                if (nmhdr->code == EN_REQUESTRESIZE) {
                    REQRESIZE* pReqResize = (REQRESIZE*)lParam;
                    int iWidth = pReqResize->rc.right - pReqResize->rc.left;
                    int iHeight = pReqResize->rc.bottom - pReqResize->rc.top; 
                    TCHAR szText[4096 + 1] = {0};
                    int iCharNum = GetWindowText(hRichEdit, szText, 4096);
                    int cx = iCharNum * 18 * 2; //18代表控件上的字宽
                    RECT winRect;
                    GetWindowRect(hWnd, &winRect);
                    POINT pRB = {winRect.right, winRect.bottom};
                    ScreenToClient(hWnd, &pRB);
                    int iMaxWidth = pRB.x - pReqResize->rc.left;
                    if (cx > iMaxWidth)
                        iWidth = iMaxWidth;
                    else
                        iWidth = cx;
                    ::MoveWindow(hRichEdit, pReqResize->rc.left, pReqResize->rc.top, iWidth, iHeight, TRUE);
                }
            }
            breeak; 

case WM_KEYDOWN: {
            TCHAR tmpBuf[128] = {0};

            if (wParam == VK_RETURN) {
                wsprintf(tmpBuf, L"回车键\n");
                OutputDebugString(tmpBuf);
            } else if (wParam == VK_BACK) {
                wsprintf(tmpBuf, L"回格键\n");
                OutputDebugString(tmpBuf);
            }
        } break;

        ...
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}


4. 卸载RICHED20.dll
void UnInitRichEditCtrlModule()
{
    if (m_hRichEditDll)
        FreeLibrary(m_hRichEditDll);
    m_hRichEditDll = NULL;
}

//windows操作系统dpi换算
static int s_iDPI = ::GetDeviceCaps(::GetDC(NULL), LOGPIXELSX);
#define GDIWIDTH(i) (i * (s_iDPI / 96))
//通过控件句柄和控件上的字体获取控件宽度
static UINT GetStringWidth(const HWND& hWnd, const std::wstring& szStr, const HFONT& hFont) {
    TCHAR tmpBuf[128] = {0};
    if (NULL == hFont)
        OutputDebugString(L"NULL ============ hFont\n");
    if (!hFont || szStr.empty())
        return 0;

    HDC hdc = GetDC(NULL);
    HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);

    SIZE size = {0};
    int nCount = szStr.size();
    ::GetTextExtentPoint32(hdc, szStr.c_str(), nCount, &size);
    SelectObject(hdc, hOldFont);
    ReleaseDC(NULL, hdc);

    wsprintf(tmpBuf, L" =======> szStr [%s] nCount [%s] cx [%d]\n", szStr.c_str(), nCount, size.cx);
    OutputDebugString(tmpBuf);

    return size.cx;
}
 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

hsy12342611

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值