Painting bitmap in Overridden Paint event

kasdoffe

Well-known member
Joined
Aug 27, 2003
Messages
57
I have a custom datagrid class that inherits from the System.Windows.Forms.Datagrid and Ive overridden the OnPaint event. I want to change the normal error icon that shows up in each grid cell that has an error with the new one I created.

The only problem is that after it paints my new image on top of the same location as the default icon, the OnPaint method executes again and again and again, looping forever. How do I get my image to be painted on top of the grid, in the exact cell location without the OnPaint infinitely looping?

Help please? Its got to be simple.

Code:
protected override void OnPaint(PaintEventArgs e)
{
   base.OnPaint(e);
   if (this.DataTable!=null)
   {
      if (this.DataTable.HasErrors==true)
      {
	 for (int i = 0; i<this.DataTable.Rows.Count; i++)
	 {
	    System.Data.DataColumn [] dc = this.DataTable.Rows[i].GetColumnsInError();
	    for (int j=0; j<dc.Length; j++)
	    {	
	        this.CurrentCell = new DataGridCell(i,dc[j].Ordinal);
	        System.Drawing.Rectangle CellRect = this.GetCellBounds(this.CurrentCell);
  		System.Drawing.Image img = new Bitmap(@"C:\caution.gif");
		System.Drawing.Bitmap b = new System.Drawing.Bitmap(img,14,14);
		System.Drawing.Graphics g = this.CreateGraphics();
		g.DrawImage(b,CellRect.Left+1,CellRect.Top+1);
	    }
	}
     }
  }	
}
 
A couple of things:

System.Drawing.Image img = new Bitmap(@"C:\caution.gif");
System.Drawing.Bitmap b = new System.Drawing.Bitmap(img,14,14);
Your loop will run faster if you put this at the start of the onpaint sub.

System.Drawing.Graphics g = this.CreateGraphics();
You can just use e.Graphics() to get the Graphics object instead of painting again.

e.Graphics.DrawImage(b,CellRect.Left+1,CellRect.Top+1);

For the infinite looping thing, perhaps you can check the values of i and j while you are in the loop. :)
 
Heres what I have now with some debug messages to help me on the looping. It appears that the paint event gets called time after time when I do my own painting of my bitmap. If I comment out my DrawImage command, no loop!

Am I in the right place for this?

Code:
protected override void OnPaint(PaintEventArgs e)
{
  Debug.WriteLine("Starting OnPaint...");
  base.OnPaint(e);

  if (this.DataTable!=null)
  {
    if (this.DataTable.HasErrors==true)
    {
      System.Drawing.Image img = new Bitmap(@"C:\FACSGUI .NET\fgClaims\caution.gif");
      System.Drawing.Bitmap b = new System.Drawing.Bitmap(img,14,14);
      for (int i = 0; i<this.DataTable.Rows.Count; i++)
      {
        Debug.WriteLine("Looping Rows - Row " + i.ToString());
	System.Data.DataColumn [] dc = this.DataTable.Rows[i].GetColumnsInError();
	for (int j=0; j<dc.Length; j++)
	{
          Debug.WriteLine("Writing image - Row " + i.ToString() + ", Col " + dc[j].Ordinal.ToString());
          this.CurrentCell = new DataGridCell(i,dc[j].Ordinal);
          System.Drawing.Rectangle CellRect = this.GetCellBounds(this.CurrentCell)			
          e.Graphics.DrawImage( b,CellRect.Left+1,CellRect.Top+1);
	}
      }
      System.Diagnostics.Debug.WriteLine("Finished Looping Rows");
    }
  }
  System.Diagnostics.Debug.WriteLine("...Finished OnPaint");
}

I still have my infinite loop, heres what I get in my output window:

Code:
Starting OnPaint...
Looping Rows - Row 0
Writing image - Row 0, Col 2
Looping Rows - Row 1
Writing image - Row 1, Col 2
Finished Looping Rows
...Finished OnPaint
Starting OnPaint...
Looping Rows - Row 0
Writing image - Row 0, Col 2
Looping Rows - Row 1
Writing image - Row 1, Col 2
Finished Looping Rows
...Finished OnPaint
Starting OnPaint...
Looping Rows - Row 0
Writing image - Row 0, Col 2
Looping Rows - Row 1
Writing image - Row 1, Col 2
Finished Looping Rows
...Finished OnPaint
....and on and on

Any ideas?
 
Woot! I got it.

setting this.CurrentCell was causing the repaint. I moved the new DataGridCell part to the parameters of this.GetCellBounds and the problem was fixed.

I also created a delegate and event that fired after the base.OnPaint so I could listen for the event in only certain cases. My application has many DataGrids and I didnt want them all to perform this code.
 
Back
Top