I draw an image in OnRender method of my custom FrameworkElement. I would like to draw a shadow of this image as well. I need to do this in code, and I would not like to use DropShadowBitmapEffect because it is obsolete. How can I achieve this?
public class MyDrawingView : FrameworkElement
{
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
drawImagesOnDrawingContext(dc);
}
public RenderTargetBitmap getBitmap()
{
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dcMine = dv.RenderOpen())
{
drawImagesOnDrawingContext(dcMine);
dcMine.Close();
}
RenderTargetBitmap rtb = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
rtb.Render(dv);
return rtb;
}
private void drawImagesOnDrawingContext(System.Windows.Media.DrawingContext dc)
{
//how to draw shadow on bi?
BitmapImage bi = new BitmapImage(new Uri(@"D:\mytemp\img1.jpg"));
dc.DrawImage(bi, new Rect(50, 50, 100, 100));
//how to draw shadow on bi1
BitmapImage bi1 = new BitmapImage(new Uri(@"D:\mytemp\img2.jpg"));
dc.DrawImage(bi1, new Rect(30, 30, 100, 100));
}
}
Note that the solution suggested by SvenG below, to add an effect to the underlying element, doesn’t work for me because it gives a shadow to the whole element, not the individual images I draw. For example, if I were to have two overlapping DrawImage, the suggested solution will draw shadow considering the whole. The shadow of upper image will not be drawn on the lower image.
Additionally, I want to create a bitmap using the getBitmap function as shown above to export the drawn image with the shadows.
There is an old
PushEffect()call onDrawingContextthat would have done what you required, but like BitmapEffect this is obsolete.BitmapEffect‘s replacement is theEffectclass. There is a subclass calledDropShadowEffectthat is exactly what you are after, but unfortunately as SvenG says, this cannot be applied directly to bitmaps.The lowest level element that supports applying effects is the
DrawingVisualclass. This isn’t too bad becauseDrawingVisualis a pretty lightweight class. There is no layout overhead. Your best bet would be to create each bitmap in its ownDrawingVisual, and set theEffectproperty of the visual to aDropShadowEffect. Obviously if you have thousands of bitmaps it may not be a viable solution.All this can be done in code, although not
OnRender()since each visual has its own render context. However, for child DrawingVisuals to render properly, you need to tell the framework about them.You need to override two methods in your custom element in order to see these visuals:
VisualChildrenCountto say how many children you have, and GetVisualChild() to return them to the system. Because of this you will need to keep a collection of visuals available. You can also callAddVisualChild()andAddLogicalChild()if you want to do hit testing against them.