简体   繁体   中英

TextBox border not being drawn when in a Panel

I've been messing around with this Paint method for hours now. This is the cleanest/closest solution I could come up with. I even tried making a custom TextBox Control instead, but I think that's out of my current skill set. FYI I am new to VS and C#, so take it easy on me please.

    //Draw Borders around our Controls
    private void Form1_Paint(object sender, PaintEventArgs e)
    {

        //Loops through all our text boxes and draws a border
        //Works fine when the textbox is just in the form.
        foreach (TextBox txt in this.Controls.OfType<TextBox>())
        {
            Rectangle rect = new Rectangle(txt.Location.X, txt.Location.Y, txt.ClientSize.Width, txt.ClientSize.Height);

            rect.Inflate(1, 1);
            ControlPaint.DrawBorder(e.Graphics, rect, Color.FromArgb(255, 0, 0), ButtonBorderStyle.Solid);
        }


        //Loops through all Panels and draws a border
        foreach (Panel pnl in this.Controls.OfType<Panel>())
        {
            Rectangle rect = new Rectangle(pnl.Location.X, pnl.Location.Y, pnl.ClientSize.Width, pnl.ClientSize.Height);

            rect.Inflate(1, 1);
            ControlPaint.DrawBorder(e.Graphics, rect, Color.FromArgb(0, 0, 0), ButtonBorderStyle.Solid);

            //Loops through all our TextBoxes in the Panels and draws a border
            //Not drawing the border around the textbox
            foreach (TextBox txt in pnl.Controls.OfType<TextBox>())
            {
                rect = new Rectangle(txt.Location.X, txt.Location.Y, txt.ClientSize.Width, txt.ClientSize.Height);

                rect.Inflate(1, 1);
                ControlPaint.DrawBorder(e.Graphics, rect, Color.FromArgb(255, 0, 0), ButtonBorderStyle.Solid);
                txt.Text = "FML";       //Just added this to see if we were interacting with each TextBox, and we are.
            }

        }


        //To simplify the nested loop above I tried to just draw a border directly to textBox2, which is inside a Panel.
        Rectangle rect2 = new Rectangle(textBox2.Location.X, textBox2.Location.Y, textBox2.ClientSize.Width, textBox2.ClientSize.Height);

        rect2.Inflate(1, 1);
        ControlPaint.DrawBorder(e.Graphics, rect2, Color.FromArgb(255, 0, 0), ButtonBorderStyle.Solid);
        textBox2.Text = "Hello World";      //Still changing the text, just no border.

    }

You can't see the drawing because your coordinates are off because you mix two things:

  • You draw in the Form.Paint event, but..
  • You use the Textboxes ' Locations , which are relative to the Panel they sit in.

You can either

  • use the Panel.Paint event or..
  • calculate the TextBox locations to be relative to the Form .

For the latter solution you can use the Rectangle.Offset(Point) function. Do take the border styles into account; also note that ClientSize is the area inside the borders only..

The first solution also assumes the Panel is transparent and that no other controls are between Panel and Form !

This works for me:

rect = new Rectangle(textBox3.Left - 1, textBox3.Top - 1,
                     textBox3.Width + 1, textBox3.Height + 1);
rect.Offset(panel1.Location);

Also note that Rectangle.Inflate(a,b) will not just increase Width by a but by a*2 and also decrease Left by a etc.

Final note: Do note that there is a difference of how DrawRectangle and FillRectangle treat the size to draw or fill!

https://github.com/vignesh-nethaji/Windows-Custom-Controls/blob/master/Menporul.Windows/Menporul.Windows.Controls/Controls/MenTextBox.cs

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;


namespace Menporul.Windows.Controls
{
    /// <summary>
    /// Menporul TextBox
    /// </summary>
    /// <author>Vignesh Nethaji</author>
    public class MenTextBox : TextBox
    {
        /// <summary>
        /// Border Color when textbox focus
        /// </summary>
        private Color _focusBorderColor = Color.Blue;
        /// <summary>
        /// Default Border Color 
        /// </summary>
        private Color _defaultBorderColor = Color.Gray;
        /// <summary>
        /// 
        /// </summary>
        public MenTextBox()
        {


        }
        /// <summary>
        /// On control resize refresh the control for Border rendering based on the control size
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            this.Refresh();
        }
        /// <summary>
        /// Getting device context for creating graphics for draw border on textbox
        /// </summary>
        /// <param name="hwnd"></param>
        /// <returns></returns>
        [DllImport("user32")]
        private static extern IntPtr GetWindowDC(IntPtr hwnd);
        /// <summary>
        /// Draw textbox border when its painting 
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == 0x85 || m.Msg == 0x000F)
            {
                Rectangle rect = new Rectangle(0, 0, Width, Height);
                if (this.Focused)
                {

                    var dc = GetWindowDC(Handle);
                    using (Graphics g = Graphics.FromHdc(dc))
                    {
                        ControlPaint.DrawBorder(g, rect,
                       _focusBorderColor, 2, ButtonBorderStyle.Solid,
                       _focusBorderColor, 2, ButtonBorderStyle.Solid,
                       _focusBorderColor, 2, ButtonBorderStyle.Solid,
                       _focusBorderColor, 2, ButtonBorderStyle.Solid);
                    }
                }
                else
                {

                    var dc = GetWindowDC(Handle);
                    using (Graphics g = Graphics.FromHdc(dc))
                    {
                        ControlPaint.DrawBorder(g, rect,
                       _defaultBorderColor, 1, ButtonBorderStyle.Solid,
                       _defaultBorderColor, 1, ButtonBorderStyle.Solid,
                       _defaultBorderColor, 1, ButtonBorderStyle.Solid,
                       _defaultBorderColor, 1, ButtonBorderStyle.Solid);
                    }
                }
            }

        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM