How to override the preferred size of a WinForms TextBox?

走远了吗. 提交于 2019-12-01 08:40:25
Olivier Jacot-Descombes

See the answer of Phil Wright for the SO question What is the purpose of Control.GetPreferredSize method?:

"The Control.GetPreferredSize is called by containers as part of the layout cycle.

It allows the called control to return the size they would like to have if possible. The container does not have to honor this requested size however. For example, when a control has a Dock setting of Top the width would be defined as the width of the containing control regardless of the value returned from the GetPreferredSize method. This method is particularly useful for containers like the flow layout control which will position each child control one after another." [Phil Wright]

This means that this PreferredSize will not change the size of your TextBox.


I think this solves your problem:

public class MyTextBox : TextBox
{
    const int RequestedHight = 30;

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        AssureRequestedHight();
    }

    protected override void OnCreateControl()
    {
        base.OnCreateControl();
        AssureRequestedHight();
    }

    private void AssureRequestedHight()
    {
        if (this.Size.Height != RequestedHight && !this.Multiline) {
            this.Multiline = true;
            this.MinimumSize = new Size(0, RequestedHight);
            this.Size = new Size(this.Size.Width, RequestedHight);
            this.Multiline = false;
        }
    }
}

Have you tried doing an override of

protected override System.Drawing.Size DefaultSize
{ get { return new System.Drawing.Size( 145, 52 ); } }

or whatever size you need

Depending on your purposes, and something I've done in the past was to create my own sub-classes for certain controls and did an override of things like FontSize, FontName, Size, etc and made them all as read-only (only applying an externally visible "getter" ). By doing this, any instances of my class that were put onto a WinForms form that had the design-time serialization would nag at me to get rid of the "read-only" property from the designer. After doing so early on in the development, these controls never had a problem again. If I ever changed it, the form would get the newest value/size/font in the designer without having to go through every form and every instance of the control.

I found it to work well with things like a textbox that would be showing date only, or date/time fields, additionally applied to labels, command buttons, and other "common" purpose elmeents. So, throughout the app, it was almost like applying a cascading style sheet, but at a WinForms level.

Just a thought and hope it opens you to another approach to your dilemma.

I found a solution for the Rich text box height issues.. i have modified it a for general use..

Create following structs in your application....

[StructLayout(LayoutKind.Sequential)]
    public struct RECT {
        public Int32 left;
        public Int32 top;
        public Int32 right;
        public Int32 bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SCROLLBARINFO {
        public Int32 cbSize;
        public RECT rcScrollBar;
        public Int32 dxyLineButton;
        public Int32 xyThumbTop;
        public Int32 xyThumbBottom;
        public Int32 reserved;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Int32[] rgstate;
    }

Create following private variables in your class for form (where ever you need to calculate rich text height)

private UInt32 SB_VERT = 1;
        private UInt32 OBJID_VSCROLL = 0xFFFFFFFB;

        [DllImport("user32.dll")]
        private static extern
            Int32 GetScrollRange(IntPtr hWnd, UInt32 nBar, out Int32 lpMinPos, out Int32 lpMaxPos);

        [DllImport("user32.dll")]
        private static extern
            Int32 GetScrollBarInfo(IntPtr hWnd, UInt32 idObject, ref SCROLLBARINFO psbi);

Add following method to your Class for form

private int CalculateRichTextHeight(string richText) {
            int height = 0;
            RichTextBox richTextBox = new RichTextBox();
            richTextBox.Rtf = richText;
            richTextBox.Height = this.Bounds.Height;
            richTextBox.Width = this.Bounds.Width;
            richTextBox.WordWrap = false;
            int nHeight = 0;
            int nMin = 0, nMax = 0;

            SCROLLBARINFO psbi = new SCROLLBARINFO();
            psbi.cbSize = Marshal.SizeOf(psbi);

            richTextBox.Height = 10;
            richTextBox.ScrollBars = RichTextBoxScrollBars.Vertical;

            int nResult = GetScrollBarInfo(richTextBox.Handle, OBJID_VSCROLL, ref psbi);
            if (psbi.rgstate[0] == 0) {
                GetScrollRange(richTextBox.Handle, SB_VERT, out nMin, out nMax);
                height = (nMax - nMin);
            }

            return height;
        }

You may need to modify above method to make it work as per your requirement... Make sure to send Rtf string as parameter to method not normal text and also make sure to assign available width and height to the Richtextbox variable in the method...

You can play with WordWrap depending on your requirement...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!