【问题标题】:Calculate Windows Form Width for Displayed Text计算显示文本的 Windows 窗体宽度
【发布时间】:2011-05-18 13:48:14
【问题描述】:

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

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

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

这样效果更好,但我认为不正确:

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

我们将不胜感激。

AnimationPic - 图片框, 标题设置在标签上

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

设计器中的图像:

【问题讨论】:

  • 我要澄清一些我遗漏的东西,但这很重要。我也有动画图片。这是整个公式:int width = AnimationPic.Location.X + AnimationPic.Width + TextRenderer.MeasureText(_caption, animationForm.Font).Width;

标签: .net winforms forms graphics textrenderer


【解决方案1】:

您需要使用Form.ClientSize.Width,而不是Form.Width

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

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

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

我明白了:

我觉得挺好看的……

【讨论】:

  • @Frosty:你的意思是什么?我是否使用了“被调用”这个词而不是“设置”?我的坏,我会解决它。当然,重点还是一样的。您需要设置客户区的大小,而不是整个表单(包括非客户区)的大小。
  • 伙计们,这是没有任何边框的动画对话框,所以这并不重要。尽管如此,无论我是否使用客户区,我仍然会丢失(因为宽度太短而被截断)40% 的文本。
  • @ActiveX:我无法想象问题是什么。这对我来说非常有效...使用您尝试过的涉及 ClientSize 属性的代码更新您的问题。
  • 我要澄清一些我遗漏的东西,但这很重要。我也有动画图片。这是整个公式:int width = AnimationPic.Location.X + AnimationPic.Width + TextRenderer.MeasureText(_caption, animationForm.Font).Width;
  • 我已经在上面的原始帖子中发布了整个代码。我只对宽度感兴趣,因为它只能改变。
【解决方案2】:

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

【讨论】:

  • 但绝对不要尝试手动执行此操作。使用为此目的明确提供的属性。
  • 是的,我正在使用标签...文本的急剧丢失(被截断)告诉我还有其他问题。我在上面发布了整个代码。
【解决方案3】:

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

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

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

【讨论】:

  • 我很难想象设备上下文在这里是如何相关的。
  • AnimationPic 是直接放在表单上还是放在某个容器中?
  • @ActiveX 能否发一份设计模式下的表单截图?
  • 直接在表格上。表单样式为 FixedDialog,没有最大值、最小值、按钮等。我如何在这里给您发送电子邮件?我是堆栈溢出的新手。
  • @ActiveX:您不需要电子邮件。您可以直接在问题中附加图像。详情请见here
猜你喜欢
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
  • 2010-10-28
  • 1970-01-01
  • 2011-11-25
  • 2010-09-12
相关资源
最近更新 更多