Гиперссылки без подчеркивания в RichTextBox в Windows 10 1803 - PullRequest
0 голосов
/ 17 мая 2018

Я отображаю RTF-документ в RichTextBox («обновлен» до RichEdit50W).Ключевые слова в документе связаны с веб-страницей с использованием синтаксиса:

{\field{\*\fldinst{HYPERLINK ""https://www.example.com/"" }}{\fldrslt{\cf1 keyword\cf0 }}}

Я не хочу подчеркивать ключевые слова.До версии Windows 10 1803 (и во всех предыдущих версиях Windows, включая XP, Vista, 8), всякий раз, когда цвет был установлен на привязке (обратите внимание на \cf1), привязка не была подчеркнута.

Но это больше не работает в Windows 10 версии 1803. Я собираюсь сообщить об этом в Microsoft.Но я не совсем уверен, если бы я не полагался на недокументированное поведение.Я могу представить, что это изменение на самом деле не ошибка, а скорее исправление.Поэтому мне интересно, не существует ли более правильного способа запретить подчеркивание гиперссылок.

Пример кода:

public class ExRichText : RichTextBox
{
    [DllImport("kernel32.dll", EntryPoint = "LoadLibraryW", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern IntPtr LoadLibraryW(string path);

    protected override CreateParams CreateParams
    {
        get
        {
            var cp = base.CreateParams;
            LoadLibraryW("MsftEdit.dll");
            cp.ClassName = "RichEdit50W";
            return cp;
        }
    }
}

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

        ExRichText rtb = new ExRichText();
        rtb.Parent = this;
        rtb.SetBounds(10, 10, 200, 100);
        rtb.Rtf = @"{\rtf1 {\colortbl ;\red255\green0\blue0;}bar {\field{\*\fldinst{HYPERLINK ""https://www.example.com/"" }}{\fldrslt{\cf1 link\cf0 }}} bar}";
    }
}

(нежелательный) результат в Windows 10 версии 1803:

enter image description here

(желательный) результат для Windows 10 версии 1706:

enter image description here

итот же результат в Windows 7:

enter image description here

1 Ответ

0 голосов
/ 25 мая 2018

Для Windows 8 и выше, вы можете использовать функцию SendMessage , чтобы отправить сообщение EM_SETEDITSTYLEEX в элемент управления richedit, чтобы отключить подчеркивание дружественных ссылок, указав SES_EX_HANDLEFRIENDLYURL для lParam аргумент и ноль для аргумента wParam`.

SES_EX_HANDLEFRIENDLYURL

Отображать дружественные именные ссылки с тем же цветом текста и подчеркиванием, что и автоматические ссылки, при условии, что временное форматирование не используется или использует автоцвет цвета текста (по умолчанию: 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 . В частности этот фрагмент кода.

        //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 и обрабатывая уведомление о щелчке мыши, можно извлечь ссылку с использованием структуры CharRange при компиляции для x86 или AnyCPU (предпочтительнее 32-битный). При работе в качестве 64-битной сборки структура CharRange возвращает недопустимые значения, как указано в исходном коде.


Редактировать: Все тестирование проводилось на Windows 10 версии 1706, так как я не буду устанавливать 1803. В настоящее время

...