在Windows 10 1803上的RichTextBox中没有下划线的超链接

时间:2018-05-17 11:17:35

标签: c# .net winapi richtextbox rtf

我在fseek($handle,0);("已升级"到RichTextBox)中显示RTF文档。文档中的关键字使用语法链接到网页:

RichEdit50W

我不想强调关键字。在Windows 10版本1803(以及所有以前版本的Windows,包括XP,Vista,8)中,只要在锚点上设置了颜色(注意{\field{\*\fldinst{HYPERLINK ""https://www.example.com/"" }}{\fldrslt{\cf1 keyword\cf0 }}} ),锚点就不会加下划线。

但是这在Windows 10版本1803中不再有效。我将向Microsoft报告此情况。但我不确定,如果我不依赖于无证件的行为。我可以想象这个改变实际上不是一个错误,而是一个修复。所以我想知道是否有更正确的方法来防止超链接加下划线。

示例代码:

\cf1
Windows 10版本1803上的

(不需要的)结果:

enter image description here

Windows 10版本1706上的

(所需)结果:

enter image description here

和Windows 7上的相同结果:

enter image description here

1 个答案:

答案 0 :(得分:4)

对于Windows 8及更高版本,您可以使用SendMessage functionEM_SETEDITSTYLEEX message发送到richedit控件,以通过为lParam参数指定SES_EX_HANDLEFRIENDLYURL来禁用友好链接的下划线,并为0 wParam`论证。

SES_EX_HANDLEFRIENDLYURL

  

使用相同的文本颜色显示友好名称链接并在自动链接下划线,前提是不使用临时格式或使用文本autocolor(默认值:0)。

即使默认情况下禁用下划线,RichTextBox控件也会启用它。

将以下内容添加到ExRichText类,以提供禁用下划线的方法(UnderlineFriendlyLink)。

private const Int32 WM_User = 0x400;
private const Int32 EM_SETEDITSTYLEEX = WM_User + 275;
private const Int32 EM_GETEDITSTYLEEX = WM_User + 276;

/// <summary>Display friendly name links with the same text color and underlining as automatic links, provided that temporary formatting isn’t used or uses text autocolor (default: 0)</summary>
private const Int32 SES_EX_HANDLEFRIENDLYURL = 0x100;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private extern static Int32 SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Int32 lParam);

public static void UnderlineFriendlyLink(RichTextBox rtb, bool enabled = false)
{
    if (rtb.IsHandleCreated)
    {
        Int32 wParam = enabled ? SES_EX_HANDLEFRIENDLYURL : 0;
        Int32 lParam = SES_EX_HANDLEFRIENDLYURL; // settings mask
        Int32 res = SendMessage(new HandleRef(null, rtb.Handle), EM_SETEDITSTYLEEX, wParam, lParam);
    }
}

使用示例:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        exRichText1.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}{\colortbl ;\red0\green0\blue255;}{\*\generator Riched20 10.0.16299}\viewkind4\uc1 \pard\f0\fs29 Hello {\b{\field{\*\fldinst{HYPERLINK ""http://www.fred.com""}}{\fldrslt{Link}}}}\f0\fs29\par\par https://www.google.com \par\par sd {{\field{\*\fldinst{HYPERLINK ""http://www.fred.com""}}{\fldrslt{klasl}}}}\f0\fs29  wed asdasd \par\par}";
    }

    private void exRichText1_LinkClicked(object sender, LinkClickedEventArgs e)
    {
        System.Diagnostics.Debug.Print(e.LinkText);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ExRichText.UnderlineFriendlyLink(exRichText1, false);
    }
}

您的帖子未说明您是如何检测链接的点击,但请注意,如果您依赖上面示例中显示的LinkClicked事件,该事件可能会由于RichTextBox CharRangeToString method中的逻辑错误而无法触发。特别是这段代码片段。

        //Windows bug: 64-bit windows returns a bad range for us.  VSWhidbey 504502.  
        //Putting in a hack to avoid an unhandled exception.
        if (c.cpMax > Text.Length || c.cpMax-c.cpMin <= 0) {
            return string.Empty;
        }

如果您尝试示例代码,您会注意到事件仅针对第一个链接触发。如果CharRangeToString返回String.Empty,则不会引发该事件。此限制条件使用Text.Length属性(示例为58),返回显示的长度。我认为它应该使用TextLength属性(示例为120)。

通过监视控件的父级以获取EM_Notify消息并处理鼠标单击通知,可以在编译x86或AnyCPU(更喜欢32位)时使用CharRange结构提取链接。当作为64位程序集运行时,CharRange结构会返回无效值,如源代码中所示。

编辑:所有测试均在Windows 10版本1706上完成,因为此时我不会安装1803。