DrawString Graphics problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Brian Ward

    DrawString Graphics problem

    I am trying to get to grips with some basic graphics, being new to C#.
    I have this code (see below) in a simple project .. when I run it 6 text
    strings are drawn, as I expected .. but this happens twice .. once with
    a grey background and once with the white one.
    Clearly I am missing something fundamental here.
    Can anyone please explain.
    TIA
    ===
    Brian
    =====
    private void Form1_Paint(obj ect sender, PaintEventArgs e)
    {
    this.BackColor = Color.White;
    Graphics g = e.Graphics; // get a graphics object
    Font ft = new Font("Arial", 30); // create a font ft
    Brush br = new SolidBrush(Colo r.Tomato); // create a brush br
    int y = 20;
    for (int i = 0; i < 6; i++)
    {
    g.DrawString("B rian is texting a Window", ft, br, 30, y);
    y += 50;
    System.Threadin g.Thread.Sleep( 1000); // pause for 1 sec
    }
    }
  • Peter Duniho

    #2
    Re: DrawString Graphics problem

    On Thu, 10 Jan 2008 08:40:42 -0800, Brian Ward <brian.ward@zet net.co.uk>
    wrote:
    I am trying to get to grips with some basic graphics, being new to C#.
    I have this code (see below) in a simple project .. when I run it 6 text
    strings are drawn, as I expected .. but this happens twice .. once with
    a grey background and once with the white one.
    Clearly I am missing something fundamental here.
    Your event handler is wrong.

    First, you created a Font and a Brush, both of which need to be disposed
    of when you're done with them.

    Second, you _never_ ever want to do anything in a paint handler except
    anything _directly_ related to drawing to the control. Calling
    Thread.Sleep() is a _huge_ no-no. So is changing the background color for
    the control.

    I believe that what's going on in your case is that the change to the
    background color won't take effect until you return from the paint
    handler, because nothing else can happen to the control until the paint
    handler is done. So you're stuck in the paint handler, drawing the string
    six times using the old background color. Then you finally exit, which
    allows the background color change to take effect, at which point another
    redraw is signaled, causing you to draw the string six more times.

    The basic .NET Forms painting outline is as follows:

    * Write a paint handler (or override OnPaint()) that, given some state
    for your control and/or data can always draw the complete state

    * Write some code elsewhere that manages the state. For animation,
    this usually involves some sort of timing mechanism that updates the state
    at suitable intervals.

    * Any time the state changes, call Control.Invalid ate() to signal to
    the framework that the display of that state needs to be updated. This
    will result in your paint handler being called, at which time it will
    completely draw the current state.

    It is completely inappropriate to manage the state and/or timing of
    animation from within the paint handler. Do not ever do this.

    Pete

    Comment

    • Chris Dunaway

      #3
      Re: DrawString Graphics problem

      On Jan 10, 10:40 am, Brian Ward <brian.w...@zet net.co.ukwrote:
      I am trying to get to grips with some basic graphics, being new to C#.
      I have this code (see below) in a simple project .. when I run it 6 text
      strings are drawn, as I expected .. but this happens twice .. once with
      a grey background and once with the white one.
      Clearly I am missing something fundamental here.
      Can anyone please explain.
      TIA
      ===
      Brian
      =====
      private void Form1_Paint(obj ect sender, PaintEventArgs e)
      {
      this.BackColor = Color.White;
      Graphics g = e.Graphics; // get a graphics object
      Font ft = new Font("Arial", 30); // create a font ft
      Brush br = new SolidBrush(Colo r.Tomato); // create a brush br
      int y = 20;
      for (int i = 0; i < 6; i++)
      {
      g.DrawString("B rian is texting a Window", ft, br, 30, y);
      y += 50;
      System.Threadin g.Thread.Sleep( 1000); // pause for 1 sec
      }
      >
      }
      To add to what Peter has said, here is a site that might help you:



      Chris

      Comment

      • Bob Powell [MVP]

        #4
        Re: DrawString Graphics problem

        Funny, I was just about to suggest that myself ;-)


        --
        --
        Bob Powell [MVP]
        Visual C#, System.Drawing

        Ramuseco Limited .NET consulting


        Find great Windows Forms articles in Windows Forms Tips and Tricks


        Answer those GDI+ questions with the GDI+ FAQ


        All new articles provide code in C# and VB.NET.
        Subscribe to the RSS feeds provided and never miss a new article.


        "Chris Dunaway" <dunawayc@gmail .comwrote in message
        news:53a6d933-a049-425d-80c8-d14696adc19a@v6 7g2000hse.googl egroups.com...
        On Jan 10, 10:40 am, Brian Ward <brian.w...@zet net.co.ukwrote:
        >I am trying to get to grips with some basic graphics, being new to C#.
        >I have this code (see below) in a simple project .. when I run it 6 text
        >strings are drawn, as I expected .. but this happens twice .. once with
        >a grey background and once with the white one.
        >Clearly I am missing something fundamental here.
        >Can anyone please explain.
        >TIA
        >===
        >Brian
        >=====
        >private void Form1_Paint(obj ect sender, PaintEventArgs e)
        >{
        > this.BackColor = Color.White;
        > Graphics g = e.Graphics; // get a graphics object
        > Font ft = new Font("Arial", 30); // create a font ft
        > Brush br = new SolidBrush(Colo r.Tomato); // create a brush
        >br
        > int y = 20;
        > for (int i = 0; i < 6; i++)
        > {
        > g.DrawString("B rian is texting a Window", ft, br, 30, y);
        > y += 50;
        > System.Threadin g.Thread.Sleep( 1000); // pause for 1 sec
        > }
        >>
        >}
        >
        To add to what Peter has said, here is a site that might help you:
        >

        >
        Chris

        Comment

        • Chris Dunaway

          #5
          Re: DrawString Graphics problem

          On Jan 11, 4:56 am, "Bob Powell [MVP]" <b...@spamkille rbobpowell.net>
          wrote:
          Funny, I was just about to suggest that myself ;-)
          >
          --
          --
          Bob Powell [MVP]
          Visual C#, System.Drawing
          >
          Ramuseco Limited .NET consultinghttp://www.ramuseco.co m
          >
          Find great Windows Forms articles in Windows Forms Tips and Trickshttp://www.bobpowell.n et/tipstricks.htm
          >
          Answer those GDI+ questions with the GDI+ FAQhttp://www.bobpowell.n et/faqmain.htm
          >
          All new articles provide code in C# and VB.NET.
          Subscribe to the RSS feeds provided and never miss a new article.
          >
          "Chris Dunaway" <dunaw...@gmail .comwrote in message
          >
          news:53a6d933-a049-425d-80c8-d14696adc19a@v6 7g2000hse.googl egroups.com...
          >
          On Jan 10, 10:40 am, Brian Ward <brian.w...@zet net.co.ukwrote:
          I am trying to get to grips with some basic graphics, being new to C#.
          I have this code (see below) in a simple project .. when I run it 6 text
          strings are drawn, as I expected .. but this happens twice .. once with
          a grey background and once with the white one.
          Clearly I am missing something fundamental here.
          Can anyone please explain.
          TIA
          ===
          Brian
          =====
          private void Form1_Paint(obj ect sender, PaintEventArgs e)
          {
          this.BackColor = Color.White;
          Graphics g = e.Graphics; // get a graphics object
          Font ft = new Font("Arial", 30); // create a font ft
          Brush br = new SolidBrush(Colo r.Tomato); // create a brush
          br
          int y = 20;
          for (int i = 0; i < 6; i++)
          {
          g.DrawString("B rian is texting a Window", ft, br, 30, y);
          y += 50;
          System.Threadin g.Thread.Sleep( 1000); // pause for 1 sec
          }
          >
          }
          >
          To add to what Peter has said, here is a site that might help you:
          >>
          Chris
          Hi Bob,

          I love your site! When will your book be out? ;)

          I noticed on your site that you have started a WPF faq. Have had a
          chance to use WPF much? What are your impressions of it compared to
          GDI and GDI+ ?

          Cheers,

          Chris

          Comment

          • Brian Ward

            #6
            Re: DrawString Graphics problem

            Thanks for all this help .. Bob's site looks really good.
            One more thing. I have another problem (always another!)
            I am using protected override bool ProcessCmdKey to control the movement
            of this circle (see below) by adjusting x and y values .. it works fine,
            but I also want the circle to leave a trace behind it as it moves .. I
            would think that writing to a Bitmap would be the thing, but I can't
            seem to figure out how.
            Any help again much appreciated
            ==
            Brian
            ==

            private void Form1_Paint(obj ect sender, PaintEventArgs e)
            {
            Graphics g = e.Graphics;
            g.FillEllipse(B rushes.Blue, x, y, 20, 20);
            g.Dispose()
            }

            Comment

            • Peter Duniho

              #7
              Re: DrawString Graphics problem

              On Sat, 12 Jan 2008 01:27:09 -0800, Brian Ward <brian.ward@zet net.co.uk>
              wrote:
              [...]
              but I also want the circle to leave a trace behind it as it moves .. I
              would think that writing to a Bitmap would be the thing, but I can't
              seem to figure out how.
              Any help again much appreciated
              Well, the basic idea would be to create a Bitmap instance into which you
              draw, using Graphics.FromIm age() to get a Graphics instance you can use
              for drawing the circle, then in your Paint handler draw the Bitmap instead
              of the circle.

              Assuming the size of your control never changes, this may be the easiest.
              If you want to handle changes in the control size gracefully it gets more
              complicated, at least partly just because you then need to decide what
              behavior is "correct" for your application.

              You could save the circles into a Metafile instead, which introduces its
              own complexities but can avoid the resizing issue. Alternatively, you
              could just keep your own list of circles as you add them, drawing all of
              them one by one each time the control needs to be painted. And of course
              you could use some combination of the above, such as using a Bitmap most
              of the time, but still storing a list of the circles so that you can
              recreate a new Bitmap at arbitrary sizes as the control changes without
              worrying about how best to preserve previously drawn circles.

              Basically, for small numbers of circles, just storing the circles
              themselves is easiest and more efficient. As the number of circles goes
              up, a solution that uses only a Bitmap becomes more efficient. There's a
              large area of wiggle room in the middle where you can pretty much do it
              however you prefer. :)

              Pete

              Comment

              • Peter Duniho

                #8
                Re: DrawString Graphics problem

                I was looking at this thread in review for a reply elsewhere, and I took
                another look at this post. I'm embarassed that I didn't notice the
                obvious bug, especially since it might have been introduced as a result of
                a misunderstandin g of a comment I made earlier. In particular:

                On Sat, 12 Jan 2008 01:27:09 -0800, Brian Ward <brian.ward@zet net.co.uk>
                wrote:
                [...]
                private void Form1_Paint(obj ect sender, PaintEventArgs e)
                {
                Graphics g = e.Graphics;
                g.FillEllipse(B rushes.Blue, x, y, 20, 20);
                g.Dispose()
                }
                Do _not_ dispose the Graphics instance. It is good and correct to dispose
                objects that are disposable and which you created in your own code. But
                the Graphics instance is passed to you in the event args and must remain
                valid for other Paint event handlers. Don't call Dipose() on it.

                Sorry for not noticing this earlier.

                Pete

                Comment

                Working...