在 C# 中重写派生标签控件的 AutoSize

发布于 2024-10-07 11:27:01 字数 1896 浏览 4 评论 0原文

我正在尝试扩展 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,然后根据控件的方向调整控件的大小。

I am trying to extend the System.Windows.Forms.Label class to support vertically drawn text. I do this by creating a new property called MyLabelOrientation that the user can set to Horizontal or Vertical. When the user changes this setting, the values for width and height are swapped to resize the control to its new orientation. Finally, I override the OnPaint function to draw my Label.

I would like to extend the AutoSize property for this control as well so that my Label will auto-size to the text it contains. For the horizontal orientation, the base functionality implements this for me. For the vertical orientation, I create a Graphics object and set the height of the control to the width of the SizeF object returned from Graphics.MeasureString(Text, Font). You can see an example of the code I'm using below.

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

However, setting AutoSize to true seems to prevent and/or override any changes to the size of the control. This means that I can't change the width or height when I want to change the Label's orientation. I'm wondering if this behavior can be overridden, so that I can test whether AutoSize is set, and then adjust the size of the control according to it's orientation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

幸福丶如此 2024-10-14 11:27:01

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

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

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

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

I know this a a pretty old question, but i stumbled across it today and was wondering how to do the same thing.

My solution to the problem was overriding the GetPreferredSize(Size proposedSize) method. I used a button class that houses an arrow in addition to the text which, of course, was not taken into account using the AutoSize property so i added additional space and it works fine for me.

Given the problem of changing orientation or switching width and height, you could completely change the way the preferred size is calculated.

public override Size GetPreferredSize(Size proposedSize)
{
    Size s = base.GetPreferredSize(proposedSize);
    if (AutoSize)
    {
        s.Width += 15;
    }
    return s;
}
泪之魂 2024-10-14 11:27:01

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

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

I have not done this before, I believe you can theoretically override a property declaration (via the new keyword) and check the orientation before proceeding:

override public bool AutoSize
{
   set 
   {
      if( /* orientation is horizontal */ )
      {
          base.AutoSize = value;
      }
      else
      {
          // do what you need to do
      }    
   }    
}
小女人ら 2024-10-14 11:27:01

如果认为解决方案是重写 OnResize 本身:

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

If think a solution is to override OnResize itself :

protected override void OnResize(EventArgs e)
{
    if (AutoSize)
    {
        // Perform your own resizing logic
    }
    else
        OnResize(e);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文