具有自动高度属性的用户控件

2023-11-30

我想创建将显示文本的用户控件。
我需要一种在运行时调整控件大小的方法,以便它调整高度以显示所有文本。 我创建了如下所示的控件:

enter image description here

正如你所看到的,我使用以下方法绘制了图标和文本TextRenderer.DrawText。不幸的是,当我调整控件大小(仅向左或向右)时,我的文本有时会被剪切,如下所示:

enter image description here

我正在使用测量文本TextRenderer.MeasureText基于此,我计算行数,然后绘制该文本。这是我正在使用的代码:

[Designer(typeof(MyTextBoxDesigner))]
public partial class MyTextBox : UserControl
{
    public MyTextBox()
    {
        InitializeComponent();
    }

    [DefaultValue("Demo"), Description("Text of control"), Category("Appearance"),Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public override string Text
    {
        get
        {
            return base.Text;
        }
        set
        {
            if (base.Text == value) return;
            base.Text = value;
            Invalidate();
        }
    }

    Image _image;
    [Description("Image shown on the left side of the control"),
    Category("Appearance")]
    public Image Image
    {
        get
        {
            return _image;
        }
        set
        {
            if (_image == value) return;
            _image = value;
            Invalidate();
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        int imagePadding = 0;
        if (_image != null)
        {
            imagePadding = 25;
            e.Graphics.DrawImage(_image,new Rectangle(5,5,16,16));
        }
        Size textSize1 = TextRenderer.MeasureText(e.Graphics, Text, Font);
        SizeF textSize2 = e.Graphics.MeasureString(Text, Font);

        Debug.WriteLine(textSize2);

        int maxTextWidth = Width - Padding.Left-Padding.Right-imagePadding;
        int lineHeight = textSize1.Height + 2;
        int numLines = 1;

        if (textSize1.Width > maxTextWidth)
        {
            numLines = textSize1.Width / maxTextWidth + 1;
        }

        Rectangle textRect = new Rectangle
        {
            Width = Width - Padding.Left-Padding.Right-imagePadding,
            Height = (numLines * lineHeight),
            X = Padding.Left+imagePadding,
            Y = 5
        };

        TextRenderer.DrawText(e.Graphics, Text, Font, textRect, ForeColor, TextFormatFlags.WordBreak | TextFormatFlags.Left | TextFormatFlags.Top);

        e.Graphics.DrawRectangle(Pens.CadetBlue, textRect);

        base.OnPaint(e);
    }
}

internal class MyTextBoxDesigner : ControlDesigner
{
    public override SelectionRules SelectionRules
    {
        get
        {
            //all minus bottom and top
            return (base.SelectionRules & ~(SelectionRules.BottomSizeable | SelectionRules.TopSizeable));
        }
    }
}

理想情况下,我希望我的控件能够根据文本长度自动调整高度,因此如果文本很短(或控件足够长),高度将是例如 20px,但如果文本很长,我的控件应该是(例如)40px高度(2 行文本)。

我应该如何更改我的文本测量来计算textRect正确吗?
我应该使用 Size 属性更新控件的高度还是有更好的方法?

EDIT:基本上我想绘制可以包裹在矩形内的文本,但具有固定宽度,因此当文本较长时,矩形将调整其高度。然后根据这个高度我想调整控制高度。


这是一个自动高度控制。如果更改控件的宽度,控件的高度也会发生变化,从而可以显示整个文本。

enter image description here

您可以使用不同的方法创建此类控件,包括:

  • 方法 1:自动调整托管标签的复合控件的大小
    此方法基于托管自动调整大小Label在自动调整大小时具有动态最大宽度Control。在这种方法中,我们根据控件的宽度设置标签的最大宽度,并且由于标签是自动调整大小的,因此它的高度将自动设置为显示所有文本,然后我们根据标签的高度设置控件的高度。

  • 方法 2:从头开始自动调整大小,无需标签的简单控制
    该方法基于重写SetBoundsCore并根据其设置控件的大小Text尺寸。在这种方法中,我们根据控件的宽度计算文本的大小,使用TextRenderer.MeasureText然后将计算出的高度设置为控件的高度。在这种方法中,您应该自己处理文本格式标志和渲染。

在这两种方法中ControlDesigner用于禁用除左和右之外的所有尺寸的手柄。

请注意

这些不是唯一可用的方法,但却是很好的例子。作为另一种选择,您可以继承Label并改变它的行为。

方法 1:自动调整托管标签的复合控件的大小

它根据设置工作AutoSize标签的属性为true然后设置MaximumSize基于控制的标签Width。控件的高度也是根据标签的高度设置的。 您可以简单地绘制图像OnPaint方法。您还可以添加一个PictureBox对于图像。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
[Designer(typeof(MyLabelDesigner))]
public partial class MyLabel : Control
{
    public MyLabel() { InitializeComponent(); }
    private System.Windows.Forms.Label textLabel;
    private void InitializeComponent()
    {
        this.textLabel = new System.Windows.Forms.Label();
        this.textLabel.AutoSize = true;
        this.textLabel.Location = new System.Drawing.Point(0, 0);
        this.textLabel.Name = "label1";
        textLabel.SizeChanged += new EventHandler(textLabel_SizeChanged);
        this.AutoSize = true;
        this.Controls.Add(this.textLabel);
    }
    void textLabel_SizeChanged(object sender, EventArgs e)
    {
        this.Height = this.textLabel.Bottom + 0;
    }
    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        this.textLabel.MaximumSize = new Size(this.Width, 0);
    }
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public override string Text
    {
        get { return this.textLabel.Text; }
        set { this.textLabel.Text = value; }
    }
}

方法 2:从头开始自动调整大小,无需标签的简单控制

这种方法的工作原理是基于设置控件的大小SetBoundsCore基于当前宽度和计算出的高度Text。计算控制高度。你可以简单地画出Image.

using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms.Design;
[Designer(typeof(MyLabelDesigner))]
public class ExLabel : Control
{
    public ExLabel()
    {
        AutoSize = true;
        DoubleBuffered = true;
        SetStyle(ControlStyles.ResizeRedraw, true);
    }
    protected override void OnTextChanged(System.EventArgs e)
    {
        base.OnTextChanged(e);
        SetBoundsCore(Left, Top, Width, Height, BoundsSpecified.Size);
        Invalidate();
    }
    protected override void SetBoundsCore(int x, int y, int width, int height,
        BoundsSpecified specified)
    {
        var flags = TextFormatFlags.Left | TextFormatFlags.WordBreak;
        var proposedSize = new Size(width, int.MaxValue);
        var size = TextRenderer.MeasureText(Text, Font, proposedSize, flags);
        height = size.Height;
        base.SetBoundsCore(x, y, width, height, specified);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        var flags = TextFormatFlags.Left | TextFormatFlags.WordBreak;
        TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle,
            ForeColor, BackColor, flags);
    }
}

Designer

这里是ControlDesigner对于这两种实现,它用于将设计器中的手柄大小限制为左侧和右侧:

using System.Windows.Forms.Design;
public class MyLabelDesigner : ControlDesigner
{
    public override SelectionRules SelectionRules
    {
        get
        {
            return (base.SelectionRules & ~(SelectionRules.BottomSizeable | 
                                            SelectionRules.TopSizeable));
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有自动高度属性的用户控件 的相关文章

随机推荐

  • 是否可以在范围报告等步骤之间获得诱惑报告的屏幕截图?

    我在用着allurereport 为我的测试生成报告 早些时候我曾经使用过extent报告 如您所知 在范围报告中 您可以添加日志和屏幕截图以创建它们 但在诱惑报告中 所有屏幕截图都将显示在步骤的末尾 My Question Is it p
  • Visual Studio 2015 RC3 TypeScript Intellisense 不再工作

    我正在使用 TypeScript 1 8 10 和 TypeScript Tools for VS2015 1 8 1 0 Beta 另外 我正在使用 VS2015 RC3 我尝试升级到 TypeScript 2 0 但遇到了完全相同的问题
  • 使用私有 API 扫描 iOS 7 上的网络 (SSID)

    是否可以通过在 iOS 7 越狱设备上使用私有 API 来获取周围网络的 SSID 列表 我知道关于MobileWiFi framework管理 iOS 上的 WiFi 功能 它取代了过时的 Apple80211 框架 这是 4 年前的答案
  • Magento SOAP 2 API 致命错误:过程“登录”不存在

    我收到 致命错误 程序 登录 不存在于 chroot home mystore mystore com html lib Zend Soap Server php 第 832 行 这就是错误的来源 soap this gt getSoap
  • Python:如何从 pandas 列中删除所有非数字值?

    我有一个数据框df像下面这样 Rooms BFS 0 3 5 4201 1 1 5 4201 2 NA 4201 3 NA 4201 4 5 5 4201 5 5 4201 6 4 5 4201 7 3 4201 8 4201 9 3 42
  • 在 R 正则表达式中获取文本段落中超过 1 个引用

    首先 找到引用 我想要这里的所有内容 内的文本 第二 在引文前摘录1句话 如果可能的话 我想通过查看 R 中的正则表达式来实现所需的输出 Example Yoyo He is sad Oh no Don t sad Yeah Testing
  • 如何使用ThreadException?

    我尝试使用 http msdn microsoft com en us library system windows forms application threadexception aspx Y399 但当我这样做时 throw new
  • Gradle 无法检测 osDetector 插件

    我正在将 OpenSSL 用于我的 Java GRPC 项目 该项目使用 gradle 我读了文档其中提到我们应该按照本节中提到的进行安全设置link 我已将 osDetector 插件包含在 build gradle 文件中 但是当我构建
  • 单击 Viewpager Xamarin Android

    我是 Xamarin Android 开发新手 我使用以下命令创建了图像滑块浏览器 现在我想单击该 ViewPager 的图像 我该如何实现呢 我已经尝试过这个但没有成功 viewpage mview FindViewById
  • 目标无法访问,标识符解析为 null

    我正在尝试在外部服务器上运行 j2EE 项目 项目是在 NetBeans 6 7 1 中制作的 当我从那里运行它时 一切都很顺利 我在 GlassFish v3 服务器上运行它 但是当我从 asadmin 脚本运行 GlassFish 并向
  • UWP C# 禁用方向更改动画

    是否可以禁用当手机旋转发生变化 从横向变为纵向或反之亦然 时执行的 屏幕旋转 动画 你需要使用DisplayInformation AutoRotationPreferences DisplayOrientations LandscapeF
  • :remote => true 和 url_for,如何做到这一点?

    我正在尝试使整个 div 标签可点击 我尝试使用的代码如下 当我添加 remote gt true 它会抛出 Too much args 错误 2 for 1 Code div div url for 不接受 remote gt true争
  • 从脚本启动 Spring boot 应用程序

    使用普通的 spring mvn 命令 我可以从命令行启动 spring boot 应用程序并使用 Control c 终止它 不过 我已经创建了一堆服务 稍后我将对其进行 dockerize 现在它们是由 mvn 生成的普通 java j
  • JSTree 拖放问题

    我将 JSTree 与 ASP net 一起使用 为树生成的 html 看起来像 ul li a href node 1 a li li a href node 2 a li li a href node 3 a li li a href
  • 升级到 JSF 2.2 后,#{cc.clientId} 在错误的组合中进行评估

    我有一个用 JSF 2 0 PrimeFaces 3 4 编写的标签库 现在我正在尝试更新到 JSF 2 2 和 PrimeFaces 4 0 但我意识到传递给组件的属性值是在复合组件中计算的 这会导致渲染的 id 错误 enum xhtm
  • Cygwin 和 Apache Pig - 令人困惑的伪 grunt>

    我正在尝试在运行 Vista 操作系统的 Windows PC 上安装 Apache Pig 以便将其用作学习工具 我不打算在这台机器上使用 Pig 进行任何严肃的数据处理 单节点 单 JVM x local设置是我想要的 我有 Windo
  • 始终显示 JavaFX ListView 的垂直滚动条

    ListView 似乎已经有一个滚动条 我希望滚动条始终可见 原因是因为我在其上放置了一个标题 并在滚动条和标题之间的角落放置了一个按钮 如何让ListView滚动条始终显示 您可以将其放入适当大小的 JScrollPane 中 并将 JS
  • 如何在运行时更改注释/Hibernate 验证规则?

    如果有一个带有某些字段的 Java 类 我想使用 Hibernate Validator 进行验证 现在我希望我的用户能够在运行时配置进行哪些验证 例如 public class MyPojo NotEmpty String void ge
  • 我需要 iOS 设备来“存档”Xcode 项目吗?

    我是一名 iOS 开发新手 试图推出我的第一个应用程序 我在 StackOverflow 上挖掘了很长时间来寻找答案 但没有成功 有3个关键点需要牢记 我实际上并没有 iOS 设备 到目前为止我只是使用模拟器来测试该应用程序 我也有所有证书
  • 具有自动高度属性的用户控件

    我想创建将显示文本的用户控件 我需要一种在运行时调整控件大小的方法 以便它调整高度以显示所有文本 我创建了如下所示的控件 正如你所看到的 我使用以下方法绘制了图标和文本TextRenderer DrawText 不幸的是 当我调整控件大小