Windows 表单文本框字体颜色限时更改

Windows forms textbox font color change for a limited time

我是 C# 和 Windows 表单的新手,但有一件事: 如果我的布尔函数 returns false;

,我想将名为 NameField 的文本框中的文本颜色更改为红色

我尝试使用 NameField.ForeColor = System.Drawing.Color.Red;,但它会永远变成红色,但我只想要几秒钟。可能吗?

最简单的方法是使用Task.Delay。假设您希望在单击按钮时执行此操作:

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

计时器是另一种选择,但如果您只希望它触发一次,则需要在事件处理程序中禁用计时器。 Task.Delay 做的事情大致相同,但更整洁。

请记住 try/catch,每当您使用 async void 时,您都希望捕获任何异常以确保它们不会丢失。

您可能还想考虑重复按下按钮。要么禁用该按钮,要么增加一些字段,并且仅当该字段的值与您设置颜色时的值相同时才重置颜色。

我有适合您的解决方案,但效率有点低。请检查并告诉我。

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

有几种方法可以解决这个问题。最直接的方法是使用 Timer. If you want to keep the color changed for a period of time then a Stopwatch 可用于捕获经过的时间。

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

在您的面向对象 class 中,您了解到如果您想要一个 class 与另一个 class 几乎相同,但只有一点点功能不同,您应该推导。

所以让我们制作一个 class,派生自改变颜色的按钮,并在一段时间后自动 returns 为默认颜色。

该按钮将有一个 Flash 方法,该方法将改变按钮的颜色。一段时间后,按钮将不闪烁。

为此,class 具有指定前景/背景颜色以及闪光时间的属性。

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

用法:编译后你应该在visual studio工具箱中找到这个class。因此,您可以使用 visual studio 设计器添加它并设置属性。

您将在 InitializeComponent 中找到它。或者你可以在你的构造函数中设置它

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

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

就这些了!

有一个怪癖:class Timer 实现了 IDisposable,所以如果你停止你的表单,你应该处理它。

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

确保在处置表单时处置按钮的最简单方法是将其置于表单的组件字段中:

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