我在自定义FrameworkElement的OnRender方法中绘制图像。我也想绘制此图像的阴影。我需要在代码中执行此操作,并且我不想使用DropShadowBitmapEffect,因为它已过时。我该如何实现?
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));
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,下面的SvenG建议的为基础元素添加效果的解决方案对我不起作用,因为它为整个元素(而不是我绘制的单个图像)提供了阴影。例如,如果我有两个重叠的DrawImage,建议的解决方案将考虑整个阴影。上方图像的阴影不会在下方图像上绘制。
另外,我想使用如上所述的getBitmap函数创建位图,以导出带有阴影的绘制图像。
有一个旧的PushEffect()调用DrawingContext可以满足您的要求,但是像BitmapEffect一样,这已经过时了。
BitmapEffect的替代者是Effect阶级。有一个子类DropShadowEffect正是您所追求的,但是不幸的是,正如SvenG所说,它不能直接应用于位图。
支持应用效果的最低级别的元素是DrawingVisual类。这还不错,因为它DrawingVisual是一个非常轻量级的类。没有布局开销。最好的选择是单独创建每个位图DrawingVisual,然后将Effect视觉效果的属性设置为DropShadowEffect。显然,如果您有成千上万个位图,那可能不是一个可行的解决方案。
所有这些都可以用代码完成,尽管OnRender()由于每种视觉效果都有其自己的渲染上下文,所以这不能做到。但是,为了使子DrawingVisuals正确呈现,您需要告诉框架有关它们的信息。
您需要重写自定义元素中的两个方法才能看到这些视觉效果:VisualChildrenCount说出您有多少个孩子,以及GetVisualChild()将它们返回给系统。因此,您将需要保留一组可用的视觉效果。您也可以致电AddVisualChild(),AddLogicalChild()如果您想对他们进行命中测试。
public class MyDrawingView : FrameworkElement
{
List<DrawingVisual> _visuals = new List<DrawingVisual>();
public MyDrawingView()
{
CreateVisuals();
}
//Gets a bitmap rendering of the visual and its children for saving as image file
public RenderTargetBitmap GetBitmap()
{
var rtb = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
rtb.Render(this);
return rtb;
}
protected override int VisualChildrenCount
{
get
{
return _visuals.Count;
}
}
protected override Visual GetVisualChild(int index)
{
return _visuals[index];
}
private void CreateVisuals()
{
CreateVisualForBitmap(@"D:\mytemp\img1.jpg", new Rect(50, 50, 100, 100));
CreateVisualForBitmap(@"D:\mytemp\img2.jpg", new Rect(30, 30, 100, 100));
}
private void CreateVisualForBitmap(string bitmapPath, Rect bounds)
{
var bitmap = new BitmapImage(new Uri(bitmapPath));
var visual = new DrawingVisual();
visual.Effect = new DropShadowEffect();
using (DrawingContext dc = visual.RenderOpen())
{
dc.DrawImage(bitmap, bounds);
}
_visuals.Add(visual);
AddVisualChild(visual);
AddLogicalChild(visual);
}
}
Run Code Online (Sandbox Code Playgroud)