You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用RichEdit控件文本选择光标并保留超链接手型光标

我想在RichEdit控件中显示标准"pointer"箭头光标,替代默认的"文本选择光标"(如下图所示):
enter image description here

目前我能想到的唯一方案是在窗口中拦截WM_SETCURSOR消息,判断光标处于RichEdit控件范围内时将其替换为普通箭头光标。但该方案不够简便,同时我需要保留光标指向超链接时显示的手型光标。

请问是否有更简单的实现方法?

更新:针对评论的补充说明:

  • @Remy Lebeau:我实际需要的是具备以下能力的文本展示控件:自动换行、同段文本内不同字符可设置不同颜色、支持超链接、可按需展示图片,且需要支持加载网络文本、在单个控件内展示,同时可以通过写字板这类RTF编辑器快速生成对应内容。但RichEdit内展示的信息不允许编辑或复制,去掉文本选择光标更符合应用设计需求,所以我认为RichEdit是合适的选择,当然也欢迎推荐其他替代方案。
  • @Jeaninez:我已经设置了ES_READONLY属性,但它既不会改变光标样式,也不会禁止文本选中,后者我已经通过拦截EN_SELCHANGE通知解决了。
  • @Barmak Shemirani:我可以处理超链接事件,目前我使用的光标切换代码片段如下:
// 该方法处理WM_SETCURSOR消息
LRESULT MainWindow::OnSetCursor(WPARAM wParam, LPARAM lParam) {
    auto h = (HWND)wParam;
    if (h == richEditHwnd) {
        return TRUE; // 阻止后续处理器修改光标
    }
    return DefWindowProc(mainWindowHandle, WM_SETCURSOR, wParam, lParam);
}

更新2:根据Barmak Shemirani在评论中的提示,ENLINK通知可由鼠标事件触发,目前我已经有了接近可用的方案(不过我还没完全搞懂其运行逻辑):

WM_SETCURSOR处理函数:

LRESULT MainWindow::OnSetCursor(WPARAM wParam, LPARAM lParam)
{
    auto h = (HWND)(wParam);
    if (rich.hwnd == h) {
        if (HIWORD(lParam) == WM_MOUSEMOVE || HIWORD(lParam) == WM_LBUTTONDOWN || HIWORD(lParam)== WM_LBUTTONDBLCLK) {
            DefWindowProc(windowHandle, WM_SETCURSOR, wParam, lParam);
            auto cursor = LoadCursor(NULL, IDC_ARROW);
            SetClassLongPtr(rich.hwnd, GCLP_HCURSOR, (LONG_PTR)cursor);
            return true;
        }
    }                

    return DefWindowProc(windowHandle, WM_SETCURSOR, wParam, lParam);
}

EM_LINK通知处理函数:

auto enLink = (ENLINK*)lParam;
if (enLink->msg == WM_LBUTTONUP) {
    std::wstring linkId(enLink->chrg.cpMax - enLink->chrg.cpMin, L'0');
    TEXTRANGE textRange{enLink->chrg, (LPTSTR)linkId.data()};
    SendMessage(nmHeader->hwndFrom, EM_GETTEXTRANGE, NULL, reinterpret_cast<LPARAM>(&textRange));
    ProcessLinkClick(enLink, linkId);
}
else if (enLink->msg == WM_MOUSEMOVE || enLink->msg == WM_LBUTTONDBLCLK || enLink->msg == WM_LBUTTONDOWN) {
    auto cursor = LoadCursor(NULL, IDC_HAND);
    SetClassLongPtr(enLink->nmhdr.hwndFrom, GCLP_HCURSOR, (LONG_PTR)cursor);
    return TRUE;
}

return 0;

这段代码在lParam为WM_MOUSEMOVE和WM_LBUTTONDOWN时运行正常,但处理WM_LBUTTONDBLCLK时会失效。

更新3:
我之前推出的代码过于仓促,它会阻塞EM_LINK通知的WM_LBUTTONUP消息,导致我无法正常处理超链接点击事件。


内容的提问来源于stack exchange,提问作者qloq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:54:03