Click here to Skip to main content
15,881,089 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am trying to use DrawString in my C# Windows Form application. On program startup, three paint events are fired. On the first event, the string is written on the form in the correct position. On the 2nd and 3rd paint events, the string is written above and to the left of the correct position.

After that, the program runs as expected. (Min and then max, or resize the form and the screen is drawn correctly.)

This happens with DrawLine, DrawRectangle, etc.

Is this a bug with C# or am I missing something VERY obvious? Here's the WHOLE application. Thanks for any help you can give.
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Junk
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            System.Drawing.Graphics graphicsObj;
            graphicsObj = this.CreateGraphics();
            Font myFont = new System.Drawing.Font("Helvetica", 40,                  FontStyle.Italic);
            Brush myBrush = new SolidBrush(System.Drawing.Color.Red);
            graphicsObj.DrawString("Hello C#", myFont, myBrush, 30, 100);
        }
    }
}
Posted
Updated 6-Jan-12 19:49pm
v2

1 solution

This is not a whole application. How do you know that Form1_Paint is a handler added to an invocation list of the event Paint. Relying on the Designer? There are many cases when the Designer only makes development slower.

As you already have your Form class, why handling the event at all? Just overriding OnPaint does exact same thing. Now, where is the mistake? This is creation of the instance of System.Drawing.Graphics using its constructor. You should use the instance which is already passed to you in the handler method of Paint or OnPaint; it is passed in event arguments parameter.

More mistakes: Font and Brush are not disposed, so you will have a permanent unmanaged resource leak. This is important enough, so it should also handle possible exceptions. Normally, it is done using try-finally, but the equivalent behavior is achieved using using statement (not to by confused with using clause, see http://msdn.microsoft.com/en-us/library/yh598w02.aspx[^]).

Also, there is not need to create a solid brush of an well-known color.

After all fixes:
C#
protected override void OnPaint(PaintEventArgs eventArgs) {
    using (Font myFont = new System.Drawing.Font("Helvetica", 40, FontStyle.Italic)) {
        e.Graphics.DrawString("Hello C#", myFont, System.Drawing.Brushes.Red, 30, 100);
    } //myFont is automatically disposed here, even if an exception was thrown
}


If you need graphics to move, and change data used by OnPaint, you need to call Control.Invalidate. You can try to improve performance using Control.Invalidate with parameters (Region or Rectange) to refresh only the part of the scene.

See also my past answers:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
Drawing Lines between mdi child forms[^],
capture the drawing on a panel[^],
How do I clear a panel from old drawing[^] (this one helps to prevent the very common abuse of PictureBox).

—SA
 
Share this answer
 
v2
Comments
Jill Slocum 6-Jan-12 23:27pm    
Thanks for the response - I tried the suggested code and got the same behavior. The first DrawString works correctly. Three or four seconds later, the other paint events occur and the string appears above and to the left of the original string.
Here's the code -

namespace Junk
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs eventArgs)
{
using (Font myFont = new System.Drawing.Font("Helvetica", 40, FontStyle.Italic))
{
eventArgs.Graphics.DrawString("Hello C#", myFont, System.Drawing.Brushes.Red, 30, 100);
} //myFont is automatically disposed here, even if an exception was thrown
}
}
}
Sergey Alexandrovich Kryukov 7-Jan-12 22:12pm    
What are "other paint events", for goodness sake? It means you are doing something else and don't share with use -- what exactly. There can be many ways to spoil correct behavior. Instead of down-voting a correct answer, try to sort it out; and also try to thing about correctness of your questions.
--SA
Jill Slocum 8-Jan-12 0:56am    
I replaced the Form1_Paint function in my original code with the "protected override void OnPaint" which you provided. Nothing else is happening in this application. If you were to create a windows forms application and add the OnPaint function, you should see the problem. By "other paint events", I mean that when the program starts, three paint events are thrown. I don't know where they are coming from. It looks like the client area is being redrawn using screen coordinates instead of client coordinates. I downgraded your response because the problem wasn't solved. I do not mean to be offensive, but it would help if you would try this example of the problem and let me know if it occurs on your computer. Thank you.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900