Search code examples
wpfdrawinghittestinkcanvas

WPF InkCanvas draw even on space beyond bounds of Clip. Override Hit Test


I am using InkCanvas.Clip property to clip my InkCanvas to the shape I need (I am using PathGeometry for that). I can only start drawing in this area, but I want to be able to start drawing outside of it. Of course, stoke parts beyond this area would not be displayed. How can I do that? I thought about overriding HitTestCore of InkCanvas, perhaps by default HitTest fails outside of my allowed drawing area


Solution

  • Maybe OpacityMask can achieve what you want:

    1. Stroke to be clipped outside
    2. To start drawing outside and come inside.

    <Grid Background="LightSalmon">
        <InkCanvas Background="LightBlue">
            <InkCanvas.OpacityMask>
                <DrawingBrush>
                    <DrawingBrush.Drawing>
                        <GeometryDrawing>
                            <GeometryDrawing.Brush>
                                <SolidColorBrush Color="Black"/>
                            </GeometryDrawing.Brush>
                            <GeometryDrawing.Geometry>
                                <PathGeometry>
                                    <PathGeometry.Figures>
                                        <PathFigure StartPoint="0,0">
                                            <PathFigure.Segments>
                                                <PolyLineSegment Points="100,0 100,100 0,100 0,0"/>
                                                <PolyLineSegment Points="100,0 100,100 0,100 0,0"/>
                                                <PolyLineSegment Points="30,30 70,30 70,70 30,70 30,30"/>
                                            </PathFigure.Segments>
                                        </PathFigure>
                                    </PathGeometry.Figures>
                                </PathGeometry>
                            </GeometryDrawing.Geometry>
                        </GeometryDrawing>
                    </DrawingBrush.Drawing>
                </DrawingBrush>
            </InkCanvas.OpacityMask>
        </InkCanvas>
    </Grid>
    

    Appended:

    To avoid the shifting as @SaintMSent mentioned, we should enable the ClipToBounds property of the InkCanvas's AdornerDecorator:

    <InkCanvas x:Name="MyInkCanvas" Background="LightBlue" Loaded="MyInkCanvas_OnLoaded">
        ......
    </InkCanvas>
    

    Code-behind:

    private void MyInkCanvas_OnLoaded(object sender, RoutedEventArgs e)
    {
        var adornerDecorator = VisualTreeHelper.GetChild(MyInkCanvas, 0) as AdornerDecorator;
        if (adornerDecorator != null)
        {
            adornerDecorator.ClipToBounds = true;
        }
    }