【问题标题】:WinForms Button: Autosize MaximumsizeWinForms 按钮:自动调整最大尺寸
【发布时间】:2015-07-26 07:59:36
【问题描述】:

我想将按钮添加到 FlowLayoutPanel。按钮可能包含较长的文本,单词之间有空格。按钮是 Autosize=true 和 AutoSizeMode = AutoSizeMode.GrowAndShrink。此外,我将MaximumSize 属性设置为(maxwidth,0)。 maxwidth 是面板的宽度。所以按钮不会太宽。

我看到的是,Button 的宽度受 MaximumSize 属性的限制,但是当发生文本换行时,Button 的高度不会自动调整为换行文本的高度。有没有办法解决这个问题?


我也试过这样手动调整按钮的大小:

using (Graphics cg = this.CreateGraphics()) {
SizeF size = cg.MeasureString(button.Text, button.Font, 200);
  button.Width = (int)size.Width+20;
  button.Height = (int)size.Height+20;
  button.Text = someLongTextWithSpaces;
}

但请注意,我在计算的大小上加了 20。它正在工作,但是有没有合适的方法来确定这个额外的大小?也许 2x 填充 + ?????


几个小时后……

我来到了这个似乎工作得很好的版本。

using (Graphics cg = this.CreateGraphics()) {
  var fmt = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak;
  var prop = new Size(tableLayoutPanel1.Width - 20, 0);
  var size = TextRenderer.MeasureText(button.Text, button.Font, prop, fmt);

  int border = button.Height - button.Font.Height;
  button.Width = (int)size.Width + border;
  button.Height = (int)size.Height + border;
  button.Text = someLongTextWithSpaces;
}

似乎初始按钮高度是边框+字体高度。所以我计算了减去button.Height-button.font.Height的边框。

根据 Hans 的说法,我现在使用 TextRenderer.MeasureText。我在没有启用 VisualStyles 的情况下对其进行了测试,它运行良好。有什么相关的吗?

【问题讨论】:

  • 而不是maxwidth(如果您手动添加此号码)尝试此FlowLayoutPanel1.ClientRectangle.Width(或者您调用该面板)。 ....例如,在Form_Resize 中输入代码:Button1.MaximumSize = New Size(FlowLayoutPanel1.ClientRectangle.Width, 0)(这是vb 代码,请将他转换为c#)....我认为这是c# 代码:Button1.MaximumSize == new Size(FlowLayoutPanel1.ClientRectangle.Width, 0);
  • 我还将MaximumSize手动设置为固定值。该值是好的,只有高度调整大小不起作用。您也可以在 FormDesigner 中进行测试。添加带有增长/缩小功能的自动调整大小的按钮和带有空格的较长文本。将最大宽度设置为小于文本。按钮宽度有限,但高度没有增长..
  • 你为什么加了+20?
  • @Aseem Gautam:只需客串一个值进行测试。找出真正的价值是个问题。
  • 您可以使用虚拟对象通过将文本设置为“X”来找出按钮上一行的高度,然后将其设置为“X\r\nX”。区别在于一行按钮文字的高度。

标签: c# winforms button autosize


【解决方案1】:

有一个适当的方法,但它不是很微妙。从 ButtonRenderer 类源代码进行逆向工程,绘制按钮文本的 Winforms 类,您必须使用 TextRenderer 类来测量文本。并且您必须使用 VisualStyleRenderer.GetBackgroundContentRectangle() 方法来获取有效的绘图边界。请注意,它小于按钮的大小,因为边框和边距取决于所选的视觉样式。

重要的问题是将计算出的内容矩形映射回外部按钮大小,以及处理未启用视觉样式的旧机器。大小正确的示例代码:

    private static void SetButtonSize(Graphics gr, Button button) {
        VisualStyleElement ButtonElement = VisualStyleElement.Button.PushButton.Normal;
        var visualStyleRenderer = new VisualStyleRenderer(ButtonElement.ClassName, ButtonElement.Part, 0);
        var bounds = visualStyleRenderer.GetBackgroundContentRectangle(gr, button.Bounds);
        var margin =  button.Height - bounds.Height;
        var fmt = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak;
        var prop = new Size(bounds.Width, 0);
        var size = TextRenderer.MeasureText(button.Text, button.Font, prop, fmt);
        button.ClientSize = new Size(button.ClientSize.Width, size.Height - margin);
    }

    protected override void OnLoad(EventArgs e) {
        using (var gr = this.CreateGraphics()) {
            SetButtonSize(gr, this.button1);
        }
        base.OnLoad(e);
    }

没有针对极端情况进行广泛测试,不能说我推荐这个。

【讨论】:

  • 我创建了一种计算边界的新方法(请参阅我上面的帖子)。您认为这是一种合适的方式吗?至少它在启用和不启用 VisualStyles 的情况下对我有用。
  • 嗯,像“20”这样的幻数从来都不是一个好主意,当视频 DPI 发生变化时它们就不起作用了。
  • 你的意思是“tableLayoutPanel1.Width - 20”中的“20”吗?我只是不希望按钮填写 tableLayoutPanel1 的完整宽度。好的,实际上居中按钮端边之间的距离不是 2x10 而是 2x(10-bordersize)。因此,除非边框为 10 或更多,否则它应该适合。也许我应该使用 2x(计算的边框 + 一些东西)并取它而不是“20”。
【解决方案2】:

似乎初始按钮高度是边框+字体高度。所以我计算了减去button.Height-button.font.Height的边框。 (见我原帖的最后一段)

这也适用于启用/禁用 VisualStyles。

【讨论】:

  • 我不确定button.Height-button.font.Height 是否等于调用VisualStyleRenderer.GetBackgroundContentRectangle()。我的测试表明button.Height-button.font.Height 返回的边框值比VisualStyleRenderer.GetBackgroundContentRectangle() 大。这取决于 Dpi、字体大小等。例如,对于 96dpi 和 8.25pt 字体大小,您的方法返回 5px 作为边框,VisualStyles 的方法返回 3px 作为边框!
【解决方案3】:

您应该通过在文本中添加换行符来控制换行符。自动换行不能单独使用空格:

button1.Text = "123232131232\r\nfgfdgfdgdfgdfgdf\r\nASDSADSDASD";

或者:

button1.Text = "123232131232" + Environment.NewLine + 
           "fgfdgfdgdfgdfgdf" + Environment.NewLine + "ASDSADSDASD";

如果您希望获得自动换行,可以尝试使用TextMeasure 来确定文本所需的高度,然后相应地设置按钮的高度,但这可能需要额外注意..

但我建议考虑改用标签。对于标签,包装开箱即用。具有不同大小的巨大按钮是非标准 UI 元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2015-03-12
    • 2019-11-20
    • 2019-05-01
    • 1970-01-01
    • 2020-12-14
    相关资源
    最近更新 更多