• 13
• 14
• 27
• 9
• 9

# Problems with GDI+ and C#

This topic is 4430 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, I am working on creating a new map editor for my game, this time written in C#. This is my first win forms app. Anyway, things have been going smooth so far, however I ran into a snag.. I am just testing the basic rendering code, and it seems that it's not "refreshing". When I choose a different tile to draw to the map, I have to actually drag the window and put it "behind" another window that is currently open (like internet explorer or the task bar at the bottom or another form in the app), before the new tile is rendered... this reminds me of when using OpenGL and not calling the SwapBuffers() function... However, I'm not sure what the problem is... I am even calling graphics.Clear(Color.White) before rendering everything..... Thanks for any help.. EDIT: here is the OnPaint for the window which displays the map. Currently I am just trying to draw the "currently selected tile" onto the top left corner.
		protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.Clear(System.Drawing.Color.White);

if(Globals.selected_tileset != null)
{
g.DrawImage(Globals.selected_tileset,new Rectangle(0,0,32,32),Globals.selected_tile,GraphicsUnit.Pixel);
}
}


##### Share on other sites
Hiya,

When you chose a different tile, did you try calling Refresh() on the window or the control containing and displaying the tile?

##### Share on other sites
Hmmm... I added "this.Refresh()" to the top of the OnPaint that I pasted above... it seems to be working now, but now I am getting flickering.... me thinks I need to google for double buffering... one question though - is it a bad idea to refresh from the OnPaint()? I mean do I really have to Refresh() only each time something changes?

Another question - since I haven't been calling Refresh(), what exactly is happening behind the scenes? I mean, I know that OnPaint() is definietly being called each frame, so those DrawImage() and Clear() ARE being executed - what is happening here? Is it really being executed and just totally wasted because I'm not calling Refresh()? Is it being drawn to a backbuffer, and calling Refresh() is like flipping the buffer or something? But that doesn't explain why dragging the window would make it (kind of) Refresh...

thanks again.

##### Share on other sites
Oh no :) Don't put refresh in OnPaint(), put it where you know there's a change in your app that needs to be Refresh(). If you put it in your OnPaint() then the fact that you are painting will cause a refresh which will cause OnPaint which cause a Refresh etc...

Look at OnPaint like the WM_Paint message in win32 programming and not necessarily per frame :). For enable double buffering, look at Setstyle(Controlstyles.DoubleBuffering,true). You can also reduce flicker by looking at AllPaintingInWmPaint. I'm sorry I can't show you an example, I haven't touched C# in a few months and I'm a bit rusty right now.

Edit...forgot you also need to put Controlstyle.UserPaint to true when using Controlstyle.AllPaintingInWmPaint

##### Share on other sites
Quote:
 what is happening here?

It's my understanding that windows maintains 'dirty rectangle' lists for the regions that need redrawn. If the area isn't changed, no need to redraw it, right? Refresh() just specifies to redraw everything.

##### Share on other sites
Thanks again... it seems to be working now...

I have a few more questions I had come across while working on this and it's not worth making a new post, so.....

Is it possible to draw the currently selected tile where the mouse currently is? I have tried doing this but it seems like nothing is rendered to the screen... I put this line into the OnPaint() of the root Form (which is an MDI container).

g.DrawImage(Globals.selected_tileset,new Rectangle(Globals.mouse_x,Globals.mouse_y,32,32),Globals.selected_tile,GraphicsUnit.Pixel);

Where Globals.mouse_x/y were the mouse x/y position that I tracked using OnMouseMove (is it possible to just grab the mouse position directly?). However, nothing is drawn from this..

This didn't work for several reasons 1) I noticed the main MDI container was not spitting out OnMouseMove events and 2) I also think I'm not able to render on this.. So how can I accomplish what I want? I know I can just make a new form which displays the "currently selected tile", but it would be cool to have it rendered at my mouse w/ some transparency..

Another question - I have a form which basically just renders a tileset to the screen and allows you to click on a given tile to select it.... but for some reason it's width is locked to around 100 pixels... I can't drag it to make it smaller and doing this.ClientSize = new Size() seems to be restricted too.. I found the MinimumSize/MaximumSize properties that I thought would tweak this but they were already set to 0/0...

Another one - is there some way to have an event fire when a child window is closed? Also, when I null out a reference to a child Form, or store it in an ArrayList and do Clear(), or whatever... why is the window still visible? Does it disapear when the gc cleans it up or something? I know I can do Close() first before losing the reference but I don't understand whats going on behind the scenes...

Thanks again for any help.