#1,151 – Custom Arc Shape, part III

In the previous example of a custom arc shape, we use the standard Stroke and StrokeThickness properties when rendering the shape.  Note, however, that when we increase the thickness of the stroke, part of the stroke lies outside of the boundaries of the shape.

1151-001

We can fix this problem by accounting for the stroke thickness in the drawing logic.  The updated code is shown below.

        protected override Geometry DefiningGeometry
        {
            get
            {
                double maxWidth = Math.Max(0.0, RenderSize.Width - StrokeThickness);
                double maxHeight = Math.Max(0.0, RenderSize.Height - StrokeThickness);
                //Console.WriteLine(string.Format("* maxWidth={0}, maxHeight={1}", maxWidth, maxHeight));

                double xStart = maxWidth / 2.0 * Math.Cos(StartAngle * Math.PI / 180.0);
                double yStart = maxHeight / 2.0 * Math.Sin(StartAngle * Math.PI / 180.0);

                double xEnd = maxWidth / 2.0 * Math.Cos(EndAngle * Math.PI / 180.0);
                double yEnd = maxHeight / 2.0 * Math.Sin(EndAngle * Math.PI / 180.0);

                StreamGeometry geom = new StreamGeometry();
                using (StreamGeometryContext ctx = geom.Open())
                {
                    ctx.BeginFigure(
                        new Point((RenderSize.Width / 2.0) + xStart,
                                  (RenderSize.Height / 2.0) - yStart),
                        false,
                        false);
                    ctx.ArcTo(
                        new Point((RenderSize.Width / 2.0) + xEnd,
                                  (RenderSize.Height / 2.0) - yEnd),
                        new Size(maxWidth / 2.0, maxHeight / 2),
                        0.0,     // rotationAngle
                        (EndAngle - StartAngle) > 180,   // greater than 180 deg?
                        SweepDirection.Counterclockwise,
                        true,    // isStroked
                        true);
                }

                return geom;
            }
        }

1151-002

 

#484 – InkCanvas Contains a Collection of Strokes

When you draw on an InkCanvas control, you create a series of Stroke objects.  One Stroke is created each time you hold the left mouse button down, drag the mouse to draw and then release the mouse button.  All strokes are stored in the Strokes property of the InkCanvas.

Each Stroke stores information about its drawing attributes (e.g. color, width) as well as the collection of points that make up the Stroke, stored in its StylusPoints collection.

In the example below, we use data binding to show all Strokes for an InkCanvas in an adjacent ListBox.

</pre>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="150"/>
        </Grid.ColumnDefinitions>

        <Border Grid.Row="1" BorderBrush="DodgerBlue" BorderThickness="2" Margin="5" SnapsToDevicePixels="True">
            <InkCanvas Name="ink" MinHeight="0" MinWidth="0"/>
        </Border>
        <Label Grid.Column="1" Content="Strokes:" Margin="10,5"/>
        <ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding ElementName=ink, Path=Strokes}">
             <ListBox.ItemTemplate>
                 <DataTemplate>
                     <Label Content="{Binding Path=StylusPoints, Converter={StaticResource strokeInfoConverter}}"/>
                 </DataTemplate>
             </ListBox.ItemTemplate>
        </ListBox>
    </Grid>