Search code examples
c#timerdrawinggraphics2dthread-sleep

How to display a string for a certain time on Form or PictureBox without using DrawString() method or MessageBox() in C#


I tried to display a string using DrawString() method in onPaint() method depending on a flag in another method periodically ... I failed to display it correctly as it appears then disappears quickly!!.

Is there any other way i.e. without using DrawString() or MessageBox(), in order to display or draw such a message.

Note that I used Thread.Sleep()!.

Inside onPaint() :

 if(auvSend == true) {

                base.OnPaint(e);



                g.DrawString("Received Aggrigated Data from AUV # " + auv[auvSenderID].auvID, font,auvSendMsg, 500, 36); // Display that the sink receive data from the AUV

                MessageBox.Show("Received Aggrigated Data from AUV # " + auv[auvSenderID].auvID);

                player.Play();

                Thread.Sleep(3000);             

                g.DrawImage(new Bitmap("C:/temp/temp.png"), 500, 36, 196, 16);// clear

                player.Stop();

                auv[auvSenderID].queue1.Clear();

                auvSend = false;



            }

I check an array list if it contains a specific number to change the value of the flag in a background do work method:

if (moveBtnIsClicked == false && movebtnGeneticIsClicked == false )
                    {

                        if (auv[0].queue1.Count == 10) 
                        {


                            foreach (Packet packet in auv[0].queue1)
                            {
                                auv[0].SendToSink(packet);
                            }


                            auvSenderID = 0;

                            auvSend = true;

                            topology.Invalidate();                         


                        }



                         if (auv[1].queue1.Count == 10) 
                        {


                            foreach (Packet packet in auv[1].queue1)
                            {
                                auv[1].SendToSink(packet);
                            }

                            auvSenderID = 1;


                            auvSend = true;

                            topology.Invalidate();


                        }


                         if (auv[2].queue1.Count == 10) 
                        {


                            foreach (Packet packet in auv[2].queue1)
                            {
                                auv[2].SendToSink(packet);
                            }


                            auvSenderID = 2;

                            auvSend = true;

                            topology.Invalidate(); 


                        }


                         if (auv[3].queue1.Count == 10) 
                        {


                            foreach (Packet packet in auv[3].queue1)
                            {
                                auv[3].SendToSink(packet);
                            }


                            auvSenderID = 3;

                            auvSend = true;

                            topology.Invalidate();




                        }


                    }

Solution

  • There's not enough context in your question to provide an answer that is tailored to your specific need. However, I believe that the basic approach you're using is fundamentally wrong. I.e. there does not appear to be a reason to put the code in the OnPaint() method, and doing so will block the UI thread, and in the middle of a redraw for that matter (so, doubly wrong).

    Assuming you have a button that initiates the action (called, for example, button1), and a label on the form where you want to display the text (called, for example, label1) something like this would work:

    private async void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Received Aggregated Data from AUV # " + auv[auvSenderID].auvID
        label1.Visible = true;
        player.Play();
        await Task.Delay(3000);             
        label1.Visible = false;
        player.Stop();
        auv[auvSenderID].queue1.Clear();
        auvSend = false;
    }
    

    Lacking context, I don't know what player is, nor whether the Play() and/or Stop() methods complete quickly or not. But assuming those are immediately-returning methods, the above will set the text, show the label, call the Play() method, and then wait three seconds without blocking the UI thread, and then hide the label, call the Stop() method, etc. once the wait has completed.

    If you are doing all this in response to something other than a user clicking a button, you can do the same basic thing, but just in a different method (i.e. not a Click event handler). Just call that method when you want to initiate the text display, etc.