Dokuwiki for science

This article is also published at CodeProject
http://www.codeproject.com/useritems/Extended_PictureBox.asp

ExtendedPictureBox

Introduction

Have you ever been wanted to use a graphical view that has a large and vast screen ? Since the size of the PictureBox control in Windows.Forms namespace is limited to about 32k pixels, you cannot scatter graphical objects on vast space. But Graphics control can draw over the maximum size of the PictureBox control. And, it equips very useful method, 'TranslateTransform'. So, a small modification enables you to use vast 'virtual screen'.

In this article and source code, I demonstrate the ExtendedPictureBox that can handle virtual screen point easily for drawing and exchanging pointers by using a small app like a 'Google map'.

<float left> Download

Latest ver.

</float> <float left> </float> <clear/>

How does it work ?

In the demo application, Form has two group boxes, ExtendedPictureBox and scroll bars. In the virtual space, there are many rectangles (200,000 rects) that created on virtual screen with the size of (50,000 x 50,000). The ExtendedPictureBox control displays only the rectangles that intersects with displaying rectangle. By using scroll bars, you can see any rectangles in the space. Also, you can drag the screen. You may notice that the response during scrolling and dragging is fast.

Can I use on the VisualStudio ?

Yes, you can use this control in your own project and place the control on your Form on Visual Studio 2005.

  1. Download source file and upzip.
  2. Open project of ExtendedPictureBox, not TestForm.
  3. Build to compile the control as a 'Release version'
  4. Close Visual Studio.
  5. Finally, open your own project and add the reference to the ExtendedPictureBox.dll you built.

Extending PictureBox control

ExtendedPictureBox control has only 1 field, 'virtualPoint'. The virtualPoint is where the top-left point of the real screen is.

private Point virtualPoint = new Point(0, 0);
public Point VirtualPoint 
{
    get { return virtualPoint; }
    set { virtualPoint = value; }
}

The virtual point is used for drawing at the OnExpandedPaint event.

protected void OnExpandedPaint(PaintEventArgs e)
{
    /// Set offset.
    e.Graphics.TranslateTransform(-(float)virtualPoint.X, -(float)virtualPoint.Y);
 
    ExpandedOnPaint(
        this, new ExtendedPaintEventArgs(e.Graphics, e.ClipRectangle,
            new Rectangle(virtualPoint.X, virtualPoint.Y,
            this.ClientRectangle.Width, this.ClientRectangle.Height)));
}

You can see this event on the VisualStudio as follows. The event 'MouseMoveInVirtual' is another event that return the virtual point of the mouse cursor. If you want to use points on the real space, you can just use OnPaint or OnMouseMove.

In Demo Application

What the demo application does are

  1. Creation of instances of drawing rectangles at Form_Load.
  2. Painting of the only rectangles that intersects the displaying screen at virtual space.
  3. Handling of the event (Painting, MouseMove, ScrollBar, SearchButton)
  4. Searching pointed rectangles.

DrawObj class (added 2007.Feb.)

DrawObj is a base class for drawing. This class has a Rectangle instance for drawing. RectObj and ImageObj classes extend the DrawObj.

RectObj class

This class is a very simple class for graphical object that contains geometry of its rectangle on the virtual space, Pen, Brush, Font and Name. All parameters are passed at the instantiation. Main method is only 'Draw' method.

In the Rev.2, drawing parameters (isSelected,selectionBrush and selectionPen) were added. If the 'IsSelected' property of RectObj is true, the selectionBrush and the selectionPen are used.

public void Draw(Graphics g)
{
    if (!isSelected)
        g.FillRectangle(drawBrush, objRect);
    else
        g.FillRectangle(selectionBrush, objRect);
 
    if (!isSelected)
        g.DrawRectangle(drawPen, objRect);
    else
        g.DrawRectangle(selectionPen, objRect);
 
    g.DrawString(text, drawFont, Brushes.Black, objRect.Location);
}

In the demo application,200,000 RectObj instances are created randomly and put in the List&lt;RectObj&gt; graphicsObjects collection. (Number of rectangles is defined by MAX_OBJECTS_COUNTS)</p>

private void Form_Load(object sender, EventArgs e)
    {
        Random rnd = new Random();
        for (int i = 0; i &lt; MAX_OBJECTS_COUNTS; i++)
        {
            // Create random rectangles.
            int left = rnd.Next(0, VIRTUAL_WIDTH);
            int top = rnd.Next(0, VIRTUAL_HEIGHT);
            int width = rnd.Next(RECTANGLE_MIN_WIDTH, RECTANGLE_MAX_WIDTH);
            int height = rnd.Next(RECTANGLE_MIN_HEIGHT,RECTANGLE_MAX_HEIGHT);
            Color col = Color.FromArgb((rnd.Next(int.MaxValue) &amp; 0x7fffffff));
 
            /// RectObj with selectionPen and selectionBrush. --- Added 2006.4.16
            RectObj rect = new RectObj(new Rectangle(left, top, width, height), Pens.Black, new SolidBrush(col),
                selectionPen, selectionBrush, i.ToString(), LBL_FONT);
            rect.Tag = i;
            graphicsObjects.Add(rect);
        }

Paint event

In order to draw only the displaying objects, all the RectObj are checked with the virtual points of the rectangle and the 'ClippingInVirtual'. The ClippingInVirtual parameter is translated to the point in the virtual space, you don't have to translate the points.

As the code shows, the drawing performance is not bad and the code is simple, I think.

private void extendedPictureBox_ExpandedOnPaint(object sender, ExtendedPaintEventArgs e)
{
    /// Draw only graphicsObjects that are in the clipping rectangle.
    for (int i = 0; i &lt; graphicsObjects.Count; i++)
    {
        if (graphicsObjects[i] != null &amp;&amp; graphicsObjects[i].ObjRect.IntersectsWith(e.ClippingInVirtual))
            graphicsObjects[i].Draw(e.Graphics);
    }
}

Conclusion

Since the ExtendedPictureBox has simple structure with only one virtual point parameter and two event handlers, it is likely useful for other applications. I wish it helped your work or fun.

<float left>search?q=compass_large&amp;btnI=lucky</float> <float left>

</float> <clear/>