简体   繁体   English

在Button_Click上的Control周围绘制边框

[英]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. 当用户单击我的验证按钮( 在我的C#,WinForm,.net 3.5应用程序中 )时,如果它是空的,我想在某个控件周围绘制一个边框。 Say a textbox that is named tbxLastName I thought I needed to do something like this --> 说一个名为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. 我遇到的所有示例, MSDN - HERE ,都在Paint事件中包含此代码。 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 但是,我只希望在某些条件满足时出现边框,这是由Button_Click启动的


So many of the suggestions suggest using a container object to hold the textbox and call it's Paint_Event. 许多建议建议使用容器对象来保存文本框并将其命名为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. 它出现在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,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. 我从我需要的任何Container的Paint_Event中调用它。

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. 在这个帖子的帮助下,我刚刚用VB.Net做了类似的事情。 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" . 我有一个Panel周围每组我控制的容器,并在OnPaint处理程序Panel ,我遍历所有的孩子在控制Panel和借鉴他们周围的边框,如果他们有tag="required" I only display the borders on Edit or New so I created the fVisible parameter to toggle these on and off. 我只在Edit或New上显示边框,所以我创建了fVisible参数来打开和关闭它们。 When I want to fire this off, I call Panel.Refresh() so it fires the OnPaint event. 当我想关闭它时,我调用Panel.Refresh()以便它触发OnPaint事件。 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. 这是我从Panel的所有OnPaint事件处理程序调用的共享函数。 (Sorry I know you're using C# and this is VB but it's pretty basic.) (对不起,我知道你使用的是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

Textboxes do not call the OnPaint method (See Note section of this page ). 文本框不会调用OnPaint方法(请参阅this page Note部分)。 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. MSDN论坛上的一个帖子有一些解决方案。

Edit To clarify the panel solution, simply create a panel and add your textbox to it: eg 编辑要阐明面板解决方案,只需创建一个面板并将文本框添加到其中:例如

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;
        }
    }
    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. 矩形“缺少”文本框的原因是ClientRectangle仅包含控件的大小,而不是位置。 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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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