Search code examples
c#winformsvisual-studioflickerdispatchertimer

Flickering buttons with different timespans


Is it possible to use the dispatchertimer class, to create two timers(or more) for two different button, so they will flicker at different timesettings. I have tried to do this in the code I ahve attaced, however, if the two timespans are not the same, lack accors, which it should not i the application I am making.

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Diagnostics;
 using System.Drawing;
 using System.Linq;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System.Windows.Forms;
 using System.Windows.Threading;


namespace UDPReceiveWPF
{
public partial class Form1 : Form
{
    bool button_flag = true;

    private byte[] dataStream = new byte[1024];
    private Socket udpSock;
    private byte[] buffer;

    private DispatcherTimer dispatcherTimer;
    private DispatcherTimer dispatcherTimer2;

    private delegate void DisplayMessageDelegate(string message);
    private DisplayMessageDelegate displayMessageDelegate = null;

    public Form1()
    {
        InitializeComponent();
        this.displayMessageDelegate = new DisplayMessageDelegate(this.DisplayMessage);

        dispatcherTimer = new DispatcherTimer();
        dispatcherTimer.Tick += dispatcherTimer_Tick;
        dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 100);
        dispatcherTimer.Start();

        dispatcherTimer2 = new DispatcherTimer();
        dispatcherTimer2.Tick += dispatcherTimer2_Tick;
        dispatcherTimer2.Interval = new TimeSpan(0, 0, 0, 0, 50);
        dispatcherTimer2.Start();

        udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        udpSock.Bind(new IPEndPoint(IPAddress.Any, 11000));
        buffer = new byte[1024];

        EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
        udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
    }


    private void DoReceiveFrom(IAsyncResult iar)
    {
        try
        {
            Socket recvSock = (Socket)iar.AsyncState;
            EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
            int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
            byte[] localMsg = new byte[msgLen];
            Array.Copy(buffer, localMsg, msgLen);

            EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
            udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);

            if (msgLen > 0)
            {
                string textToprint = Encoding.UTF8.GetString(localMsg, 0, msgLen);
                this.Invoke(this.displayMessageDelegate, new object[] { textToprint });
            }
        }
        catch (ObjectDisposedException)
        {
        }
    }

    private void DisplayMessage(string messge)
    {
        textBox1.Text += messge + Environment.NewLine;
    }


    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        if (button_flag)
        {
            button3.BackColor = Color.White;
            //button1.BackColor = Color.Black;
            button_flag = false;
        }
        else
        {
            button3.BackColor = Color.Black;
            //button1.BackColor = Color.White;
            button_flag = true;
        }
    }
    private void dispatcherTimer2_Tick(object sender, EventArgs e)
    {
        if (button_flag)
        {
            //button3.BackColor = Color.White;
            button1.BackColor = Color.Black;
            button_flag = false;
        }
        else
        {
            //button3.BackColor = Color.Black;
            button1.BackColor = Color.White;
            button_flag = true;
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }
}
}

Or is there antoher way to do this? - Aslak


Solution

  • You could do it by writing a small extra class that handles this usecase, and example could be the following. The FlickTimer will take any control, and you can define the desired states and colors you wish it to handle ( in this case my colors array)

    public partial class Form1 : Form
    {
        StateWithColor[] colors = new StateWithColor[] {
            new StateWithColor(0, Color.Black),
            new StateWithColor(1, Color.White)
        };
    
        FlickTimer<Button> timer1Button, timer2Button;
    
        public Form1()
        {
            InitializeComponent();
            timer1Button = new FlickTimer<Button>(colors, 500, button1);
            timer2Button = new FlickTimer<Button>(colors, 100, button2);
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
    
        }
    }
    
    public struct StateWithColor
    {
        public int State;
        public Color Color;
    
        public StateWithColor(int state, Color color)
        {
            Color = color;
            State = state;
        }
    }
    
    public class FlickTimer<T> : IDisposable
        where T: Control
    {
        public T Target { get; set; }
    
        protected readonly IList<StateWithColor> possibleStates = new List<StateWithColor>();
        protected int currentState = 0;
        protected object lockState = new object();
        protected Timer timer = new Timer();
    
        protected void Flicker(object sender, EventArgs e)
        {
            if (Target == null)
            {
                return;
            }
            if (Target.InvokeRequired)
            {
                Target.Invoke(new EventHandler(Flicker), sender, e);
                return;
            }
            lock (lockState)
            {
                Target.BackColor = possibleStates[currentState].Color;
                currentState++;
                if (currentState >= possibleStates.Count)
                {
                    currentState = 0;
                }
            }
        }
    
        public FlickTimer(StateWithColor[] states, int timeout = 100, T target = null)
        {
            Target = target;
            lock (lockState)
            {
                foreach (var state in states)
                {
                    possibleStates.Add(state);
                }
            }
            timer.Interval = timeout;
            timer.Tick += Flicker;
            Start();
        }
    
        public void Start()
        {
            timer.Start();
        }
    
        public void Stop()
        {
            timer.Stop();
        }
    
        public void Dispose()
        {
            if (timer != null)
            {
                Stop();
                timer.Tick -= Flicker;
                timer = null;
            }
        }
    }