【问题标题】:How to disable "text-selection" cursor in RichEdit如何在 RichEdit 中禁用“文本选择”光标
【发布时间】:2023-03-30 09:44:01
【问题描述】:

我想在 RichEdit 中显示标准的“指针”光标而不是“文本选择光标”(如下图所示):

我现在看到的唯一方法是在我的窗口中拦截WM_SETCURSOR 消息,确定光标是否在 RichEdit 控件内,并将其替换为“正常”光标。除了不那么酷之外,我还想保留一个“手”光标,当光标指向链接时会出现。

有没有更简单的方法?

更新:对 cme​​ts 的一些说明:

  1. @Remy Lebeau。实际上,我只想显示具有一些格式化功能的文本:自动换行,相同文本中某些符号的不同颜色,超链接,并且可能是 - 显示图像。我想从互联网上获取这个文本,在一个控件中显示这个文本,在 RTF 编辑器中创建这样的文本也很舒服,比如写字板。然而,RichEdit 中显示的信息并非用于编辑或复制,并且应用程序设计在没有“文本选择”光标的情况下看起来会更好。所以,我认为 RichEdit 是我所需要的。但是,当然,您可以提出其他建议。
  2. @Jeaninez。我已经设置了ES_READONLY 属性,它既不影响光标,也不影响选择(我通过拦截EN_SELCHANGE 通知解决了后者)。
  3. @Barmak Shemirani。是的,我可以处理超链接。这是我现在用来处理光标更改的代码 sn-p:
    // This method processes the WM_SETCURSOR message.
    LRESULT MainWindow::OnSetCursor(WPARAM wParam, LPARAM lParam) {
        auto h = (HWND)wParam;
        if (h == richEditHwnd) {
            return TRUE; // Prevents cursor changes by next processors
        }
        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;

此代码适用于 WM_MOUSEMOVEWM_LBUTTONDOWN LPARAM 参数,但在 WM_LBUTTONDBLCLK 参数上失败。

更新 3: 似乎我匆忙使用以前的代码 - 它以某种方式阻止了 EM_LINK 通知的 WM_LBUTTONUP 消息,因此我无法正确处理链接点击。

【问题讨论】:

  • 你为什么要这个?当鼠标悬停在文本输入字段上时显示文本光标是标准的 UI 行为,也是用户所期望的。为什么要改变它?
  • 也许你想添加样式ES_READONLY。将手形光标放在只读 Richedit 控件中的超链接上是有意义的。您是否管理过超链接重定向?我应该是类似的方法。显示代码,或至少显示您正在使用的部分代码。
  • 根据你的描述,是否要让richedit不选择?如果是这样,我建议你可以尝试使用EM_SETREADONLY message来设置编辑控件的只读样式。
  • 当您将@user 放入问题中时,不会通知评论者。我的意思是你有什么WM_NOTIFY

标签: c++ winapi richedit


【解决方案1】:

这是评论,不回答问题

不要覆盖 WM_SETCURSOR,让 RichEdit 处理它,“Hand”光标应自动显示超链接。

您可以覆盖光标并强制它使用“箭头”光标。但是richedit 将不再显示超链接的“Hand”光标(因为覆盖)这个覆盖可以如下完成:

hcursor = LoadCursor(nullptr, MAKEINTRESOURCE(IDC_ARROW));
...
case WM_SETCURSOR:
{
    if (hrichedit == (HWND)wparam) { SetCursor(hcursor); return TRUE; }
    break;
}

否则我们必须找出鼠标在超链接上的时间。我不知道如何顺利​​地做到这一点。

理论上,当我们进入/退出链接时,我们可以捕捉到 mousemove 的 WM_NOTIFY 消息,但我很难做到这一点。

【讨论】:

  • 我将此答案降级为评论!
猜你喜欢
  • 2012-06-25
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 2021-10-04
  • 2014-04-10
  • 2012-01-24
相关资源
最近更新 更多