Adapt the size of a form to its title text in C#

前端 未结 2 1644
轻奢々
轻奢々 2020-12-10 17:49

Is there a way to adapt the size of a form to the size of its title / caption text?

For example, official C# Message Box forms will adjust to the size of its title t

相关标签:
2条回答
  • 2020-12-10 18:37

    For those who wants a full answer, here it is.

    The actual line that resizes the form according to the caption text is the following:

    this.Width = TextRenderer.MeasureText(this.Text, SystemFonts.CaptionFont).Width + AllButtonsAndPadding;
    

    AllButtonsAndPadding contains the width of all the buttons (minimize, maximize and close), the window borders and the icon. Getting these information takes a bit of coding. Here's a full example of a form that resizes itself, no matter what buttons or icon you put.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Windows.Forms.VisualStyles;
    
    namespace WindowAutoAdapt
    {
    public partial class Form1 : Form
    {
        //A default value in case Application.RenderWithVisualStyles == false
        private int AllButtonsAndPadding = 0;
        private VisualStyleRenderer renderer = null;
    
        public Form1()
        {
            InitializeComponent();
            this.Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; //A big text in the title
            GetElementsSize();
            ResizeForm();
        }
    
        //This gets the size of the X and the border of the form
        private void GetElementsSize()
        {
            var g = this.CreateGraphics();
    
            // Get the size of the close button.
            if (SetRenderer(VisualStyleElement.Window.CloseButton.Normal))
            {
                AllButtonsAndPadding += renderer.GetPartSize(g, ThemeSizeType.True).Width;
            }
    
            // Get the size of the minimize button.
            if (this.MinimizeBox && SetRenderer(VisualStyleElement.Window.MinButton.Normal))
            {
                AllButtonsAndPadding += renderer.GetPartSize(g, ThemeSizeType.True).Width;
            }
    
            // Get the size of the maximize button.
            if (this.MaximizeBox && SetRenderer(VisualStyleElement.Window.MaxButton.Normal))
            {
                AllButtonsAndPadding += renderer.GetPartSize(g, ThemeSizeType.True).Width;
            }
    
            // Get the size of the icon.
            if (this.ShowIcon)
            {
                AllButtonsAndPadding += this.Icon.Width;
            }
    
            // Get the thickness of the left, bottom, 
            // and right window frame.
            if (SetRenderer(VisualStyleElement.Window.FrameLeft.Active))
            {
                AllButtonsAndPadding += (renderer.GetPartSize(g, ThemeSizeType.True).Width) * 2; //Borders on both side
            }
        }
    
        //This resizes the form
        private void ResizeForm()
        {
            this.Width = TextRenderer.MeasureText(this.Text, SystemFonts.CaptionFont).Width + AllButtonsAndPadding;
        }
    
        //This sets the renderer to the element we want
        private bool SetRenderer(VisualStyleElement element)
        {
            bool bReturn = VisualStyleRenderer.IsElementDefined(element);
    
            if (bReturn && renderer == null)
                renderer = new VisualStyleRenderer(element);
            else
                renderer.SetParameters(element);
    
            return bReturn;
        }
     }
     }
    
    0 讨论(0)
  • 2020-12-10 18:43

    Thanks @CydrickT, that was helpful. I have some modification that were needed when applying this to a window with FormBorderStyle of FixedDialog and if ControlBox == false on the form (needs try catch to handle error thrown).

    Also even though and icon is specified, certain FormBorderStyle's don't display them (even though ShowIcon == true which your code based some logic on) so this version of code adjusts for that.

    I also added a new private property that holds the minimum width of the window that is set in the constructor to the minimum width if it was specified or the design time width if not. This allows contraction of the window's width if it were to have its text (title) changed in code and then the form redisplayed.

    I added a text changed method for the form's text: Form1_TextChanged() so that anytime the form's title text is changed the form width adjusts (again, if reusing the form instance). The form's designer of course would need to set this for the Text Changed event to be used.

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Windows.Forms.VisualStyles;
    
    namespace WindowAutoAdapt
    {
        public partial class Form1: Form
        {
            private int AllButtonsAndPadding = 10;//seems things are coming up about this amount short so.  . .
            private VisualStyleRenderer renderer = null;
            private int minWidth = 0;//will hold either the minimum size width if specified or the design time width of the form.
    
            public Form1()
            {
                InitializeComponent();
    
                //Capture an explicit minimum width if present else store the design time width.
                if (this.MinimumSize.Width > 0)
                {
                    minWidth = this.MinimumSize.Width;//use an explicit minimum width if present.
                }
                else
                {
                    minWidth = this.Size.Width;//use design time width
                }
    
                GetElementsSize();
                ResizeForm();
            }
    
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_TextChanged(object sender, EventArgs e)
        {
            GetElementsSize();
            ResizeForm();
        }
    
            //This gets the size of the X and the border of the form
            private void GetElementsSize()
            {
                var g = this.CreateGraphics();
    
                // Get the size of the close button.
                if (SetRenderer(VisualStyleElement.Window.CloseButton.Normal))
                {
                    AllButtonsAndPadding += renderer.GetPartSize(g, ThemeSizeType.True).Width;
                }
    
                // Get the size of the minimize button.
                if (this.MinimizeBox && SetRenderer(VisualStyleElement.Window.MinButton.Normal))
                {
                    AllButtonsAndPadding += renderer.GetPartSize(g, ThemeSizeType.True).Width;
                }
    
                // Get the size of the maximize button.
                if (this.MaximizeBox && SetRenderer(VisualStyleElement.Window.MaxButton.Normal))
                {
                    AllButtonsAndPadding += renderer.GetPartSize(g, ThemeSizeType.True).Width;
                }
    
                // Get the size of the icon only if it is actually going to be displayed.
                if (this.ShowIcon && this.ControlBox && (this.FormBorderStyle == FormBorderStyle.Fixed3D || this.FormBorderStyle == FormBorderStyle.Sizable || this.FormBorderStyle == FormBorderStyle.FixedSingle))
                {
                    AllButtonsAndPadding += this.Icon.Width;
                }
    
                // Get the thickness of the left and right window frame.
                if (SetRenderer(VisualStyleElement.Window.FrameLeft.Active))
                {
                    AllButtonsAndPadding += (renderer.GetPartSize(g, ThemeSizeType.True).Width) * 2; //Borders on both side
                }
            }
    
            //This resizes the form
            private void ResizeForm()
            {
                //widen window if title length requires it else contract it to the minWidth if required.
                int newWidth = TextRenderer.MeasureText(this.Text, SystemFonts.CaptionFont).Width + AllButtonsAndPadding;
                if (newWidth > minWidth)
                {
                    this.Width = newWidth;
                }
                else
                {
                    this.Width = minWidth;
                }
            }
    
            //This sets the renderer to the element we want
            private bool SetRenderer(VisualStyleElement element)
            {
                try
                {
                    bool bReturn = VisualStyleRenderer.IsElementDefined(element);
                    if (bReturn && renderer == null)
                    {
                        renderer = new VisualStyleRenderer(element);
                    }
                    else
                    {
                        renderer.SetParameters(element);
                    }
                    return bReturn;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题