Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Drawing onto a Windows Form without freezing it

Drawing onto a Windows Form without freezing it

Scheduled Pinned Locked Moved C#
graphicsquestion
17 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SimpleData
    wrote on last edited by
    #1

    Hi, I would like to draw onto a Windows form constantly, without freezing it. I know it is possible, but how? :) Thanks in advance.

    R S 2 Replies Last reply
    0
    • S SimpleData

      Hi, I would like to draw onto a Windows form constantly, without freezing it. I know it is possible, but how? :) Thanks in advance.

      R Offline
      R Offline
      Rob Philpott
      wrote on last edited by
      #2

      Application.DoEvents() is probably what you're after. What sort of drawing are you doing continuously?

      Regards, Rob Philpott.

      S 1 Reply Last reply
      0
      • S SimpleData

        Hi, I would like to draw onto a Windows form constantly, without freezing it. I know it is possible, but how? :) Thanks in advance.

        S Offline
        S Offline
        Saksida Bojan
        wrote on last edited by
        #3

        Create timer and every tick event is fired call Invalidate() method

        S 1 Reply Last reply
        0
        • R Rob Philpott

          Application.DoEvents() is probably what you're after. What sort of drawing are you doing continuously?

          Regards, Rob Philpott.

          S Offline
          S Offline
          SimpleData
          wrote on last edited by
          #4

          I've thought about Application.DoEvents() but some say that it is not a safe solution. I think I can summarize what I am doing as creating random bitmaps until it is identical to another bitmap. I know the concept is meaningless, but it is just a test which is leading to familiarizing myself with the idea of drawing onto Windows forms. :)

          1 Reply Last reply
          0
          • S Saksida Bojan

            Create timer and every tick event is fired call Invalidate() method

            S Offline
            S Offline
            SimpleData
            wrote on last edited by
            #5

            I've tried it but the form is still freezing and I've no control over it. Here is the code I have in my OnPaint method.

            protected override void OnPaint(PaintEventArgs e)
            {
            if (session == 0)
            {
            Graphics dc = e.Graphics;

                        Pen CyanPen = new Pen(Color.Cyan, 1);
                        Pen MagentaPen = new Pen(Color.Magenta, 1);
                        Pen YellowPen = new Pen(Color.Yellow, 1);
                        Pen BlackPen = new Pen(Color.Black, 1);
            
                        Random rnd = new Random();
                        int buff = 0;
            
                        for (int y = 0; y < 300; y++)
                        {
                            for (int x = 0; x < 300; x++)
                            {
                                buff = rnd.Next(0, 4);
                                if (buff == 0)
                                    dc.DrawRectangle(CyanPen, x, y, 1, 1);
                                if (buff == 1)
                                    dc.DrawRectangle(MagentaPen, x, y, 1, 1);
                                if (buff == 2)
                                    dc.DrawRectangle(YellowPen, x, y, 1, 1);
                                if (buff == 3)
                                    dc.DrawRectangle(BlackPen, x, y, 1, 1);
                            }
                        }
                        session++;
                    }
                }
            
            D S 2 Replies Last reply
            0
            • S SimpleData

              I've tried it but the form is still freezing and I've no control over it. Here is the code I have in my OnPaint method.

              protected override void OnPaint(PaintEventArgs e)
              {
              if (session == 0)
              {
              Graphics dc = e.Graphics;

                          Pen CyanPen = new Pen(Color.Cyan, 1);
                          Pen MagentaPen = new Pen(Color.Magenta, 1);
                          Pen YellowPen = new Pen(Color.Yellow, 1);
                          Pen BlackPen = new Pen(Color.Black, 1);
              
                          Random rnd = new Random();
                          int buff = 0;
              
                          for (int y = 0; y < 300; y++)
                          {
                              for (int x = 0; x < 300; x++)
                              {
                                  buff = rnd.Next(0, 4);
                                  if (buff == 0)
                                      dc.DrawRectangle(CyanPen, x, y, 1, 1);
                                  if (buff == 1)
                                      dc.DrawRectangle(MagentaPen, x, y, 1, 1);
                                  if (buff == 2)
                                      dc.DrawRectangle(YellowPen, x, y, 1, 1);
                                  if (buff == 3)
                                      dc.DrawRectangle(BlackPen, x, y, 1, 1);
                              }
                          }
                          session++;
                      }
                  }
              
              D Offline
              D Offline
              Dan Mos
              wrote on last edited by
              #6

              That's a lot of drawing 300 by 300 => 90000 rectagles in one session :omg: Try putting a a this.Invalidate inside the first for and out of the second/inner for.:~

              S 1 Reply Last reply
              0
              • D Dan Mos

                That's a lot of drawing 300 by 300 => 90000 rectagles in one session :omg: Try putting a a this.Invalidate inside the first for and out of the second/inner for.:~

                S Offline
                S Offline
                SimpleData
                wrote on last edited by
                #7

                I tried your advise and still, I can't do anything on the form until the drawing is over.

                D 1 Reply Last reply
                0
                • S SimpleData

                  I've tried it but the form is still freezing and I've no control over it. Here is the code I have in my OnPaint method.

                  protected override void OnPaint(PaintEventArgs e)
                  {
                  if (session == 0)
                  {
                  Graphics dc = e.Graphics;

                              Pen CyanPen = new Pen(Color.Cyan, 1);
                              Pen MagentaPen = new Pen(Color.Magenta, 1);
                              Pen YellowPen = new Pen(Color.Yellow, 1);
                              Pen BlackPen = new Pen(Color.Black, 1);
                  
                              Random rnd = new Random();
                              int buff = 0;
                  
                              for (int y = 0; y < 300; y++)
                              {
                                  for (int x = 0; x < 300; x++)
                                  {
                                      buff = rnd.Next(0, 4);
                                      if (buff == 0)
                                          dc.DrawRectangle(CyanPen, x, y, 1, 1);
                                      if (buff == 1)
                                          dc.DrawRectangle(MagentaPen, x, y, 1, 1);
                                      if (buff == 2)
                                          dc.DrawRectangle(YellowPen, x, y, 1, 1);
                                      if (buff == 3)
                                          dc.DrawRectangle(BlackPen, x, y, 1, 1);
                                  }
                              }
                              session++;
                          }
                      }
                  
                  S Offline
                  S Offline
                  Saksida Bojan
                  wrote on last edited by
                  #8

                  Of course it keep freezing. In orther to respond, you need to make sure it only redraws once. And use timer.Tick event and forcfully call OnPaint by calling Invalidate(). Do not call OnPaint() directly. Invalidate works like a message pump (Or at least i think so). If it is called 3 times and redraw hasn't occourt, it will only redraw once, and clear quee. other option is to put onto another thread. But i do not recomend. I would recomend a timer. ps: Make sure to call dispose on a PEN, to clear unmanaged resources. I would recomend you use only this code inside OnPaint. And make another Thread like a timer to Invalidate(), or OnPaint (Forcfully) as long as it doesn't call too frequent.

                  if (buff == 0)
                  dc.DrawRectangle(CyanPen, x, y, 1, 1);
                  if (buff == 1)
                  dc.DrawRectangle(MagentaPen, x, y, 1, 1);
                  if (buff == 2)
                  dc.DrawRectangle(YellowPen, x, y, 1, 1);
                  if (buff == 3)
                  dc.DrawRectangle(BlackPen, x, y, 1, 1);

                  S 1 Reply Last reply
                  0
                  • S SimpleData

                    I tried your advise and still, I can't do anything on the form until the drawing is over.

                    D Offline
                    D Offline
                    Dan Mos
                    wrote on last edited by
                    #9

                    I just realized that my first reply or message is a total ... My bad. All of the drawing is inside the OnPaint()!!!! Use the fors outside the OnPaint() or better said call the paint or invalidate method FROM the fors.

                    S 1 Reply Last reply
                    0
                    • D Dan Mos

                      I just realized that my first reply or message is a total ... My bad. All of the drawing is inside the OnPaint()!!!! Use the fors outside the OnPaint() or better said call the paint or invalidate method FROM the fors.

                      S Offline
                      S Offline
                      SimpleData
                      wrote on last edited by
                      #10

                      I see. But there is some thing that I don't understand. If I use OnPaint method, only for the painting process while randomizing in another method; how am I going to transfer my variables like color and position to the OnPaint method? I can use global variables but is it a good solution? There should be an easier and neater solution.

                      D L 2 Replies Last reply
                      0
                      • S SimpleData

                        I see. But there is some thing that I don't understand. If I use OnPaint method, only for the painting process while randomizing in another method; how am I going to transfer my variables like color and position to the OnPaint method? I can use global variables but is it a good solution? There should be an easier and neater solution.

                        D Offline
                        D Offline
                        Dan Mos
                        wrote on last edited by
                        #11

                        Yep. Create a method that draws. Something like:

                        private void Draw(params here){
                        Grphics g = this.CreateGraphics();
                        //draw stuff using the params
                        }

                        And inside a for:

                        for(..){
                           Draw(params here);
                           this.Invalidate();
                        }
                        
                        1 Reply Last reply
                        0
                        • S Saksida Bojan

                          Of course it keep freezing. In orther to respond, you need to make sure it only redraws once. And use timer.Tick event and forcfully call OnPaint by calling Invalidate(). Do not call OnPaint() directly. Invalidate works like a message pump (Or at least i think so). If it is called 3 times and redraw hasn't occourt, it will only redraw once, and clear quee. other option is to put onto another thread. But i do not recomend. I would recomend a timer. ps: Make sure to call dispose on a PEN, to clear unmanaged resources. I would recomend you use only this code inside OnPaint. And make another Thread like a timer to Invalidate(), or OnPaint (Forcfully) as long as it doesn't call too frequent.

                          if (buff == 0)
                          dc.DrawRectangle(CyanPen, x, y, 1, 1);
                          if (buff == 1)
                          dc.DrawRectangle(MagentaPen, x, y, 1, 1);
                          if (buff == 2)
                          dc.DrawRectangle(YellowPen, x, y, 1, 1);
                          if (buff == 3)
                          dc.DrawRectangle(BlackPen, x, y, 1, 1);

                          S Offline
                          S Offline
                          SimpleData
                          wrote on last edited by
                          #12

                          This is my current code and I still have the freezing issue but I think we are getting there. :)

                          private void SetPixel(Point xy, Color clr)
                          {
                          Graphics dc = this.CreateGraphics();
                          Pen _pen = new Pen(clr, 1);

                                  dc.DrawRectangle(\_pen, new Rectangle( xy, new Size(1,1) ) );
                          
                                  \_pen.Dispose(); dc.Dispose();
                              }
                          
                              private void button1\_Click\_1(object sender, EventArgs e)
                              {
                                  Random rnd = new Random();
                                  int buff = 0;
                          
                                  for (int y = 0; y < 300; y++)
                                  {
                                      this.Invalidate();
                                      for (int x = 0; x < 300; x++)
                                      {
                                          this.Invalidate();
                                          buff = rnd.Next(0, 4);
                                          if (buff == 0)
                                              SetPixel(new Point(x,y),Color.Cyan);
                                          else if (buff == 1)
                                              SetPixel(new Point(x,y),Color.Magenta);
                                          else if (buff == 2)
                                              SetPixel(new Point(x,y),Color.Yellow);
                                          else if (buff == 3)
                                              SetPixel(new Point(x,y),Color.Black);
                                      }
                                  }
                              }
                          
                          S L 2 Replies Last reply
                          0
                          • S SimpleData

                            This is my current code and I still have the freezing issue but I think we are getting there. :)

                            private void SetPixel(Point xy, Color clr)
                            {
                            Graphics dc = this.CreateGraphics();
                            Pen _pen = new Pen(clr, 1);

                                    dc.DrawRectangle(\_pen, new Rectangle( xy, new Size(1,1) ) );
                            
                                    \_pen.Dispose(); dc.Dispose();
                                }
                            
                                private void button1\_Click\_1(object sender, EventArgs e)
                                {
                                    Random rnd = new Random();
                                    int buff = 0;
                            
                                    for (int y = 0; y < 300; y++)
                                    {
                                        this.Invalidate();
                                        for (int x = 0; x < 300; x++)
                                        {
                                            this.Invalidate();
                                            buff = rnd.Next(0, 4);
                                            if (buff == 0)
                                                SetPixel(new Point(x,y),Color.Cyan);
                                            else if (buff == 1)
                                                SetPixel(new Point(x,y),Color.Magenta);
                                            else if (buff == 2)
                                                SetPixel(new Point(x,y),Color.Yellow);
                                            else if (buff == 3)
                                                SetPixel(new Point(x,y),Color.Black);
                                        }
                                    }
                                }
                            
                            S Offline
                            S Offline
                            Saksida Bojan
                            wrote on last edited by
                            #13

                            i would suggest what you have in button method you move to other thread. and it is incorect usage. you must let all drawing into OnPaint for perforamce. Invalidate prepares a message into a quee, when message pump has avaible slot, it will call OnPaint. Your Invalidate() is meanigless.

                            S 1 Reply Last reply
                            0
                            • S Saksida Bojan

                              i would suggest what you have in button method you move to other thread. and it is incorect usage. you must let all drawing into OnPaint for perforamce. Invalidate prepares a message into a quee, when message pump has avaible slot, it will call OnPaint. Your Invalidate() is meanigless.

                              S Offline
                              S Offline
                              SimpleData
                              wrote on last edited by
                              #14

                              I now got it working. It is the incorrect usage but whatever, it seems to be working. The only problem I've left is the issue when the windows gets out of sight, the drawings I did are gone. How can I solve this?

                              private void SetPixel(Point xy, Color clr)
                              {
                              Graphics dc = this.CreateGraphics();
                              Pen _pen = new Pen(clr, 1);

                              dc.DrawRectangle(_pen, new Rectangle( xy, new Size(1,1) ) );

                              _pen.Dispose(); dc.Dispose();
                              }

                              private void button1_Click_1(object sender, EventArgs e)
                              {
                              Thread th = new Thread( new ThreadStart(Dummy) );
                              th.Name = "Drawer";
                              th.Start();
                              }

                              private void Dummy()
                              {
                              Random rnd = new Random();
                              int buff = 0;

                              for (int y = 0; y < 300; y++)
                              {
                              for (int x = 0; x < 300; x++)
                              {
                              buff = rnd.Next(0, 4);
                              if (buff == 0)
                              SetPixel(new Point(x,y),Color.Cyan);
                              else if (buff == 1)
                              SetPixel(new Point(x,y),Color.Magenta);
                              else if (buff == 2)
                              SetPixel(new Point(x,y),Color.Yellow);
                              else if (buff == 3)
                              SetPixel(new Point(x,y),Color.Black);
                              }
                              }
                              }

                              S 1 Reply Last reply
                              0
                              • S SimpleData

                                I see. But there is some thing that I don't understand. If I use OnPaint method, only for the painting process while randomizing in another method; how am I going to transfer my variables like color and position to the OnPaint method? I can use global variables but is it a good solution? There should be an easier and neater solution.

                                L Offline
                                L Offline
                                Luc Pattyn
                                wrote on last edited by
                                #15

                                SimpleData wrote:

                                use global variables

                                use class members to do so, and make sure your Paint handler executes fast. I suggest you read this[^] little article of mine. :)

                                Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


                                I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that.
                                All Toronto weekends should be extremely wet until we get it automated in regular forums, not just QA.


                                modified on Friday, February 26, 2010 12:58 PM

                                1 Reply Last reply
                                0
                                • S SimpleData

                                  This is my current code and I still have the freezing issue but I think we are getting there. :)

                                  private void SetPixel(Point xy, Color clr)
                                  {
                                  Graphics dc = this.CreateGraphics();
                                  Pen _pen = new Pen(clr, 1);

                                          dc.DrawRectangle(\_pen, new Rectangle( xy, new Size(1,1) ) );
                                  
                                          \_pen.Dispose(); dc.Dispose();
                                      }
                                  
                                      private void button1\_Click\_1(object sender, EventArgs e)
                                      {
                                          Random rnd = new Random();
                                          int buff = 0;
                                  
                                          for (int y = 0; y < 300; y++)
                                          {
                                              this.Invalidate();
                                              for (int x = 0; x < 300; x++)
                                              {
                                                  this.Invalidate();
                                                  buff = rnd.Next(0, 4);
                                                  if (buff == 0)
                                                      SetPixel(new Point(x,y),Color.Cyan);
                                                  else if (buff == 1)
                                                      SetPixel(new Point(x,y),Color.Magenta);
                                                  else if (buff == 2)
                                                      SetPixel(new Point(x,y),Color.Yellow);
                                                  else if (buff == 3)
                                                      SetPixel(new Point(x,y),Color.Black);
                                              }
                                          }
                                      }
                                  
                                  L Offline
                                  L Offline
                                  Luc Pattyn
                                  wrote on last edited by
                                  #16

                                  CreateGraphics() is an expensive method (expect everything with Create in its name to be expensive and slow); you should really do without it. :)

                                  Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


                                  I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that.
                                  All Toronto weekends should be extremely wet until we get it automated in regular forums, not just QA.


                                  1 Reply Last reply
                                  0
                                  • S SimpleData

                                    I now got it working. It is the incorrect usage but whatever, it seems to be working. The only problem I've left is the issue when the windows gets out of sight, the drawings I did are gone. How can I solve this?

                                    private void SetPixel(Point xy, Color clr)
                                    {
                                    Graphics dc = this.CreateGraphics();
                                    Pen _pen = new Pen(clr, 1);

                                    dc.DrawRectangle(_pen, new Rectangle( xy, new Size(1,1) ) );

                                    _pen.Dispose(); dc.Dispose();
                                    }

                                    private void button1_Click_1(object sender, EventArgs e)
                                    {
                                    Thread th = new Thread( new ThreadStart(Dummy) );
                                    th.Name = "Drawer";
                                    th.Start();
                                    }

                                    private void Dummy()
                                    {
                                    Random rnd = new Random();
                                    int buff = 0;

                                    for (int y = 0; y < 300; y++)
                                    {
                                    for (int x = 0; x < 300; x++)
                                    {
                                    buff = rnd.Next(0, 4);
                                    if (buff == 0)
                                    SetPixel(new Point(x,y),Color.Cyan);
                                    else if (buff == 1)
                                    SetPixel(new Point(x,y),Color.Magenta);
                                    else if (buff == 2)
                                    SetPixel(new Point(x,y),Color.Yellow);
                                    else if (buff == 3)
                                    SetPixel(new Point(x,y),Color.Black);
                                    }
                                    }
                                    }

                                    S Offline
                                    S Offline
                                    Saksida Bojan
                                    wrote on last edited by
                                    #17

                                    I have done it:

                                    private Bitmap bit;
                                    private Graphics dc;
                                    // Used to suspend layout
                                    private delegate void Suspend(bool b);
                                    private Suspend mySuspend;

                                    private void SuspendLayoutDel(bool b)
                                    {
                                    if (b)
                                    this.SuspendLayout();
                                    else
                                    {
                                    this.ResumeLayout();
                                    // Set to true to force full redraw
                                    Invalidate(true);
                                    }
                                    }

                                    private void SetPixel(Point xy, Color clr, Graphics dc)
                                    {
                                    Pen _pen = new Pen(clr, 1);

                                        //Lock prevents accsess from other threads
                                        lock(dc)
                                        {
                                                dc.DrawRectangle(\_pen, new Rectangle(xy, new Size(1, 1)));
                                        }
                                    
                                        \_pen.Dispose();
                                    

                                    }

                                    protected override void OnPaint(PaintEventArgs e)
                                    {
                                    base.OnPaint(e);
                                    if (bit == null)
                                    {
                                    bit = new Bitmap(300, 300);
                                    dc = Graphics.FromImage(bit);
                                    }
                                    e.Graphics.DrawImage(bit,0,0);
                                    }

                                    private void button1_Click(object sender, EventArgs e)
                                    {
                                    // Asign delegate so that Invoke is useed (Threat Safety)
                                    mySuspend = new Suspend(SuspendLayoutDel);
                                    Thread th = new Thread(new ThreadStart(Dummy));
                                    th.Name = "Drawer";
                                    th.Start();
                                    }

                                    private void Dummy()
                                    {
                                    this.Invoke(mySuspend, new Object[]{true});
                                    Random rnd = new Random();
                                    int buff = 0;

                                        for (int y = 0; y < 300; y++)
                                        {
                                                for (int x = 0; x < 300; x++)
                                                {
                                                        buff = rnd.Next(0, 4);
                                                        if (buff == 0)
                                                                SetPixel(new Point(x, y), Color.Cyan,dc);
                                                        else if (buff == 1)
                                                                SetPixel(new Point(x, y), Color.Magenta, dc);
                                                        else if (buff == 2)
                                                                SetPixel(new Point(x, y), Color.Yellow, dc);
                                                        else if (buff == 3)
                                                                SetPixel(new Point(x, y), Color.Black, dc);
                                                }
                                        }
                                        this.Invoke(mySuspend, new Object\[\] { false });
                                    

                                    }

                                    I used graphic to draw to bitmap. Aka to memory. After all is displayed, it draws on screen. This aproach is olmost instantly compared to draw directly to screen.

                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups