2

Inheriting Shape, we have created a number of custom shapes. RectangleAnnotation.cs is one of them:

using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace ShareX.ScreenCaptureLib
{
    public class RectangleAnnotation : Annotation
    {
        public int ShadowSize { get; set; } = 15;

        protected override Geometry DefiningGeometry
        {
            get
            {
                return new RectangleGeometry(new Rect(0, 0, Width, Height));
            }
        }

        public RectangleAnnotation()
        {
            brush = Brushes.Red;

            Fill = Brushes.Transparent;
            Stroke = brush;
            StrokeThickness = 1;

            Effect = new DropShadowEffect
            {
                RenderingBias = RenderingBias.Quality,
                Opacity = 1,
                Color = Colors.Black,
                ShadowDepth = 0,
                BlurRadius = ShadowSize
            };
        }
    }
}

The abstract class, Annotation.cs is as follows:

using HelpersLib;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace ShareX.ScreenCaptureLib
{
    public abstract class Annotation : Shape, IAnnotation
    {
        protected Brush brush;
        protected Adorner adorner;

        public bool IsCreating { get; set; }

        private bool selected;

        public bool Selected
        {
            get
            {
                return selected;
            }
            set
            {
                if (Selectable)
                {
                    selected = value;

                    if (selected)
                    {
                        ShowNodes();
                    }
                    else
                    {
                        HideNodes();
                    }
                }
            }
        }

        private bool selectable = true;

        public bool Selectable
        {
            get
            {
                return selectable;
            }
            set
            {
                selectable = value;

                if (!selectable)
                {
                    Selected = false;
                }
            }
        }

        public Point PointStart
        {
            get { return new Point(X1, Y1); }
            set { X1 = value.X; Y1 = value.Y; }
        }

        public Point PointFinish
        {
            get { return new Point(X2, Y2); }
            set { X2 = value.X; Y2 = value.Y; }
        }

        public Rect Bounds
        {
            get
            {
                return CaptureHelper.CreateRectangle(PointStart, PointFinish);
            }
        }

        protected void CreateNodes()
        {
            adorner = new CircleAdorner(this);
            AdornerLayer.GetAdornerLayer(this).Add(adorner);
        }

        protected void ShowNodes()
        {
            if (adorner == null)
            {
                CreateNodes();
            }

            adorner.Visibility = Visibility.Visible;
        }

        protected void HideNodes()
        {
            if (adorner != null)
            {
                adorner.Visibility = Visibility.Hidden;
            }
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.ChangedButton == MouseButton.Left)
            {
                Selected = !Selected;
            }
        }

        public void UpdateDimensions()
        {
            Rect area = Bounds;
            Canvas.SetLeft(this, area.X);
            Canvas.SetTop(this, area.Y);
            Width = area.Width;
            Height = area.Height;
        }

        internal static bool IsDoubleFinite(object o)
        {
            double d = (double)o;
            return (!double.IsInfinity(d) && !double.IsNaN(d));
        }

        public virtual RenderTargetBitmap GetBitmap()
        {
            var rtb = new RenderTargetBitmap((int)Width, (int)Height, AnnotationHelper.CapturedImage.Source.DpiX, AnnotationHelper.CapturedImage.Source.DpiY, PixelFormats.Pbgra32);
            rtb.Render(this);
            return rtb;
        }

        public virtual void Render()
        {
        }

        public static readonly DependencyProperty X1Property = DependencyProperty.Register("X1", typeof(double), typeof(Annotation),
            new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender),
            new ValidateValueCallback(IsDoubleFinite));

        public static readonly DependencyProperty Y1Property = DependencyProperty.Register("Y1", typeof(double), typeof(Annotation),
            new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender),
            new ValidateValueCallback(IsDoubleFinite));

        public static readonly DependencyProperty X2Property = DependencyProperty.Register("X2", typeof(double), typeof(Annotation),
            new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender),
            new ValidateValueCallback(IsDoubleFinite));

        public static readonly DependencyProperty Y2Property = DependencyProperty.Register("Y2", typeof(double), typeof(Annotation),
            new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender),
            new ValidateValueCallback(IsDoubleFinite));

        [TypeConverter(typeof(LengthConverter))]
        public double X1
        {
            get { return (double)GetValue(X1Property); }
            set { SetValue(X1Property, value); }
        }

        [TypeConverter(typeof(LengthConverter))]
        public double Y1
        {
            get { return (double)GetValue(Y1Property); }
            set { SetValue(Y1Property, value); }
        }

        [TypeConverter(typeof(LengthConverter))]
        public double X2
        {
            get { return (double)GetValue(X2Property); }
            set { SetValue(X2Property, value); }
        }

        [TypeConverter(typeof(LengthConverter))]
        public double Y2
        {
            get { return (double)GetValue(Y2Property); }
            set { SetValue(Y2Property, value); }
        }
    }
}

The problem is that when we draw shapes in within the canvas, the shadow is clipped outside of the rectangle. However, the same shape drawn using XAML, renders differently.

Screenshot from Visual Studio designer:

Screenshot from Visual Studio designer

Screenshot from compiled app window:

Screenshot from compiled app window:

I would appreciate any help in the right direction please.

McoreD
  • 313
  • 2
  • 12
  • 2
    Is `ClipToBounds` (which has [problems](http://stackoverflow.com/q/6684904/1997232) with `Canvas`) is what you need? – Sinatr Mar 07 '16 at 15:39
  • @Sinatr adding `ClipToBounds = false;` not helps, still shadow not visible outside. – Jaex Mar 07 '16 at 16:14
  • I suggest you have a look at rectangle implementation [here](http://www.dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/wpf/src/Framework/System/Windows/Shapes/Rectangle@cs/1305600/Rectangle@cs) and see if that gives you any hint of what is happening to you – Pikoh Mar 07 '16 at 17:20

0 Answers0