I found that there is difference between Graphics g and e.Graphics from paint event .. e.Graphics is something like "more PRO" which allows more fun with transformations matrices.
Transformations like this https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx
I'm writing app, where will be several objects. In this question there is example
C# rotation (transformation) issue
I found how OnPaint method could be overrided here https://msdn.microsoft.com/en-us/library/b818z6z6(v=vs.71).aspx
The think I don't understand is usecase how I should use it. I need override OnPaint method - ok, but on what object??
Lets imagine simple situation I will have Form in c#
public partial class Form1 : Form {
private Bitmap canvasBitmap; //bitmap for drawing
private Graphics g;
...
public Form1() {
//on Form there is placed PictureBox called canvas
//so canvas is PictureBox 640x480 px
canvasBitmap = new Bitmap(canvas.Width, canvas.Height);
canvas.Image = canvasBitmap;
//prepare graphics
g = Graphics.FromImage(canvasBitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
...
g.Invalidate();
}
}
All drawing will be done on PictureBox which will be my canvas. Is ok to keep there the Graphics g and not the e.Graphics?
Than I will have some objects:
List<Fish> fishes = new List<Fish>();
List<Food> food = new List<Food>();
And I will want to do some fun stuff with them e.g. some transformations like here (scalling, translation, rotation) https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx
Here are the objects. I tryed to write that OnPaint method (not sure if its on correct place.)
class Fish {
Point position;
Fish(int x, int y) {
...
}
protected override void OnPaint(PaintEventArgs e){
...
}
}
class Food {
Point position;
public Food(int x, int y) {
...
}
protected override void OnPaint(PaintEventArgs pe) {
....
}
}
The question is: How should be used in this case OnPaint method? What is the usecase of using this? I guess I will probably override this method on Fish and Food object like I did it. How I draw it? How I redraw it? How I put it on my Graphics g canvas in Form? Where and how should be used Invalidate?
normaly i use
canvas.Invalidate();
see the form example. Can I mix Graphics g and e.Graphics? There could be also with e.Graphics used some doublebuffering or something like that.
Edit
E1) So Form and PicutreBox are control? My Fish and Food class are not controll? Ok?
E2) On Picture box can be somehow up to 3 graphics I can switch and its for smooth drawing. But for simplicity I can stay with one? Ok?
E3) Graphics g is tool e.Graphics is some wrapper of some graphics library which have in it some support for transformatins (work with transformation matrices). OK?
E4) OnPaint(PaintEventArgs e)
will make me able use e.Graphics, but if I have my "loop" in timer (in handle of timer object which I simply put on my form and set the period) and from it I call the method for update and update all objects of fishes and food in some lists(Update = do transformations with them according to my calculation). Is possible somehow use the methods of e.Graphics here?
E5) If E1 is true, the override OnPaint methods in Food and Fish class is nonsense ok?
e.Graphics
is coming from the OnPaint
or Paint
event and therefore only for controls.
The Graphics
object you create from a bitmap is just for that bitmap.
You should use the one you actually want: Draw on the surface or into a bitmap.
Note that the bitmap may or may not be displayed (below the surface) in a controls.
A picturebox for example can even display two bitmaps below its surface, so you may want to use three Graphics
objects for it..
They do the same things to different pixels and no, you can't do more with one..! You can apply matrix and other transformation with either.
The reason behing having the e.Graphics
from the OnPaint
parameters is that the system needs to do some repainting all its controls in a form at some times and therefore must call your drawing code in addition to the internal control drawing routines.
So you need to use this event and/or its e.Graphics
or else your drawing will disappear upon such redrawing. Using e.Graphics
for drawing onto controls will make the drawing persist. (*)
The bitmaps on the other hand will always be shown in their current state. No need to redraw them; just call Refresh()
once after finishing your changes to let the System know about them.
Finally: DoubleBuffering
is a property for controls, not the Graphics
object. Note that is is hidden for most, especailly containers like Panel, so to turn it on you need to subclass them. PictureBox
is meant for drawing and has DoubleBuffered = true
out of the box.
The Graphics
object does not contain any graphics; it is a tool that lets you draw onto a related bitmap, including a control's surface.
(*) Note that not all drawing needs or is supposed to persist: A rubberband line or rectangle should not and here you use the 3rd Graphics
construstor: Graphics g = someControl.CreateGraphics();
.