【问题标题】:Determine Label Size based upon amount of text and font size in Winforms/C#根据 Winforms/C# 中的文本数量和字体大小确定标签大小
【发布时间】:2008-12-23 14:12:22
【问题描述】:

我想知道是否有更好的方法来解决这个问题。我想(垂直)调整标签的大小以容纳一定数量的文本。我的标签有一个固定的宽度(在它必须换行之前大约 60 个字符宽),大约 495 像素。字体也是固定大小(12points afaik),但文本不是。

当有“NewLine”或文本必须换行时,我想做的是增加标签高度;这个想法是文本在标签中完全可见。 AutoSize 不起作用,因为它会增加宽度,而不是高度。

当然,我可以计算 NewLine 的数量并添加:Newlines * LineHeight,然后 - 假设我设法每行放置 60 个字符,只需将字符数相除并根据需要添加尽可能多的 LineHeight 像素。

我想知道是否有更专业的方法可以做到这一点。我的做法是不是太“蹩脚”了?

提前致谢。

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    Graphics.MeasureString 怎么样,具有接受字符串、字体和最大宽度的重载?这将返回一个SizeF,因此您可以对Height 进行四舍五入。

            using(Graphics g = CreateGraphics()) {
                SizeF size = g.MeasureString(text, lbl.Font, 495);
                lbl.Height = (int) Math.Ceiling(size.Height);
                lbl.Text = text;
            }
    

    【讨论】:

    • 我也是+1,但是来吧!数学.天花板?老鼠,遇见榴弹炮。 :)
    • @MusiGenesis - 它确保我们四舍五入并且不会丢失任何像素。常规的 int 转换向下取整,但是是的:我们可以只添加一个以确保安全......
    • 我知道这很老了,我知道我在吹毛求疵,但是这个线程stackoverflow.com/questions/6704923/… 似乎表明在正常情况下TextRenderer.MeasureText 给出的结果比Graphics 更准确。测量字符串。
    • @RenniePet 即使您现在的问题在哪里very old for me:您的解决方案甚至比这个答案更好。一条短线Size size = TextRenderer.MeasureText(text, font); 就是这样。谢谢!
    【解决方案2】:

    System.Drawing.Graphics 有一个可用于此目的的 MeasureString 方法。使用带有字符串、字体和 int "width" 参数的重载;最后一个参数指定字符串允许的最大宽度 - 将此参数使用标签的设置宽度。

    MeasureString 返回一个 SizeF 对象。使用此返回对象的 Height 属性来设置标签的高度。

    注意:要为此目的获取一个 Graphics 对象,可以调用 this.CreateGraphics。

    【讨论】:

      【解决方案3】:

      Graphics.MeasureString() 可能会对您有所帮助。

      这也是使用 Control.CreateGraphics() 调用的唯一用例之一!

      【讨论】:

      • CreateGraphics 的另一个用例是什么?我想不出其他的了。
      • 我说“唯一的一个”以防万一,但我认为它是唯一的。老实说,我只是在模仿 Bob Powell 的 GDI 常见问题解答。
      • 我唯一能想到的另一个是用于创建自定义图形,当您将另一个窗口拖到它们上方时会消失,但这更像是一个误用情况。 :)
      • 我可以想到另一种用途,类似于:我编写了一个双缓冲 Canvas 用户控件,它覆盖 CreateGraphics 方法以从双缓冲区而不是控件本身返回一个 Graphics 对象。不确定这是否重要,因为它是一个覆盖。
      • 等等.. 我们可以根据您的误用案例的属性制作一款游戏。就像 wack-a-mole,但你使用窗户杀死痣!我们有第二个用例! :D
      【解决方案4】:
      Size maxSize = new Size(495, int.MaxValue);
      _label.Height = TextRenderer.MeasureText(_label.Text , _label.Font, maxSize).Height;
      

      【讨论】:

      • label.Height = TextRenderer.MeasureText(_label.Text , _label.Font, maxSize, TextFormatFlags.WordBreak).Height;包含“WordBreak”以换行并具有预期的高度。
      【解决方案5】:

      这个“答案”供将来参考,并与 AutoSize = true 意味着它(WinForms 标签)永远不会增长的初始假设作斗争。

      以下链接显示 AutoSize = true 与其他属性(例如 MaximumSize)的各种效果。根据问题的预期用途,采用其中一种方法可能是合适的。

      http://blogs.msdn.com/jfoscoding/articles/478299.aspx

      【讨论】:

      • 酷。现在我知道为什么我曾经编写的所有用于调整标签大小的代码都无法正常工作。我想回到过去,给自己一巴掌,但我很难选择一个日期回去。
      【解决方案6】:

      我在此处接受的答案中发布了一个解决此问题的用户控件: Autoscale Font in a TextBox Control so that its as big as possible and still fits in text area bounds

      控件扩展了 RichTextBox。它有一个方法:ScaleFontToFit,它会自动调整字体大小以使所有文本都适合。

      整洁的是它尊重多行属性。如果为 true,则允许换行,否则不允许。

      【讨论】:

        【解决方案7】:

        我想提出一个替代方案,因为它是我们正在谈论的标签,而不仅仅是文本渲染:GetPreferredSize。我尝试了 Mark 的回答,但问题是它几乎有效:标签在文本周围有一些“填充”,这需要在 MeasureStringwidth 值中考虑。我找不到任何明显的方法来获得这个填充。在挖掘时,我发现了this answer,海报建议将FlatStyle 设置为System。这行得通,但不幸的是打破了我希望它成为MiddleLeftTextAlign

        我查看了Label 代码,发现GetPreferredSize 考虑了所有奇怪的设置(FlatStyleUseCompatibleTextRendering 等),并且可以为每种情况提供正确的结果。所以你可以代替g.MeasureString(text, lbl.Font, 495); 来代替

        lbl.GetPreferredSize(new Size(495, 0));
        

        或者甚至像这样,因为标签大小是已知的:

        lbl.GetPreferredSize(new Size(lbl.Width, 0));
        

        如果您想知道,0 和 1 将被视为int.MaxValue

        我不知道GetPreferredSize 是什么时候引入的,所以早在 2008 年 Mark 写下他的答案时,上述内容可能并不相关。但是,如果您在 2021 年仍需要类似的东西,GetPreferredSize 可能会更方便一些 - 它返回 Size 而不是 SizeF

        【讨论】:

        • 感谢您的更新。自 2010 年左右以来,我个人还没有接触过 C#……我希望这对当前的开发人员有所帮助! :)
        • @MartinMarconcini 2010!那是很久以前的事了!在这么长时间之后监视这种“古老”的东西是值得称赞的。 :)
        【解决方案8】:

        这 60 个字符可能对您的测试文本有效,但并非所有字符都具有相同的宽度。例如,比较
        呸呸呸呸呸呸呸呸呸呸呸呸呸呸呸呸呸呸呸

        wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

        它们都有 60 个字符,但宽度却大不相同。

        【讨论】:

        • OP 说是固定字体,像 courier new。
        • 确实,但我有一个固定的字体和测量字符串可能会处理这个问题。谢谢。
        【解决方案9】:

        使用TextRenderer 类来测量字符串(如在 Marc 的响应中)而不是通过工作来创建 Graphics 对象等有什么缺点吗?

        【讨论】:

        • TextRenderer 比 Graphics.MeasureString 慢。我不知道为什么。然而,对于大多数用例来说,它们都非常快。
        【解决方案10】:

        根据this article,如果要使用 Windows 窗体控件进行最终输出,则应使用 TextRenderer。 TextRenderer 和 Graphics.MeasureString 将给出不同的结果,因此请使用与您的最终输出模式相匹配的结果。

        【讨论】:

          【解决方案11】:

          在某些情况下,你必须使用紧凑的框架,它没有任何 MeasureString() 的覆盖方法,你可以考虑自己计算高度。

          private int YukseklikAyarla(string p, Font font, int maxWidth)
              {
                  int iHeight = 0;
                  using (Graphics g = CreateGraphics())
                  {
                      var sizes = g.MeasureString(p, font); // THE ONLY METHOD WE ARE ALLOWED TO USE
                      iHeight = (int)Math.Round(sizes.Height);
                      var multiplier = (int)Math.Round((double)sizes.Width) / maxWidth; // DIVIDING THE TEXT WIDTH TO SEE HOW MANY LINES IT CAN HAS
                      if (multiplier > 0)
                      {
                          iHeight = (int)(iHeight * (multiplier + 1)); // WE ADD 1 HERE BECAUSE THE TEXT ALREADY HAS A LINE
                      }
                  }
                  return iHeight;
              }
          

          【讨论】:

            【解决方案12】:

            虽然,它是一个旧线程,但认为它可能会帮助新访问者。

            在 C# 中,您可以使用 control.width

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-03-19
              • 1970-01-01
              • 1970-01-01
              • 2011-03-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多