Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

int tick=1;
string Im= "D:\\Pictures\\marker.jpg";
	private void PreachForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
	{
		e.Graphics.DrawImage(Image.FromFile(Im), 10, 10, 600, 300);
	}

	private void Timer_Tick(object sender, System.EventArgs e)
	{
		if(tick==1) Im= "D:\\Pictures\\marker.jpg";
		else Im= "D:\\Pictures\\nobabysit.jpg";
		
		PreachForm_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle));
		tick= (tick+1)%2;
	}

How do I clear the last picture that I showed from memory? I am not using a picture box. I tried using e.Dispose() and e.Graphics.Dispose() but that creates an exception. There must be some other way to quickly clear the form from the last image displayed.

C#
  • *Gurus*
Posted

I would only load each image once, then keep the instances around and draw with them when required. Any bitmap instance you create you should also Dispose when you're done with it.

 

Also, instead of calling your Paint procedure directly as you are doing I would call Invalidate() instead, to make Windows call it. Just good practice.

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

Posted

I did exactly what you said and also did some testing. I found that when I use Invalidate() it is not as fast between frames, there is more of a flicker.

Is there a way around that?

 

Also, I found that there is no flicker (that I can see) when I call Paint directly but it uses memory up. I think it is the new PaintEventArgs that I create each time. Can I call paint directly so that it does not use up memory like that? Just in case there is no way to stop the flicker using Invalidate().

 

Please answer each question either way this turns out.

C#
  • *Experts*
Posted

I wouldn't call the Paint method yourself either, bad practice. There's almost surely a better way. If nothing else, move out your code from the Paint event into a function and call that function from both the Paint event and your timer.

 

Having said that, do not pass a reference to "this.CreateGraphics()" ANYWHERE. Any graphics object you create MUST be disposed of or it will NOT go away. Do this instead:

Graphics g = this.CreateGraphics();
// Use g - in a call to PreachForm_Paint or whatever
g.Dispose();

 

-Nerseus

"I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
Posted
I found the reason that invalidate is slower is because it repaints the whole form but calling paint directly leaves the images there. If there are alot of controls and other graphical objects on the form then using invalidate will make my animation very slow, right?
C#
  • *Experts*
Posted

Ideally, you only want to paint what's changed. If you're doing something with "sprites" in windowed mode (everything except DirectDraw will be in a window) and you want the best speed, you may need or want to keep track of the position of each drawn sprite so that you can only redraw a small portion of the screen each time.

 

There are lots of techniques, but the simplist (somewhat) is to redraw the background of where your sprite used to be, then draw it in the new location. To make it more efficient, you can event use IntersectRect to see if the old and new positions overlap (they often do) and then you might be able to save more time by not erasing the previous image if the new image is going to overwrite it anyway. This may be overkill for what you want/need.

 

The best bet is to find the slowest machine that you'll want someone to play your game on and make sure it works well enough on that machine.

 

Having said that, I wouldn't worry about optimizing anything right now other than obvious flaws that are noticable now - which might indicate bad design or more general optimizations that are specific to game programming (such as the aforementioned "erase last position" logic).

 

-Nerseus

"I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
Posted
So, using a rectangle to paint only a portion of the form could, if I wanted, only update half of the form? For example, a button. I could repaint it but only update half of it?
C#
  • *Experts*
Posted

You can do whatever you want, based on your needs.

 

By calling Invalidate, you're forcing a refresh of the whole form - hence a flicker occurs. When you call paint yourself, you're not really painting the form, just adding a little extra painting (looks like you're drawing an image). Honestly, if that's all you plan on doing, why not use an Image control or a Picturebox? If you're painting a picture on a button, there are better ways - but I'd ask that question instead of painting.

 

My answers thus far have related more to moving pictures, such as an image that represents a "sprite" - a non-rectangular 2D region that may or may not be animated - used in games.

 

Maybe you could tell us more about what you want, then we can offer clearer suggestions maybe even real code snippets.

 

-Ners

"I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
Posted
I asked the question about refreshing part of a button, not because I want to do that but because I am curious if that would work. It would give me a better understanding of how painting works.
C#

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...