Click here to Skip to main content
15,889,808 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys,

i have 4 textboxes on my windows forms where the user have to type in text.
So if one of the textboxes is empty, i want to fade the background color of all the empty textboxes simultaneously from white to red and back.

What I have tried:

for (int i = 0; i < 255; i++)
     {
         foreach (var myControl in myDailyToDoControlList)
         {
             if (myControl.Text == "")
             {
                 myControl.BackColor =
                 System.Drawing.Color.FromArgb(255, 255 - i, 255 - i);
                 myControl.Refresh();
             }
         }


     }

     for (int i = 0; i < 255;i++ )
     {
         foreach (var myControl in myDailyToDoControlList)
         {
             if (myControl.Text == "")
             {
                 myControl.BackColor =
                 System.Drawing.Color.FromArgb(255, 0 + i, 0 + i);
                 myControl.Refresh();
             }
         }

     }


I mean it works fine, but it is a very slow solution. It takes really long.
So i changed it to this:

for (int i = 0; i < 255; )
     {
         foreach (var myControl in myDailyToDoControlList)
         {
             if (myControl.Text == "")
             {
                 ((Control)myControl).BackColor =
                 System.Drawing.Color.FromArgb(255, 255 - i, 255 - i);
                 myControl.Refresh();
             }
         }

         i+=5;
     }

     for (int i = 0; i < 255;)
     {
         foreach (var myControl in myDailyToDoControlList)
         {
             if (myControl.Text == "")
             {
                 ((Control)myControl).BackColor =
                 System.Drawing.Color.FromArgb(255, 0 + i, 0 + i);
                 myControl.Refresh();
             }
         }
         i+=5;

     }


I removed the i++ in the for statement and increase it with 5 at the end of the for loop. And yes it is faster but its ugly. :)
So im just asking if there is an another faster solution maybe with threading or things like that? Or do you think that my solution is a good one?

Thanks.
dagogi
Posted
Updated 10-Jan-20 9:09am
Comments
CHill60 10-Jan-20 9:48am    
Threading won't make a difference as this would have to be done on the UI thread anyway - the real question is why would you want to fade the colour? Just set it to be a fixed "this textbox needs data entering" colour - instantaneous
[no name] 10-Jan-20 12:32pm    
What do you mean with slow? If I do that on my laptop, fading time with increment 1 is smaller than 2 Sek. If it would be faster you nearly don't see the fading effect.

On the other hand I have to admit, I expected that it would be much more faster. I expected one would not even see the fading effect...

Btw, because of the nonlinear sensitivity you can easily work in a range from 255 down to 55 for "fade in" and opposite for "fade out".

Please see also my comments to the question.

I tried the same in a native c++ W32 Applicattion (c++ Builder). As I expected, in this case it is that fast, that you can't recognize the "color-fading".
So I had a look to the reference source of c# Winform TextBox Reference Source[^] and also to Control.SetStyle(ControlStyles, Boolean) Method (System.Windows.Forms) | Microsoft Docs[^].

I would speculate that you can speed up if you derive from TextBox and use SetStyle to change the drawing behaviour.

Final word
From my point of view, all in all not really worth to do it, but very interesting to dive into the deep of .net ;)


[Edit]
I tried with a UserControl derived from TextBox and was not able to speed up the fading. Here the ultimative hack.

WARNING I would never do this in production code.
// Create a solid brush. The color here is irrelevant
using (SolidBrush shadowBrush = new SolidBrush(Color.Red))
{

    for (int i = 0; i < 255; i++)
    {
        foreach (var myControl in myDailyToDoControlList)
        {
            if (myControl.Text == "")
            {
                shadowBrush.Color = System.Drawing.Color.FromArgb(255, 255 - i, 255 - i);
                Rectangle r = myControl.ClientRectangle;
                Graphics g = myControl.CreateGraphics();
                g.FillRectangle(shadowBrush, r.X, r.Y, r.Width, r.Height);
            }
        }
    }

    for (int i = 0; i < 255; i++)
    {
        foreach (var myControl in myDailyToDoControlList)
        {
            if (myControl.Text == "")
            {
                shadowBrush.Color = System.Drawing.Color.FromArgb(255, 0 + i, 0 + i);
                Rectangle r = myControl.ClientRectangle;
                Graphics g = myControl.CreateGraphics();
                g.FillRectangle(shadowBrush, r.X, r.Y, r.Width, r.Height);
            }
        }

    }
}
 
Share this answer
 
v3
Stop refreshing controls inside a loops!

Keep in mind that MSDN documentation[^] states that:
Forces the control to invalidate its client area and immediately redraw itself and any child controls.

I'd suggest to refresh main container, such as form.

On the other hand, you can create - let say - "BaseForm", which will be a template for the other forms. So, in BaseForm:
C#
protected override void OnLoad(EventArgs e)
{
    //your logic here
    base.OnLoad(e);
}


In other forms:
C#
public partial class OtherForm : BaseForm
{
    //
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900