Anton Yurkov
Anton Yurkov

Reputation: 1

Windows forms textbox font color change for a limited time

I am new to C# and Windows Forms, but here is a thing: I wanna change text color in my textbox named NameField to red if my boolean function returns false;

I tried using NameField.ForeColor = System.Drawing.Color.Red; but it changes it forever to red, but I want just for a few seconds. Is it possible?

Upvotes: 0

Views: 1403

Answers (5)

Angelo Ferrante
Angelo Ferrante

Reputation: 11

Using a Timer.
Example:
NameField.ForeColor = System.Drawing.Color.Red

Timer timer1 = new Timer
{
    Interval = 1000
};
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(delegate (Object o, EventArgs a)
{  
    NameField.ForeColor = SystemColors.WindowText;
    timer1.Enabled = false;
});

Upvotes: 0

JonasH
JonasH

Reputation: 36596

The simplest way is to use Task.Delay. Assuming you want to do this when a button is clicked:

private async void button1_Click(object sender, EventArgs e){
    try{
        NameField.ForeColor = System.Drawing.Color.Red;
        await Task.Delay(1000); // 1s
        NameField.ForeColor = System.Drawing.Color.Blue;
    }
     catch(Exception e){
          // handle exception
      }
}

A timer is another alternative, but then you would need to disable the timer in the event handler if you only want it to trigger once. Task.Delay does more or less the same thing, but is a bit neater.

Keep in mind the try/catch, whenever you use async void you want to catch any exceptions to ensure that they are not lost.

You might also want to consider repeated button presses. Either disable the button, or increment some field, and only reset the color if the field has the same value as when you set the color.

Upvotes: 2

Harald Coppoolse
Harald Coppoolse

Reputation: 30474

In your object oriented class, you learned that if you want a class that is almost the same as another class, but just one little functionality different, that you should derive.

So let's make a class, derived from button that changes color and automatically returns to default color after some time.

The button will have a Flash method, which will change the color of the Button. After some specified time the button will Unflash.

For this the class has properties to specify the Foreground / Background colors as well as the flash time.

public class FlashOnceButton : Button
{
    private readonly Timer flashTimer
    private Color preFlashForeColor;
    private Color preFlashBackColor;

    public FlashOnceButton()
    {
         this.flashTimer = new Timer
         {
             AutoReset = false,
         };
         this.flashTime.Elapsed += FlashTimer_Elapsed;
    }

    public Color FlashBackColor {get; set;} = Color.Red;
    public Color FlashForeColor {get; set;} = base.ForeColor;
    public TimeSpan FlashTime {get; set;} = TimeSpan.FromSeconds(1);

    public bool IsInFlashState => this.Timer.Enabled;

    public void StartFlash()
    {
        // if already flashing, do nothing            
        if (this.IsInFlashState) return;

        // before changing the colors remember the current fore/back colors
        this.preFlashForeColor = this.ForeColor;
        this.preFlashBackcolor = this.BackColor;
        this.ForeColor = this.FlashForeColor;
        this.BackColor = this.FlashBackColor;

        this.Timer.Interval = this.FlashTime.TotalMilliseconds;
        this.Timer.Enabled = true;
    }
        
    private void FlashTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // restore the colors:
        this.ForeColor = this.preFlashForeColor;
        this.BackColor = this.preFlashBackColor;
        this.flashTimer.Enabled = false;
    }
}

Usage: After compilation you should find this class in visual studio Toolbox. So you can add it using the visual studio designer and set the properties.

You'll find this in InitializeComponent. Alternatively you can set it in your constructor

I wanna change text color in my textbox named NameField to red if my boolean function returns false;

public void OnBooleanChangedFalse()
{
    this.flashOnceButton1.StartFlash();
}

That's all!

There is one quirk: class Timer implements IDisposable, so you should Dispose it if you stop your form.

public class FlashOnceButton : Button
{
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            this.flashTimer.Dispose();
        }
    }
}

The easiest way to make sure that the button is disposed when your form is disposed, is to at it to the form's components field:

public void MyForm()
{
    InitializeComponent();   // this will create flashOnceButton1

    // make sure that the button is disposed when the Form is disposed:
    this.components.Add(this.flashOnceButton1);
}

Upvotes: 1

bPuhnk
bPuhnk

Reputation: 385

There are a few ways to handle this. The most straight forward approach would be to use a Timer. If you want to keep the color changed for a period of time then a Stopwatch can be used to capture the elapsed time.

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private Timer _colorTimer; // Create a timer as a private field to capture the ticks
        private Stopwatch _swColor; // Create a stopwatch to determine how long you want the color to change
        private void Form1_Load(object sender, EventArgs e)
        {
            // Initialize fields
            _colorTimer = new Timer();
            _colorTimer.Interval = 10; // in milliseconds
            _colorTimer.Tick += ColorTimer_Tick; // create handler for timers tick event
            _swColor = new Stopwatch();

            NameField.Text = "Person Name"; // For testing purposes
        }

        // the timer will run on a background thread (not stopping UI), but will return to the UI context when handling the tick event
        private void ColorTimer_Tick(object sender, EventArgs e)
        {
            if(_swColor.ElapsedMilliseconds < 1000) // check elapsed time - while this is true the color will be changed
            {
                if(NameField.ForeColor != Color.Red)
                {
                    NameField.ForeColor = Color.Red;
                }
            } 
            else
            {
                // reset the controls color, stop the stopwatch and disable the timer (GC will handle disposal on form close)
                NameField.ForeColor = Color.Black;
                _swColor.Stop();
                _swColor.Reset();
                _colorTimer.Enabled = false;
            }
        }

        private void btnChangeColor_Click(object sender, EventArgs e)
        {
            // on button click start the timer and stopwatch
            _colorTimer.Start();
            _swColor.Start();
        }
    }

Upvotes: 0

Srijon Chakraborty
Srijon Chakraborty

Reputation: 2164

I have solution for you however it is little bit inefficient. Please check and let me know.

        int counter = 1;
        Timer timer1 = new Timer{Interval = 5000};
        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;

            if (myBoolMethod(counter))
            { 
                textBox1.ForeColor = System.Drawing.Color.Red;
                timer1.Tick += OnTimerEvent;
            }
            
            if (counter == 1)
                counter = 2;
            else
                counter = 1;
        }

        private void OnTimerEvent(object sender, EventArgs e)
        {
            textBox1.ForeColor = System.Drawing.Color.Black;
            timer1.Tick -= OnTimerEvent;
        }


        bool myBoolMethod(int param)
        {
           if(param % 2 == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Upvotes: 0

Related Questions