计算显示文本的 Windows 窗体宽度

发布于 2024-11-08 16:39:22 字数 3637 浏览 0 评论 0 原文

我需要计算显示文本的 Windows 窗体宽度。 表单宽度显然以像素为单位,因此您只想获取以像素为单位的文本宽度,但这不起作用:

animationForm.Width = TextRenderer.MeasureText(_caption, animationForm.Font).Width;

计算出的表单宽度太小(截断文本) - 这是怎么回事? MeasureText 使用像素,表单宽度以像素为单位。

这效果更好,但我认为不对:

animationForm.Width = (int)(_caption.Length * animationForm.Font.Size);

将不胜感激。

动画图片 - PictureBox, 标签图像上设置

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace PrlSystems.MaimInvoicing.Forms
{
    public partial class ProgressIndicatorForm : Form
    {
        private volatile bool _animating = false;
        private Form _parent;
        private string _caption = "";

        private object _mutex = new object();

        public ProgressIndicatorForm(Form parent)
        {
            InitializeComponent();
            _parent = parent;
        }

        public string Caption
        {
            set { _caption = value; }
            get { return _caption; }
        }

        public void StartAnimation()
        {
            lock (_mutex)
            {
                if (!_animating)
                {
                    if (_parent != null)
                    {
                        _parent.Cursor = Cursors.WaitCursor;
                        _parent.Enabled = false;
                    }

                    _animating = true;
                    _SpawnAnimationThread();
                }
            }
        }

        public void StopAnimation()
        {
            lock (_mutex)
            {
                if (_animating)
                {
                    _animating = false; // stop animation thread

                    if (_parent != null)
                    {
                        // restore parent form UI
                        _parent.Cursor = Cursors.Default;
                        _parent.Enabled = true;
                        _parent.Activate();
                    }
                }
            }
        }

        private void _SpawnAnimationThread()
        {
            Thread animationThread = new Thread(new ThreadStart(_Animate));
            animationThread.Priority = ThreadPriority.Normal;
            animationThread.IsBackground = true;    // should terminate when application ends
            animationThread.Start();
        }

        private void _Animate()
        {
            ProgressIndicatorForm animationForm = new ProgressIndicatorForm(_parent);
            animationForm.CaptionLabel.Text = _caption;
            animationForm.StartPosition = FormStartPosition.CenterScreen;
            animationForm.TopMost = true;
            animationForm.Width = _CalculateFormWidth(animationForm);

            animationForm.Show();

            while (_animating)
            {
                animationForm.CaptionLabel.Text = _caption;
                animationForm.Width = _CalculateFormWidth(animationForm);

                animationForm.BringToFront();
                animationForm.Refresh();
            }
            animationForm.Close();
            animationForm.Dispose();
        }

        private int _CalculateFormWidth(ProgressIndicatorForm animationForm)
        {
            int width = AnimationPic.Location.X + AnimationPic.Width +
                TextRenderer.MeasureText(_caption, animationForm.Font).Width;


            return width;
        }
    }
}

标题在设计器中的

这就是它在设计器中的外观,进度对话框

I need to calculate Windows Form Width for displayed text.
The form width is obviously in pixels so you would just want to obtain the width of the text in pixels but this doesn't work:

animationForm.Width = TextRenderer.MeasureText(_caption, animationForm.Font).Width;

The calculated form width is way too small (cuts off text) - what is going on here?
MeasureText uses pixels, form width is in pixels.

This works better but I don't think is right:

animationForm.Width = (int)(_caption.Length * animationForm.Font.Size);

Help would be appreciated.

AnimationPic - PictureBox,
Caption is set on a Label

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace PrlSystems.MaimInvoicing.Forms
{
    public partial class ProgressIndicatorForm : Form
    {
        private volatile bool _animating = false;
        private Form _parent;
        private string _caption = "";

        private object _mutex = new object();

        public ProgressIndicatorForm(Form parent)
        {
            InitializeComponent();
            _parent = parent;
        }

        public string Caption
        {
            set { _caption = value; }
            get { return _caption; }
        }

        public void StartAnimation()
        {
            lock (_mutex)
            {
                if (!_animating)
                {
                    if (_parent != null)
                    {
                        _parent.Cursor = Cursors.WaitCursor;
                        _parent.Enabled = false;
                    }

                    _animating = true;
                    _SpawnAnimationThread();
                }
            }
        }

        public void StopAnimation()
        {
            lock (_mutex)
            {
                if (_animating)
                {
                    _animating = false; // stop animation thread

                    if (_parent != null)
                    {
                        // restore parent form UI
                        _parent.Cursor = Cursors.Default;
                        _parent.Enabled = true;
                        _parent.Activate();
                    }
                }
            }
        }

        private void _SpawnAnimationThread()
        {
            Thread animationThread = new Thread(new ThreadStart(_Animate));
            animationThread.Priority = ThreadPriority.Normal;
            animationThread.IsBackground = true;    // should terminate when application ends
            animationThread.Start();
        }

        private void _Animate()
        {
            ProgressIndicatorForm animationForm = new ProgressIndicatorForm(_parent);
            animationForm.CaptionLabel.Text = _caption;
            animationForm.StartPosition = FormStartPosition.CenterScreen;
            animationForm.TopMost = true;
            animationForm.Width = _CalculateFormWidth(animationForm);

            animationForm.Show();

            while (_animating)
            {
                animationForm.CaptionLabel.Text = _caption;
                animationForm.Width = _CalculateFormWidth(animationForm);

                animationForm.BringToFront();
                animationForm.Refresh();
            }
            animationForm.Close();
            animationForm.Dispose();
        }

        private int _CalculateFormWidth(ProgressIndicatorForm animationForm)
        {
            int width = AnimationPic.Location.X + AnimationPic.Width +
                TextRenderer.MeasureText(_caption, animationForm.Font).Width;


            return width;
        }
    }
}

Image in the designer:

This is how it looks in the designer, the progress dialog

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

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

发布评论

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

评论(3

知你几分 2024-11-15 16:39:22

您需要使用 < 而不是 Form.Width强>Form.ClientSize.Width

后者将返回表单客户区的实际宽度;即,你可以画东西的地方。来自文档的备注部分:

表单客户区的大小是表单不包括边框和标题栏的大小。窗体的客户区是窗体内可以放置控件的区域。在执行图形操作或在窗体上调整控件的大小和位置时,可以使用此属性来获取正确的尺寸。要获取整个表单的大小,请使用 Size 属性 或使用各​​个属性高度宽度

Form.Width(或 Form.Size.Width)对比,后者返回屏幕上显示的表单的整个宽度,包括非客户区域中多余的东西,例如窗口边框。绝对不要浪费任何时间尝试手动计算和删除这些项目的尺寸;它已经为你完成了。


使用以下代码:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    string longStringOfText = "This is a really long string of text we're using for testing purposes.";

    // Resize the form's client area, keeping the same height, but
    // changing the width to match that needed to draw the text.
    this.ClientSize = new Size(TextRenderer.MeasureText(longStringOfText,
                                                        this.Font).Width,
                               ClientSize.Height);

    // Then draw in the text.
    TextRenderer.DrawText(e.Graphics,
                          longStringOfText,
                          this.Font,
                          Point.Empty,
                          Color.Purple);
}

我得到这个:

对我来说看起来不错......

Rather than Form.Width, you need to use Form.ClientSize.Width.

The latter will return the actual width of the form's client area; i.e., the place where you can draw stuff. From the Remarks section in the documentation:

The size of the client area of the form is the size of the form excluding the borders and the title bar. The client area of a form is the area within a form where controls can be placed. You can use this property to get the proper dimensions when performing graphics operations or when sizing and positioning controls on the form. To get the size of the entire form, use the Size property or use the individual properties Height and Width.

Contrast that with Form.Width (or Form.Size.Width), which returns the entire width of the form as it appears on the screen, including superfluous stuff in the non-client area, like window borders. Definitely don't waste any time trying to calculate and remove the dimensions for these items manually; it's already been done for you.


Using the following code:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    string longStringOfText = "This is a really long string of text we're using for testing purposes.";

    // Resize the form's client area, keeping the same height, but
    // changing the width to match that needed to draw the text.
    this.ClientSize = new Size(TextRenderer.MeasureText(longStringOfText,
                                                        this.Font).Width,
                               ClientSize.Height);

    // Then draw in the text.
    TextRenderer.DrawText(e.Graphics,
                          longStringOfText,
                          this.Font,
                          Point.Empty,
                          Color.Purple);
}

I get this:

Form, with text string correctly fit across it

Looks pretty good to me...

述情 2024-11-15 16:39:22

您还需要考虑额外的尺寸,例如表格的宽度。标签周围的空间(如果您使用标签?)

You also need to take account the extra sizes such as width of the form. Space around the label(if you are using label?)

初吻给了烟 2024-11-15 16:39:22

您是否尝试过指定设备上下文?
尝试重载此方法 MeasureText(IDeviceContext, String, Font, Size)

当您使用Form.Width时,宽度还包含窗口边框的宽度。试试这个:

animationForm.ClientSize.Width = TextRenderer.MeasureText(_caption, animationForm.Font).Width;

Have you tried specifying device context?
Try this method overload MeasureText(IDeviceContext, String, Font, Size).

When you use Form.Width, the width contains also width of the window border. Try this:

animationForm.ClientSize.Width = TextRenderer.MeasureText(_caption, animationForm.Font).Width;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文