【问题标题】:Override AutoSize for derived Label Control in C#在 C# 中为派生的标签控件覆盖 AutoSize
【发布时间】:2010-12-14 22:10:21
【问题描述】:

我正在尝试扩展 System.Windows.Forms.Label 类以支持垂直绘制的文本。为此,我创建了一个名为 MyLabelOrientation 的新属性,用户可以将其设置为水平或垂直。当用户更改此设置时,宽度和高度的值会交换以将控件的大小调整为新的方向。最后,我重写了 OnPaint 函数来绘制我的标签。

我还想扩展此控件的 AutoSize 属性,以便我的标签将自动调整为它包含的文本。对于水平方向,基本功能为我实现了这一点。对于垂直方向,我创建了一个 Graphics 对象并将控件的高度设置为从 Graphics.MeasureString(Text, Font) 返回的 SizeF 对象的宽度。您可以在下面看到我正在使用的代码示例。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

public class MyLabel : Label
{
    public enum MyLabelOrientation {Horizontal, Vertical};
    protected MyLabelOrientation m_orientation = MyLabelOrientation.Horizontal;

    [Category("Appearance")]
    public virtual MyLabelOrientation Orientation
    {
        get { return m_orientation; }
        set
        {
            m_orientation = value;
            int temp = Height;
            Width = Height;
            Height = temp;
            Refresh();
        }
    }

    private Size ResizeLabel()
    {
        Graphics g = Graphics.FromHwnd(this.Handle);
        SizeF newSize = g.MeasureString(Text, Font);
        if (m_orientation == MyLabelOrientation.Horizontal)
            Width = (int)newSize.Width;
        else
            Height = (int)newSize.Width;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Brush textBrush = new SolidBrush(this.ForeColor);

        if (m_orientation == LabelOrientation.Vertical)
        {
            e.Graphics.TranslateTransform(Width, 0);
            e.Graphics.RotateTransform(90);
            e.Graphics.DrawString(Text, Font, textBrush, Padding.Left, Padding.Top);
        }
        else
        {
            base.OnPaint(e);
        }
    }
}

但是,将 AutoSize 设置为 true 似乎可以防止和/或覆盖对控件大小的任何更改。这意味着当我想更改标签的方向时,我无法更改宽度或高度。我想知道是否可以覆盖此行为,以便我可以测试是否设置了 AutoSize,然后根据它的方向调整控件的大小。

【问题讨论】:

    标签: c# custom-controls overriding label autosize


    【解决方案1】:

    我知道这是一个很老的问题,但我今天偶然发现了它,想知道如何做同样的事情。

    我对该问题的解决方案是覆盖GetPreferredSize(Size proposedSize) 方法。除了文本之外,我还使用了一个按钮类,其中包含一个箭头,当然,使用 AutoSize 属性没有考虑到这一点,所以我添加了额外的空间,它对我来说很好。

    考虑到改变方向或切换宽度和高度的问题,您可以完全改变首选尺寸的计算方式。

    public override Size GetPreferredSize(Size proposedSize)
    {
        Size s = base.GetPreferredSize(proposedSize);
        if (AutoSize)
        {
            s.Width += 15;
        }
        return s;
    }
    

    【讨论】:

    • 这是完美的。我想覆盖一个复选框控件并绘制一个稍大且彩色的复选框。因此,只需计算我的复选框比库存复选框大多少,并将其添加到宽度,它每次都会设置正确的宽度。
    【解决方案2】:

    我以前没有这样做过,我相信您理论上可以覆盖属性声明(通过new 关键字)并在继续之前检查方向:

    override public bool AutoSize
    {
       set 
       {
          if( /* orientation is horizontal */ )
          {
              base.AutoSize = value;
          }
          else
          {
              // do what you need to do
          }    
       }    
    }
    

    【讨论】:

    • AutoSize 是一个虚拟属性。使用覆盖,而不是新的。
    • @Hans:相应更新;发帖前我没有检查它是否是虚拟的。我认为这不是基于问题的性质。谢谢。
    • 我之前尝试过这个解决方案,当你像这样覆盖 AutoSize 时,控件或多或少会忽略。 AutoSize 阻止对宽度或高度的任何更改,尽管来源。我需要覆盖其他可能会查看 AutoSize 设置并相应调整大小的内容。
    【解决方案3】:

    如果认为解决方案是覆盖 OnResize 本身:

    protected override void OnResize(EventArgs e)
    {
        if (AutoSize)
        {
            // Perform your own resizing logic
        }
        else
            OnResize(e);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-04-04
      • 2010-10-20
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多