4

Can anybody tell me how to get a rectangle back from GetBounds in any units OTHER than pixels? The following code - lifted directly off the MSDN documentation for this function - returns a rectangle that is pretty obviously in pixels rather than points (1/72 of an inch). (Unless icons come in a size of 32/72"x32/72" rather than 32x32 pixels like I think). I am most interested in working with a rectangle in inches, but I would settle for simply seeing the GetBounds pageUnit parameter cause a change in the returned rectangle.

Bitmap bitmap1 = Bitmap.FromHicon(SystemIcons.Hand.Handle);
Graphics formGraphics = this.CreateGraphics();
GraphicsUnit units = GraphicsUnit.Point;

RectangleF bmpRectangleF = bitmap1.GetBounds(ref units);
Rectangle bmpRectangle = Rectangle.Round(bmpRectangleF);
formGraphics.DrawRectangle(Pens.Blue, bmpRectangle);
formGraphics.Dispose();
B H
  • 1,730
  • 18
  • 24
  • 1
    It's a bug in the declaration, the argument is *out*, not *ref*. Best thing to do is just use Width/Height. – Hans Passant Jul 21 '12 at 00:12
  • No, trying to use the 'out' keyword generates an error. I have little difficulty converting units, but this would be easier if it worked. – B H Aug 08 '12 at 15:46

3 Answers3

4

The Information is a little sparse on this, I was able to find this MSDN Forum posting that suggests since the Bitmap is already created the units have already been set and are not changable. Since the GraphicsUnit is being passed by a reference, it you look at it after the call you will find it set back to Pixel from Inch. If you actually want to change the size that the rectangle is drawn at set the Graphics.PageUnit Property on formGraphics to the GraphicsUnit you want to draw the Rectangle at.

From above Link:

In this sample, the parameters of Image.GetBounds method don’t change the result, because the bound of Bitmap has been decided. The parameters only determine the unit length to deal with the range, inch by inch or point by point. But the parameters will not influence the result.

emphasis mine

Mark Hall
  • 53,938
  • 9
  • 94
  • 111
  • It doesn't make any sense that the MSDN doc example would explictly inititialize units to 'point' when they have hard-coded the image used in the example and they know the units of this image. Further, the doc for the GetBounds method says: Gets the bounds of the image in the specified unit. It's almost certainly a(nother) GDI+ bug. No problem to convert units knowing the resolution, but I found bugs with large images, gave up, and started using WPF instead. – B H Aug 08 '12 at 15:44
1

A bit late answering this one, but I thought I would do so because I found it in Google when trying to answer the question "how many mm can I fit in my picture box?", it would have saved me a lot of time not having to work out how to do it!. GetBounds is useless (if you wanted it in pixels...) but it is possible to find the relation between drawing units and display pixels using the Graphics.TransformPoints method:

    private void Form1_Load(object sender, EventArgs e)
    {
        Bitmap b;
        Graphics g;
        Size s = pictureBox1.Size;
        b = new Bitmap(s.Width, s.Height);
        g = Graphics.FromImage(b);
        PointF[] points = new PointF[2];
        g.PageUnit = GraphicsUnit.Millimeter;
        g.PageScale = 1.0f;
        g.ScaleTransform(1.0f, 1.0f);
        points[0] = new PointF(0, 0);
        points[1] = new PointF(1, 1);
        g.TransformPoints(CoordinateSpace.Device, CoordinateSpace.Page, points);
        MessageBox.Show(String.Format("1 page unit in {0} is {1} pixels",g.PageUnit.ToString(),points[1].X));
        points[0] = new PointF(0, 0);
        points[1] = new PointF(1, 1);
        g.TransformPoints(CoordinateSpace.Page, CoordinateSpace.World, points);
        MessageBox.Show(String.Format("1 page unit in {0} is {1} pixels",g.PageUnit.ToString(),points[1].X));
        g.ResetTransform();
        pictureBox1.Image = b;
        SolidBrush brush = new SolidBrush(Color.FromArgb(120, Color.Azure));
        Rectangle rectangle = new Rectangle(10, 10, 50, 50);
        // Fill in the rectangle with a semi-transparent color.
        g.FillRectangle(brush, rectangle);
        pictureBox1.Invalidate();

    }

This will display the basic mm to display pixels (3.779527 in my case) - the world coordinates are 1 mm per pixel, this would change if you applied graphics.ScaleTransform.

Edit: Of course, it helps if you assign the bitmap to the pictureBox image property (and keep the Graphics object to allow changes as required).

Kevin Ford
  • 260
  • 1
  • 7
-1

Add label In class Form1 Add field PointF[] cooridates; Form1.cs [design] look for lighting bolt in properties double click Paint create handler Form1_Paint(object sender,PaintEventArgs) { e.Graphics.PageUnit = GraphicsUnit.Inch; if (cooridates != null) e.Graphics.TransformPoints(CoorinateSpace.World, CoorinateSpace.Device,cooridates); } Create handler again for Form1.MouseMove Form1_MouseMove(object sender,MouseEventArgs e { cooridates[0].X = e.Location.X; cooridates[0].Y = e.Location.Y; this.Refresh(); label1.Text = $"X = {cooridates[0].X} Y = { { cooridates[0].Y } "; }

                                                                            Form1_Load(object sender,MouseEventArgs)
                                                                                {
                                                                                    cooridates = new PointF[1] { new PointF(0f,0f) };
                                                                                         }

                                                                                             Move mouse to get cooridates in Inches
David Morrow
  • 262
  • 4
  • 9