【问题标题】:Formatting text in WinForm Label格式化 WinForm 标签中的文本
【发布时间】:2010-09-05 21:28:14
【问题描述】:

是否可以在 WinForm 标签中格式化某些文本,而不是将文本分成多个标签?请忽略标签文本中的 HTML 标签;它只是用来说明我的观点。

例如:

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

这会将标签中的文本生成为:

这是粗体文字。这是 斜体文本。

【问题讨论】:

  • Bryan,如果您使用了 Danny 答案的 #2 或 #3,您介意分享您使用的代码或链接吗?谢谢。
  • @FastAl 我相信我刚刚使用了#1,但我可能使用了#3。我无法再访问代码库,因此无法提供示例。对不起。

标签: winforms text formatting label


【解决方案1】:

WinForms 标签无法做到这一点。标签必须只有一种字体,一种尺寸和一张脸。您有两种选择:

  1. 使用单独的标签
  2. 创建一个新的 Control 派生类,该类通过 GDI+ 进行自己的绘图并使用它而不是 Label;这可能是您最好的选择,因为它可以让您完全控制如何指示控件格式化其文本
  3. 使用第三方标签控件,可以让您插入 HTML sn-ps(有一堆 - 检查 CodeProject);这将是其他人对 #2 的实现。

【讨论】:

    【解决方案2】:

    并非如此,但您可以使用只读的无边框 RichTextBox 来伪造它。 RichTextBox 支持富文本格式 (rtf)。

    【讨论】:

      【解决方案3】:

      另一种解决方法,迟到了:如果您不想使用第三方控件,并且只想引起对标签中某些文本的注意,你可以使用下划线,你可以使用LinkLabel

      请注意,许多人认为这是“usability crime”,但如果您不是为最终用户消费而设计的东西,那么它可能是您良心所愿。

      诀窍是将禁​​用的链接添加到您想要下划线的文本部分,然后全局设置链接颜色以匹配标签的其余部分。除了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;
      

      结果:

      【讨论】:

      • 哦,太好了。我从来不知道链接标签可以将特定区域作为链接。这实际上比这里提出的实际问题更接近我正在搜索的用例;无论如何,我的标签是可点击的。现在只需一个可点击区域就更好了。
      【解决方案4】:

      为我工作的解决方案 - 使用自定义 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 的功能(支持 unicode!):

         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();
          }
      

      对我来说就像一个魅力! 解决方案编译自:

      How to convert a string to RTF in C#?

      Format text in Rich Text Box

      How to hide the caret in a RichTextBox?

      【讨论】:

      • 如果您想尽可能保持轻量级并避免第三方依赖,这是可用的最佳解决方案。我测试了多种替代方法,这种方法效果最好,并且像普通标签一样正确处理 .AutoSize 和 .WordWrap 。我还内置了一个简单的 HTML 到 RTF 的转换器函数,它处理基本标记(粗体、斜体等)的直接替换,所以我根本不需要记住 RTF 格式。我只是加载 HTML 格式的字符串。
      【解决方案5】:
      1. 在写字板中将文本创建为 RTF 文件
      2. 创建没有边框且可编辑的富文本控件 = false
      3. 将 RTF 文件作为资源添加到项目中
      4. 在Form1_load中做

        myRtfControl.Rtf = Resource1.MyRtfControlText

      【讨论】:

      • 写字板用法很好!小复杂:它会产生很多垃圾,这使得理解生成的 rtf 有点困难(但可以安全地删除)......比阅读 rtf“规范”更好。
      • @sharpener 您应该会看到 MS Word 生成的 rtf... 只需在写字板中打开它并按“保存”即可极大地减少它,有时甚至减少到原始文件大小的 10%。不,我只是希望我是在开玩笑或夸大其词 X_x
      【解决方案6】:

      AutoRichLabel

            

      我通过构建一个包含只读的TransparentRichTextBoxUserControl 来解决这个问题。 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,因为RichTextBoxAutoSize 坏了。

      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)。要转义 \{},请使用前导 \。 如需更多信息,请联系full specification of the rich text format online

      使用这种非常简单的语法,您可以生成与第一张图片类似的内容。第一张图片中我的AutoRichLabelRtfContent 属性附加的富文本内容是:

      {\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}
      

      如果您想启用自动换行,请将最大宽度设置为所需的大小。但是,即使文本较短,这也会将宽度固定为最大宽度。

      玩得开心!

      【讨论】:

        【解决方案7】:

        2009 年有一篇名为“A Professional HTML Renderer You Will Use”的代码项目的优秀文章实现了与原始发帖人想要的类似的东西。

        我在我们的几个项目中成功使用它。

        【讨论】:

          【解决方案8】:

          非常简单的解决方案:

          1. 在表单上添加 2 个标签,LabelA 和 LabelB
          2. 转到 LabelA 的属性并将其停靠在左侧。
          3. 转到 LabelB 的属性并将其停靠在左侧。
          4. 将 LabelA 的字体设置为粗体。

          现在 LabelB 将根据 LabelA 的文本长度发生变化。

          就是这样。

          【讨论】:

            【解决方案9】:

            我也想知道是否有可能。

            当我们找不到解决方案时,我们求助于 Component Ones 的“SuperLabel”控件,该控件允许在标签中添加 HTML 标记。

            【讨论】:

              【解决方案10】:

              意识到这是一个老问题,我的答案更适合像我这样仍在寻找此类解决方案并偶然发现这个问题的人。

              除了已经提到的,DevExpress 的LabelControl 是一个支持这种行为的标签-demo here。唉,它是付费图书馆的一部分。

              如果您正在寻找免费的解决方案,我相信HTML Renderer 是下一个最佳选择。

              【讨论】:

              • 当我们使用 DevExpress 的通用控件时,它们曾经在主题方面遇到过巨大的问题。比如,让它们使用一些酷儿主题很容易,但很难让它们看起来像当前的操作系统。
              【解决方案11】:

              FlowLayoutPanel 可以很好地解决您的问题。如果您将标签添加到流程面板并格式化每个标签的字体和边距属性,那么您可以拥有不同的字体样式。开始工作的非常快速和简单的解决方案。

              【讨论】:

                【解决方案12】:

                是的。 您可以使用 HTML Render 来实现。 你看,点击链接:https://htmlrenderer.codeplex.com/ 我希望这很有用。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-11-30
                  • 1970-01-01
                  • 2014-06-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-08-29
                  • 1970-01-01
                  • 2011-09-15
                  相关资源
                  最近更新 更多