Форматирование текста в WinForm Label

Можно ли отформатировать определенный текст в метке WinForm вместо того, чтобы разбивать текст на несколько меток? Не обращайте внимания на HTML-теги в тексте ярлыка; это используется только для того, чтобы выразить мою точку зрения.

Например:

Dim myLabel As New Label
myLabel.Text = "This is <b>bold</b> text.  This is <i>italicized</i> text."

В результате текст на этикетке будет выглядеть так:

This is bold text. This is italicized text.

Брайан, если вы использовали №2 или №3 ответа Дэнни, не могли бы вы поделиться кодом или ссылкой на то, что вы использовали? Спасибо.

FastAl 27.02.2012 20:35

@FastAl Думаю, я только что использовал №1, но, возможно, использовал №3. У меня больше нет доступа к базе кода, поэтому я не могу привести пример. Извини.

Bryan Roth 09.03.2012 02:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
21
2
47 368
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Мне также было бы интересно узнать, возможно ли это.

Когда мы не могли найти решение, мы прибегали к элементу управления SuperLabel компонентов Ones, который позволяет разметку HTML в метке.

Ответ принят как подходящий

Это невозможно с ярлыком WinForms как таковым. На этикетке должен быть ровно один шрифт, ровно одного размера и одного начертания. У вас есть несколько вариантов:

  1. Используйте отдельные ярлыки
  2. Создайте новый производный от Control класс, который выполняет свой собственный рисунок через GDI +, и используйте его вместо Label; это, вероятно, ваш лучший вариант, поскольку он дает вам полный контроль над тем, как указать элементу управления форматировать его текст
  3. Используйте сторонний элемент управления ярлыком, который позволит вам вставлять фрагменты HTML (их много - проверьте CodeProject); это будет чья-то реализация №2.

Не совсем, но вы можете подделать его с помощью RichTextBox, доступного только для чтения, без границ. RichTextBox поддерживает Rich Text Format (RTF).

  1. Создайте текст как файл RTF в Wordpad
  2. Создать элемент управления Rich text без границ и editable = false
  3. Добавьте файл RTF в проект в качестве ресурса
  4. В Form1_load делаем

    myRtfControl.Rtf = Resource1.MyRtfControlText

Хороший аргумент в пользу использования wordpad! Небольшое осложнение: он генерирует много мусора, что немного затрудняет понимание результирующего rtf (но может быть безопасно удалено) ... Лучше, чем чтение "спецификации" rtf.

sharpener 29.10.2014 21:02

@sharpener Вы должны увидеть rtf, который создает MS Word ... просто открыв его в Wordpad и нажав «сохранить», вы значительно уменьшите его, иногда даже до 10% от исходного размера файла. А нет, я только желание пошутил или преувеличил там X_x

Nyerguds 31.03.2016 17:03

Есть отличная статья 2009 года в Code Project под названием "Профессиональный HTML-рендерер, который вы будете использовать", которая реализует нечто похожее на то, что хочет исходный плакат.

Я успешно использую его в нескольких наших проектах.

Понимая, что это старый вопрос, мой ответ больше для тех, кто, как я, все еще может искать такие решения и наткнуться на этот вопрос.

Помимо того, что уже упоминалось, DevExpress LabelControl - это метка, которая поддерживает это поведение - демо здесь. Увы, это часть платной библиотеки.

Если вы ищете бесплатные решения, я считаю, что HTML-рендерер - следующая лучшая вещь.

Когда мы использовали общие элементы управления DevExpress, у них были огромные проблемы с темами. Мол, их легко заставить использовать какую-то странную тему, но сложно сделать так, чтобы они выглядели так же, как текущая ОС.

hypersw 13.08.2015 22:19

Очень простое решение:

  1. Добавьте в форму 2 метки: LabelA и LabelB.
  2. Перейдите в свойства LabelA и закрепите его слева.
  3. Перейдите в свойства LabelB и также закрепите его слева.
  4. Установите жирный шрифт для LabelA.

Теперь LabelB будет смещаться в зависимости от длины текста LabelA.

Вот и все.

Другой обходной путь, поздно для вечеринки: если вы не хотите использовать сторонний элемент управления, и вы просто хотите привлечь внимание к некоторому тексту на вашей этикетке, и, вы в порядке с подчеркиванием, вы можете использовать а LinkLabel.

Обратите внимание, что многие считают это «преступление юзабилити», но если вы не разрабатываете что-то для конечного пользователя, то, возможно, вы готовы оставить это на своей совести.

Уловка состоит в том, чтобы добавить отключенные ссылки к тем частям вашего текста, которые вы хотите подчеркнуть, а затем глобально установить цвета ссылок, чтобы они соответствовали остальной части метки. Вы можете установить почти все необходимые свойства во время разработки, кроме части Links.Add(), но здесь они находятся в коде:

linkLabel1.Text = "You are accessing a government system, and all activity " +
                  "will be logged.  If you do not wish to continue, log out now.";
linkLabel1.AutoSize = false;
linkLabel1.Size = new Size(365, 50);
linkLabel1.TextAlign = ContentAlignment.MiddleCenter;
linkLabel1.Links.Clear();
linkLabel1.Links.Add(20, 17).Enabled = false;   // "government system"
linkLabel1.Links.Add(105, 11).Enabled = false;  // "log out now"
linkLabel1.LinkColor = linkLabel1.ForeColor;
linkLabel1.DisabledLinkColor = linkLabel1.ForeColor;

Результат:

О, замечательно. Я никогда не знал, что метки ссылок могут иметь определенные области в качестве ссылок. На самом деле это намного ближе к варианту использования, который я искал, чем вопрос, заданный здесь; мой ярлык все равно был доступен для кликов. Гораздо лучше, ведь теперь всего одна интерактивная область.

Nyerguds 31.03.2016 16:40

FlowLayoutPanel хорошо подходит для вашей проблемы. Если вы добавите метки на панель потока и отформатируете свойства шрифта и поля каждой метки, тогда у вас могут быть разные стили шрифтов. Довольно быстрое и простое решение для начала работы.

Сработанное решение для меня - использование настраиваемого RichEditBox. При правильных свойствах это будет выглядеть как простая этикетка с полужирным шрифтом.

1) Сначала добавьте свой собственный класс RichTextLabel с отключенной вставкой:

public class RichTextLabel : RichTextBox
{
    public RichTextLabel()
    {
        base.ReadOnly = true;
        base.BorderStyle = BorderStyle.None;
        base.TabStop = false;
        base.SetStyle(ControlStyles.Selectable, false);
        base.SetStyle(ControlStyles.UserMouse, true);
        base.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

        base.MouseEnter += delegate(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
        };
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x204) return; // WM_RBUTTONDOWN
        if (m.Msg == 0x205) return; // WM_RBUTTONUP
        base.WndProc(ref m);
    }
}

2) Разбивает ваше предложение на слова с флагом IsSelected, который определяет, должно ли это слово быть жирным или нет:

        private void AutocompleteItemControl_Load(object sender, EventArgs e)
    {
        RichTextLabel rtl = new RichTextLabel();
        rtl.Font = new Font("MS Reference Sans Serif", 15.57F);
        StringBuilder sb = new StringBuilder();
        sb.Append(@"{\rtf1\ansi ");
        foreach (var wordPart in wordParts)
        {
            if (wordPart.IsSelected)
            {
                sb.Append(@"\b ");
            }
            sb.Append(ConvertString2RTF(wordPart.WordPart));
            if (wordPart.IsSelected)
            {
                sb.Append(@"\b0 ");
            }
        }
        sb.Append(@"}");

        rtl.Rtf = sb.ToString();
        rtl.Width = this.Width;
        this.Controls.Add(rtl);
    }

3) Добавить функцию для преобразования текста в допустимый rtf (с поддержкой юникода!):

   private string ConvertString2RTF(string input)
    {
        //first take care of special RTF chars
        StringBuilder backslashed = new StringBuilder(input);
        backslashed.Replace(@"\", @"\");
        backslashed.Replace(@"{", @"\{");
        backslashed.Replace(@"}", @"\}");

        //then convert the string char by char
        StringBuilder sb = new StringBuilder();
        foreach (char character in backslashed.ToString())
        {
            if (character <= 0x7f)
                sb.Append(character);
            else
                sb.Append("\u" + Convert.ToUInt32(character) + "?");
        }
        return sb.ToString();
    }

Sample

Для меня работает как шарм! Решения составлены из:

Как преобразовать строку в RTF на C#?

Форматирование текста в поле RTF

Как скрыть курсор в RichTextBox?

Это лучшее доступное решение, если вы хотите оставаться максимально легким и избегать сторонних зависимостей. Я протестировал несколько альтернатив, и этот метод работает лучше всего, а также правильно обрабатывает .AutoSize и .WordWrap, как обычный ярлык. Я также встроил простую функцию конвертера HTML в RTF, которая обрабатывает прямые замены с помощью основных тегов (выделение жирным шрифтом, курсив и т. д.), Поэтому мне вообще не нужно запоминать формат RTF. Я просто загружаю строку в формате HTML.

Special Sauce 22.04.2017 05:17

Да. Вы можете реализовать, используя HTML Render. Видите, нажмите на ссылку: https://htmlrenderer.codeplex.com/ Надеюсь, это будет полезно.

AutoRichLabel

      AutoRichLabel with formatted RTF content

Я решил эту проблему, построив UserControl, который содержит TransparentRichTextBox, доступный только для чтения. TransparentRichTextBox - это RichTextBox, который позволяет быть прозрачным:

TransparentRichTextBox.cs:

public class TransparentRichTextBox : RichTextBox
{
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr LoadLibrary(string lpFileName);

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams prams = base.CreateParams;
            if (TransparentRichTextBox.LoadLibrary("msftedit.dll") != IntPtr.Zero)
            {
                prams.ExStyle |= 0x020; // transparent 
                prams.ClassName = "RICHEDIT50W";
            }
            return prams;
        }
    }
}

Последний UserControl действует как оболочка для TransparentRichTextBox. К сожалению, мне пришлось ограничиться AutoSize по своему усмотрению, потому что AutoSize у RichTextBox сломался.

AutoRichLabel.designer.cs:

partial class AutoRichLabel
{
    /// <summary> 
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// Clean up any resources being used.
    /// </summary>
    /// <param name = "disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Component Designer generated code

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.rtb = new TransparentRichTextBox();
        this.SuspendLayout();
        // 
        // rtb
        // 
        this.rtb.BorderStyle = System.Windows.Forms.BorderStyle.None;
        this.rtb.Dock = System.Windows.Forms.DockStyle.Fill;
        this.rtb.Location = new System.Drawing.Point(0, 0);
        this.rtb.Margin = new System.Windows.Forms.Padding(0);
        this.rtb.Name = "rtb";
        this.rtb.ReadOnly = true;
        this.rtb.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
        this.rtb.Size = new System.Drawing.Size(46, 30);
        this.rtb.TabIndex = 0;
        this.rtb.Text = "";
        this.rtb.WordWrap = false;
        this.rtb.ContentsResized += new System.Windows.Forms.ContentsResizedEventHandler(this.rtb_ContentsResized);
        // 
        // AutoRichLabel
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
        this.BackColor = System.Drawing.Color.Transparent;
        this.Controls.Add(this.rtb);
        this.Name = "AutoRichLabel";
        this.Size = new System.Drawing.Size(46, 30);
        this.ResumeLayout(false);

    }

    #endregion

    private TransparentRichTextBox rtb;
}

AutoRichLabel.cs:

/// <summary>
/// <para>An auto sized label with the ability to display text with formattings by using the Rich Text Format.</para>
/// <para>­</para>
/// <para>Short RTF syntax examples: </para>
/// <para>­</para>
/// <para>Paragraph: </para>
/// <para>{\pard This is a paragraph!\par}</para>
/// <para>­</para>
/// <para>Bold / Italic / Underline: </para>
/// <para>\b bold text\b0</para>
/// <para>\i italic text\i0</para>
/// <para>\ul underline text\ul0</para>
/// <para>­</para>
/// <para>Alternate color using color table: </para>
/// <para>{\colortbl ;\red0\green77\blue187;}{\pard The word \cf1 fish\cf0  is blue.\par</para>
/// <para>­</para>
/// <para>Additional information: </para>
/// <para>Always wrap every text in a paragraph. </para>
/// <para>Different tags can be stacked (i.e. \pard\b\i Bold and Italic\i0\b0\par)</para>
/// <para>The space behind a tag is ignored. So if you need a space behind it, insert two spaces (i.e. \pard The word \bBOLD\0  is bold.\par)</para>
/// <para>Full specification: http://www.biblioscape.com/rtf15_spec.htm </para>
/// </summary>
public partial class AutoRichLabel : UserControl
{
    /// <summary>
    /// The rich text content. 
    /// <para>­</para>
    /// <para>Short RTF syntax examples: </para>
    /// <para>­</para>
    /// <para>Paragraph: </para>
    /// <para>{\pard This is a paragraph!\par}</para>
    /// <para>­</para>
    /// <para>Bold / Italic / Underline: </para>
    /// <para>\b bold text\b0</para>
    /// <para>\i italic text\i0</para>
    /// <para>\ul underline text\ul0</para>
    /// <para>­</para>
    /// <para>Alternate color using color table: </para>
    /// <para>{\colortbl ;\red0\green77\blue187;}{\pard The word \cf1 fish\cf0  is blue.\par</para>
    /// <para>­</para>
    /// <para>Additional information: </para>
    /// <para>Always wrap every text in a paragraph. </para>
    /// <para>Different tags can be stacked (i.e. \pard\b\i Bold and Italic\i0\b0\par)</para>
    /// <para>The space behind a tag is ignored. So if you need a space behind it, insert two spaces (i.e. \pard The word \bBOLD\0  is bold.\par)</para>
    /// <para>Full specification: http://www.biblioscape.com/rtf15_spec.htm </para>
    /// </summary>
    [Browsable(true)]
    public string RtfContent
    {
        get
        {
            return this.rtb.Rtf;
        }
        set
        {
            this.rtb.WordWrap = false; // to prevent any display bugs, word wrap must be off while changing the rich text content. 
            this.rtb.Rtf = value.StartsWith(@"{\rtf1") ? value : @"{\rtf1" + value + "}"; // Setting the rich text content will trigger the ContentsResized event. 
            this.Fit(); // Override width and height. 
            this.rtb.WordWrap = this.WordWrap; // Set the word wrap back. 
        }
    }

    /// <summary>
    /// Dynamic width of the control. 
    /// </summary>
    [Browsable(false)]
    public new int Width
    {
        get
        {
            return base.Width;
        } 
    }

    /// <summary>
    /// Dynamic height of the control. 
    /// </summary>
    [Browsable(false)]
    public new int Height
    {
        get
        {
            return base.Height;
        }
    }

    /// <summary>
    /// The measured width based on the content. 
    /// </summary>
    public int DesiredWidth { get; private set; }

    /// <summary>
    /// The measured height based on the content. 
    /// </summary>
    public int DesiredHeight { get; private set; }

    /// <summary>
    /// Determines the text will be word wrapped. This is true, when the maximum size has been set. 
    /// </summary>
    public bool WordWrap { get; private set; }

    /// <summary>
    /// Constructor. 
    /// </summary>
    public AutoRichLabel()
    {
        InitializeComponent();
    }

    /// <summary>
    /// Overrides the width and height with the measured width and height
    /// </summary>
    public void Fit()
    {
        base.Width = this.DesiredWidth;
        base.Height = this.DesiredHeight;
    }

    /// <summary>
    /// Will be called when the rich text content of the control changes. 
    /// </summary>
    private void rtb_ContentsResized(object sender, ContentsResizedEventArgs e)
    {
        this.AutoSize = false; // Disable auto size, else it will break everything
        this.WordWrap = this.MaximumSize.Width > 0; // Enable word wrap when the maximum width has been set. 
        this.DesiredWidth = this.rtb.WordWrap ? this.MaximumSize.Width : e.NewRectangle.Width; // Measure width. 
        this.DesiredHeight = this.MaximumSize.Height > 0 && this.MaximumSize.Height < e.NewRectangle.Height ? this.MaximumSize.Height : e.NewRectangle.Height; // Measure height. 
        this.Fit(); // Override width and height. 
    }
}

Синтаксис расширенного текстового формата довольно прост:

Пункт:

{\pard This is a paragraph!\par}

Полужирный / курсив / подчеркнутый текст:

\b bold text\b0
\i italic text\i0
\ul underline text\ul0

Альтернативный цвет с помощью таблицы цветов:

{\colortbl ;\red0\green77\blue187;}
{\pard The word \cf1 fish\cf0  is blue.\par

Но учтите: всегда заключайте каждый текст в абзац. Кроме того, можно складывать разные теги (например, \pard\b\i Bold and Italic\i0\b0\par), а пробел после тега игнорируется. Поэтому, если вам нужно пространство позади него, вставьте два пробела (например, \pard The word \bBOLD\0 is bold.\par). Чтобы избежать \, { или }, используйте ведущий \. Для получения дополнительной информации существует полная спецификация форматированного текста онлайн.

Используя этот довольно простой синтаксис, вы можете создать что-то вроде того, что вы видите на первом изображении. Форматированный текстовый контент, который был прикреплен к свойству RtfContent моего AutoRichLabel на первом изображении, был:

{\colortbl ;\red0\green77\blue187;}
{\pard\b BOLD\b0  \i ITALIC\i0  \ul UNDERLINE\ul0 \\\{\}\par}
{\pard\cf1\b BOLD\b0  \i ITALIC\i0  \ul UNDERLINE\ul0\cf0 \\\{\}\par}

AutoRichLabel with formatted RTF content

Если вы хотите включить перенос слов, установите желаемый размер для максимальной ширины. Однако это зафиксирует максимальную ширину, даже если текст короче.

Веселиться!

Другие вопросы по теме