开发者

Draw border around a Control on Button_Click

When a user clicks my Validate Button (in my C#, WinForm, .net 3.5 app) I would like to draw a border around a certain control if it is empty. Say a textbox that is named tbxLastName I thought I needed to do something like this -->

ControlPaint.DrawBorder(Graphics.FromHwnd(this.Handle), 
    tbxLastName.ClientRectangle, Color.Firebrick, ButtonBorderStyle.Solid);

Unfortunately, I have no idea what to put for the Graphics Object as what I have does NOTHING.

All of the examples I have come across, MSDN - HERE, have this code in a Paint Event. Like so -->

private void panel1_Paint(object sender, PaintEventArgs e)
{    
    ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, 
        Color.DarkBlue, ButtonBorderStyle.Solid);
}

I, however, only want to have the border appear while certain conditions are meet which is kicked off by a Button_Click


So many of the suggestions suggest using a container object to hold the textbox and call it's Paint_Event. I did this and a box appears but NOT around the control. It appears in the Top Left corner of the Container Control. Here is what I am doing -->

    private void grpImmunizationCntrl_Paint(object sender, PaintEventArgs e)
    {
        if (lkuNOImmunizationReason.Text.Equals(string.Empty)
        {
           ControlPaint.DrawBorder(
                    e.Graphics, lkuNOImmunizationReason.ClientRectangle,
                        Color.Firebrick, ButtonBorderStyle.Solid);
        }
    }

EDIT

This is what I came up with combining suggestions here with what worked for me.

    public static void HighlightRequiredFields(Control container, Graphics graphics, Boolean isVisible)
    {
        Rectangle rect = default(Rectangle);
        foreach (Control control in container.Controls)
        {
            if (control.Tag is string && control.Tag.ToString() == "required")
            {
                rect = control.Bounds;
                rect.Inflate(3, 3);
                if (isVisible && control.Text.Equals(string.Empty))
                {
                    ControlPaint.DrawBorder(graphics, rect, Color.FromArgb(173,216,23开发者_如何学运维0), ButtonBorderStyle.Solid);
                }
                else
                {
                    ControlPaint.DrawBorder(graphics, rect, container.BackColor, ButtonBorderStyle.None);
                }
            }

            if (control.HasChildren)
            {
                foreach (Control ctrl in control.Controls)
                {
                    HighlightRequiredFields(ctrl, graphics, isVisible);
                }
            }
        }
    }

I call this from the Paint_Event of any Container I need to.


you can use a list of actions field in the form and add or remove, custom drawings:

// field
List<Action<Graphics>> drawings = new List<Action<Graphics>>();

// on click event:
drawings.Add(delegate(Graphics g) {
    var rect = tbxLastName.Bounds;
    rect.Inflate(1, 1); // make rectange a bit larger than textbox
    ControlPaint.DrawBorder(g, rect, 
    Color.DarkBlue, ButtonBorderStyle.Solid);
});
// make sure you added only once or clear before
panel1.Refresh(); // refresh panel to force painting


// Paint method:
foreach (var draw in drawings) {
    draw(e.Graphics);
}

This way you can add more than one border


I just did something similar with VB.Net, with help from this thread. I have a Panel container around each set of my controls, and in the OnPaint handler for the Panel, I loop through all the children controls in the Panel and draw borders around them if they have the tag="required". I only display the borders on Edit or New so I created the fVisible parameter to toggle these on and off. When I want to fire this off, I call Panel.Refresh() so it fires the OnPaint event. This way all I have to do is set the tags on the required controls at design time, and add a handler for the container Panels, and it all works dynamically.

Here's the shared function I'm calling from all of my Panel's OnPaint Event Handlers. (Sorry I know you're using C# and this is VB but it's pretty basic.)

Friend Sub HighlightRequiredFields(ByVal pnlContainer As Panel, ByVal gr As Graphics, ByVal fVisible As Boolean)
    Dim rect As Rectangle
    For Each oControl As Control In pnlContainer.Controls
        If TypeOf oControl.Tag Is String AndAlso oControl.Tag.ToString = "required" Then
            rect = oControl.Bounds
            rect.Inflate(1, 1)
            If fVisible Then
                ControlPaint.DrawBorder(gr, rect, Color.Red, ButtonBorderStyle.Solid)
            Else
                ControlPaint.DrawBorder(gr, rect, pnlContainer.BackColor, ButtonBorderStyle.None)
            End If
        End If
        If TypeOf oControl Is Panel Then HighlightRequiredFields(DirectCast(oControl, Panel), gr, fVisible)
    Next
End Sub


    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        if (string.IsNullOrEmpty(Text))
        {
            this.BorderStyle = BorderStyle.FixedSingle;
        }
        else 
        {
            this.BorderStyle = BorderStyle.Fixed3D;
        }
    }


The reason that your rectangle is "missing" the text box is that ClientRectangle only contains the size of the control, not the location. Try this instead:

private void grpImmunizationCntrl_Paint(object sender, PaintEventArgs e)
{
    if (lkuNOImmunizationReason.Text.Equals(string.Empty)
    {
       ControlPaint.DrawBorder(
                e.Graphics, new Rectangle(lkuNOImmunizationReason.Left, lkuNOImmunizationReason.Top, lkuNOImmunizationReason.ClientRectangle.Width, lkuNOImmunizationReason.ClientRectangle.Height),
                    Color.Firebrick, ButtonBorderStyle.Solid);
    }
}


Textboxes do not call the OnPaint method (See Note section of this page). A way round this, is to place the textbox in a panel, which is slightly bigger. Then, change the background colour whenever the button is clicked. A thread over at MSDN forums has a few solutions.

Edit To clarify the panel solution, simply create a panel and add your textbox to it: e.g.

private void MyForm_Load(object sender, EventArgs e)
{
     myPanel.Controls.Add(tbxLastName); //Make sure the panel size is slightly bigger than the text box (so that it looks like a border)
}

Then, handle your button click event:

private void myButton_Click(object sender, EventArgs e)
    {
        if (tbxLastName.Text == "")
        {
            myPanel.BackColor = Color.Red;
        }
        else
        {
            myPanel.BackColor = Color.Transparent;
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜