Sign in to follow this  
EvilNando

[.net] GDI+ repaint problem

Recommended Posts

HI guys its me again , im now porting my picturebox based map editor to a GDI+ environment. what Im trying to do right now is to highlight with a white square the cell where the mouse cursor is hovering Ive been reading everywhere that I should do all my painting in the paint event , so what Im doing is setting a boolean to true in the mousemove event then the paint even reads this value and decides to paint a square brush , but sadly at runtime nothing shows up ive tried many things but I think ive run out of options help me out pls!
[SOURCE]
    private void panel1_Paint(object sender, PaintEventArgs e) 
    {
      if (tile_palette != null)
      {
        Pen highlight = new Pen(Color.White, 5.0f);
        Pen grid      = new Pen(Color.Black, 1.0f);
        
        Bitmap curBitmap = new Bitmap(panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);
        
        Graphics back_buffer = Graphics.FromImage(curBitmap);
        Graphics front_buffer = panel1.CreateGraphics();
        
        back_buffer.TranslateTransform(this.panel1.AutoScrollPosition.X, this.panel1.AutoScrollPosition.Y);        

        // BACKBUFFER DRAWING
        // Draw Image
        back_buffer.DrawImageUnscaled(tile_palette.GetImage(), 0, 0);

        // Draw Grid
        for (int id_x = 0; id_x <= this.tile_palette.GetImage().Width; id_x += this.tile_palette.GetGridSize())
        {
          back_buffer.DrawLine(grid, new Point(id_x, 0), new Point(id_x, this.tile_palette.GetImage().Height));
        }

        for (int id_y = 0; id_y <= this.tile_palette.GetImage().Height; id_y += this.tile_palette.GetGridSize())
        {
          back_buffer.DrawLine(grid, new Point(0, id_y), new Point(this.tile_palette.GetImage().Width, id_y));
        }

        if (mouse_data.hover)
        {
          // Highlight selected cell
          if (this.tile_palette.GetSelectedCell(mouse_data.location).Size.Width != 0)
          {
            //e.DrawRectangle(rectangle, this.tile_palette.GetSelectedCell(r.Location));
            back_buffer.DrawRectangle(highlight, tile_palette.GetSelectedCell(mouse_data.location));            
          }

          mouse_data.hover = false;

          this.Invalidate();
        }

        // Present and Dispose
       
        front_buffer.DrawImageUnscaled(curBitmap, 0,0);
        // Dispose objects
        front_buffer.Dispose();
        back_buffer.Dispose();
        grid.Dispose();
        highlight.Dispose();
      }
    }// End Paint event

[/SOURCE]
[/source]

Share this post


Link to post
Share on other sites
OK, your code is looking a little crazy. Let's go over it a bit.

The first thing you need to do is create a custom control that will handle the painting. When doing custom painting on WinForms, it is almost always necessary to create a custom control instead of just using the exposed paint event.


class MapEditorView : Panel
{
}




When doing custom drawing, as you may have noticed, you can get some nasty flicker effects, which is probably why you are trying to use the double-buffered approach. WinForms actually has a way to do this built in, so let's take advantage of that.


// constructor
MapEditorView()
{
DoubleBuffered = true;
ResizeRedraw = true;

SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true );
}




Doing this tells .NET a few things: first, we want the control to be double buffered. Second, we need to redraw any time our size changes. And third, we will be doing all of our painting in the paint handler, and no where else.

Instead of creating GDI drawing objects every time you need to paint, create them once and store them in the class, thereby removing the performance strain.


Pen highlightPen;
Pen gridPen;

// constructor
MapEditorView()
{
DoubleBuffered = true;
ResizeRedraw = true;

SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true );

highlightPen = new Pen(Color.White, 5.0f);
gridPen = new Pen(Color.Black, 1.0f);
}




Before we take a look at the paint event, you should know a few things. You shouldn't call Invalidate within a paint event, as you are just causing the control to paint itself again. Second, you shouldn't use the CreateGraphics function to get a graphics object to draw to. Instead, use the provided object in the event arguments.

Let's take a look (note that I changed the tile_palette to use properties instead of functions, which makes everything look much cleaner).


protected override void OnPaint(PaintEventArgs e)
{
if (tile_palette == null)
return;

// draw the tile palette
e.Graphics.DrawImageUnscaled(tile_palette.Image, 0, 0);

// draw the grid
for (int x = 0; x <= tile_palette.Image.Width; x += tile_palette.GridSize)
e.Graphics.DrawLine(gridPen, new Point(x, 0), new Point(x, tile_palette.Image.Height));

for (int y = 0; y <= tile_palette.Image.Height; y += tile_palette.GridSize)
e.Graphics.DrawLine(gridPen, new Point(0, y), new Point(tile_palette.Image.Width, y));

// check if our client area contains the cursor
Point mousePosition = Control.PointToClient(Control.MousePosition);
if (ClientRectangle.Contains(mousePosition))
{
Rectangle selectedCell = tile_palette.GetSelectedCell(mousePosition);
if (selectedCell.Width != 0)
e.Graphics.DrawRectangle(highlightPen, selectedCell);
}
}




See how much cleaner that is?

Finally, when you are done with your toys, you must put them away. Since we stored the pen objects, we need to get rid of them in the Dispose event.


protected override void Dispose(bool disposing)
{
if (disposing)
{
gridPen.Dispose();
highlightPen.Dispose();
}
}


Share this post


Link to post
Share on other sites
thank a lot I will try this stuff as soon as possible

:D

lol sorry for the messy code i just posted, I kinda rush it when things dont go ok with my program, so what I posted was a rough layout of what I wanted to do


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this