Archive

Posts Tagged ‘Boundary Detection’

Drawing Dynamic Shapes in Silverlight 3

January 3, 2010 2 comments

This is a quick demonstration that focuses on some of the geometric shape drawing features that are available in Silverlight and how to use those features in code.

Live Demo: Drawing Dynamic Silverlight Shapes
Live Demo

The following code excerpts show the highlights of performing the primary shape drawing functions:

  • Dynamic shape creation
  • Sizing calculations
  • Brushes
  • Dynamic event handlers
  • Shape re-sizing
  • Shape movement

/// <summary>
/// Draws the desired geometrical shape.  This quick example app uses
/// ellipses and rectangles, but others would work here as well.
/// </summary>
private void DrawShape(Shape shape, SolidColorBrush brush)
{
    double x = 0.0, y = 0.0;

    // These calcs are required to handle sizing in any direction
    if (_ptStart.X > _mX)
    {
        shape.Width = _ptStart.X - _mX;
        x = _mX;
    }
    else
    {
        shape.Width = _mX - _ptStart.X;
        x = _ptStart.X;
    }

    if (_ptStart.Y > _mY)
    {
        shape.Height = _ptStart.Y - _mY;
        y = _mY;
    }
    else
    {
        shape.Height = _mY - _ptStart.Y;
        y = _ptStart.Y;
    }

    // Set the brushes
    shape.Fill = brush;
    shape.StrokeThickness = 1;
    shape.Stroke = _whiteBrush;

    // Set the shape's coordinates
    shape.SetValue(Canvas.LeftProperty, x);
    shape.SetValue(Canvas.TopProperty, y);

    if (_shapeLast != null)
    {
        LayoutRoot.Children.Remove(_shapeLast);
    }

    // Set the name, tooltip and add the event handlers
    shape.Name = "DynamicShape" + _shapeCount.ToString();
    ToolTipService.SetToolTip(shape, shape.Name + "\r\n" + shape.GetType().ToString());

    shape.MouseEnter += new MouseEventHandler(shape_MouseEnter);
    shape.MouseLeave += new MouseEventHandler(shape_MouseLeave);
    shape.MouseLeftButtonDown += new MouseButtonEventHandler(shape_MouseLeftButtonDown);
    shape.MouseLeftButtonUp += new MouseButtonEventHandler(shape_MouseLeftButtonUp);

    // Add the shape to the canvas
    _shapeLast = shape;
    _shapeCount++;
    LayoutRoot.Children.Add(shape);
}

/// <summary>
/// This is where the shapes are drawn, resized and moved.
/// </summary>
private void LayoutRoot_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
    // Update mouse coordinates
    _mX = e.GetPosition(sender as UIElement).X;
    _mY = e.GetPosition(sender as UIElement).Y;
    ctlCoords.Text = "(" + _mX + " ," + _mY + ")";

    // If enabled, add event info to the console
    if (chkTrackMouse.IsChecked == true)
    {
        AddConsoleMsg("LayoutRoot_MouseMove: X=" + _mX + ", Y=" + _mY);
    }

    // Perform a hittest to make sure we're operating within the bounds of our
    // drawing surface
    IEnumerable<UIElement> elements;
    elements = VisualTreeHelper.FindElementsInHostCoordinates(
        new Point(_mX, _mY), ctlBounds as UIElement);

    if (elements.Any())
    {
        // If enabled, draw the gridlines
        if (chkGridlines.IsChecked == true)
        {
            DrawGridlines();
        }

        // If enabled, draw an ellipse
        if (_isLeftMouseButtonDown == true && _isDrawEllipse)
        {
            Ellipse ellipse = new Ellipse();
            DrawShape(ellipse, _brushes[_randBrush.Next(0,_brushes.Count)]);
        }

        // If enabled, draw a rectangle
        if (_isLeftMouseButtonDown == true && _isDrawRect)
        {
            Rectangle rect = new Rectangle();
            DrawShape(rect, _brushes[_randBrush.Next(0, _brushes.Count)]);
        }

        // If enabled, draw a line
        if (_isLeftMouseButtonDown == true && _isDrawLine)
        {
            Line line = new Line();
            DrawLine(line);
        }

        // If a shape is moving
        if (_isShapeMoving)
        {
            double x = _mX - _shapeMove.Width / 2;
            double y = _mY - _shapeMove.Height / 2;

            // Move the shape
            _shapeMove.SetValue(Canvas.LeftProperty, x);
            _shapeMove.SetValue(Canvas.TopProperty, y);
        }
    }
    else
    {
        // We're outside of the bounds of our drawing surface so remove the gridlines
        RemoveGridlines();
    }
}

You can download the full source here: Drawing Dynamic Silverlight Shapes Demo. This requires Visual Studio 2008 and Silverlight 3 development tools (Expression Blend is not required but would be useful as well).

Follow

Get every new post delivered to your Inbox.