Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do graphic containers work?

I'm trying to figure out how exactly gdi+ graphics containers works with different graphic units. Take a look at the below code. It compiles, you can paste it into a fresh new form.

void Form2_Paint(object sender, PaintEventArgs e)
{
    var gfx = e.Graphics;

    System.Diagnostics.Debug.WriteLine("DpiX={0}, DpiY={1}", gfx.DpiX, gfx.DpiY);

    gfx.PageUnit = GraphicsUnit.Inch;

    var pen = new Pen(Color.Black, 0.01f);

    // Create outer container, 2 inches in size with X and Y set to 0.1 inches
    var outerContainer = gfx.BeginContainer(
        new RectangleF(0.1f, 0.1f, 2, 2),
        new RectangleF(0, 0, 2, 2),
        GraphicsUnit.Pixel);

    // Draw the outer rectangle
    gfx.DrawRectangle(pen, new Rectangle(0, 0, 2, 2));

    // Create inner container, 1 inch in size with X and Y set to 0.1 inches
    var innerContainer = gfx.BeginContainer(
        new RectangleF(0.1f, 0.1f, 1, 1),
        new RectangleF(0, 0, 1, 1),
        GraphicsUnit.Pixel);

    // Draw the inner rectangle
    gfx.DrawRectangle(pen, new Rectangle(0, 0, 1, 1));

    gfx.EndContainer(innerContainer);

    gfx.EndContainer(outerContainer);
}

Above code is a pretty simple example of nested graphic containers, I used no scaling transformation. This is how the form looks like when above paint handler is used:

graphics container illustration

It's pretty simple. Now, I will try to describe what the problem is.

This is a signature of the BeginContainer method:

public GraphicsContainer BeginContainer(
    RectangleF dstrect,
    RectangleF srcrect,
    GraphicsUnit unit
)

What I'm failing to understand is GraphicsUnit unit argument.

From MSDN:

Member of the GraphicsUnit enumeration that specifies the unit of measure for the container.

This appears not to be true!

As you can see in my code I'm using Inch units as such: gfx.PageUnit = GraphicsUnit.Inch.

But, when I'm creating containers this is what I'm passing as units argument to the BeginContainer method: GraphicsUnit.Pixel. What happens after the container is created? Inches are being used (what I actually want). But if I pass GraphicsUnit.Inch (or millimeters or anything else) to the argument, pixels are used. So, it seems that in order to accomplish what I want (use inches) I have to specify pixels?

This makes no sense to me. You can try changing units in BeginContainer methods in above code and observe strange results. I've read the MSDN and everything I could gather on this but I am still clueless.

I'm writing software which draws a lot of stuff using gdi+ and it's using millimeter units for printing purposes - when I started using containers I was quite surprised that I apparently need to specify pixels as units. I'm really suspicious of any printing code where pixels are mentioned. It must be that I have a big misunderstanding of this matter.

So, all above considered, my question is: what is the purpose of the unit argument in this method?

like image 738
bokibeg Avatar asked Mar 20 '15 15:03

bokibeg


1 Answers

Perhaps, you don't need to care about at all.

I failed to pass the right arguments to Graphics.BeginContainer as well. However, using the Transform methods (ResetTransform in the end) worked perfectly for the problem I had to solve.

So, first consider the Transform methods before trying to understand containers.

like image 133
tm1 Avatar answered Sep 30 '22 17:09

tm1