在Button_Click的控件周围绘制边框

时间:2021-09-04 23:57:12

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

当用户单击我的Validate按钮(在我的c#、WinForm、。net 3.5应用中)时,如果某个控件是空的,我想在它周围画一个边框。假设有一个名为tbxLastName的文本框,我想我需要这样做——>

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

所有我遇到的例子,MSDN -这里,有这个代码在一个油漆事件。像- - >

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

但是,我只希望在某些条件满足的情况下出现边界,而这些条件是由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 -->

很多建议建议使用容器对象来保存文本框并将其命名为Paint_Event。我做了这个,一个盒子出现了,但不是在控制范围内。它出现在容器控件的左上角。这就是我要做的——>

    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,230), 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.

我从任何需要的容器的Paint_Event调用它。

5 个解决方案

#1


2  

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.

我只是用VB做了一些类似的事情。Net,在这个线程的帮助下。我在每一组控件周围都有一个面板容器,在面板的OnPaint处理程序中,我循环遍历面板中的所有子控件,并在它们周围绘制边框,如果它们有标记=“required”。我只在Edit或New上显示边框,因此我创建了fVisible参数来开关这些边框。这样,我所要做的就是在设计时设置必需控件上的标记,并为容器面板添加一个处理程序,这一切都是动态工作的。

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.)

这是我从我的面板的OnPaint事件处理程序调用的共享函数。(对不起,我知道你用的是c#,这是VB,但它很基础。)

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

#2


3  

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

这样可以添加多个边框

#3


1  

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

#4


1  

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:

矩形“缺少”文本框的原因是,ClientRectangle只包含控件的大小,而不包含位置。试试这个:

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

#5


1  

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.

文本框不调用OnPaint方法(参见本页面的注释部分)。解决这个问题的一种方法是将文本框放在一个稍微大一点的面板中。然后,每当单击按钮时改变背景颜色。MSDN论坛上的一个线程有一些解决方案。

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

#1


2  

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.

我只是用VB做了一些类似的事情。Net,在这个线程的帮助下。我在每一组控件周围都有一个面板容器,在面板的OnPaint处理程序中,我循环遍历面板中的所有子控件,并在它们周围绘制边框,如果它们有标记=“required”。我只在Edit或New上显示边框,因此我创建了fVisible参数来开关这些边框。这样,我所要做的就是在设计时设置必需控件上的标记,并为容器面板添加一个处理程序,这一切都是动态工作的。

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.)

这是我从我的面板的OnPaint事件处理程序调用的共享函数。(对不起,我知道你用的是c#,这是VB,但它很基础。)

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

#2


3  

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

这样可以添加多个边框

#3


1  

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

#4


1  

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:

矩形“缺少”文本框的原因是,ClientRectangle只包含控件的大小,而不包含位置。试试这个:

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

#5


1  

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.

文本框不调用OnPaint方法(参见本页面的注释部分)。解决这个问题的一种方法是将文本框放在一个稍微大一点的面板中。然后,每当单击按钮时改变背景颜色。MSDN论坛上的一个线程有一些解决方案。

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