15

我在哪里可以找到有关画笔如何实现我自己的 System.Windows.Media.Brush 的足够信息?我可以处理所有可冷冻的行李,但我需要覆盖什么才能让它工作并不是很明显。


是的,所以我并不是说我想使用预定义的画笔。我想扩展 System.Windows.Media.Brush,它是一个抽象类。这一切纯粹是为了我自己的熏陶。我什至不确定我能做什么样的刷子。我只是想了解刷子是如何工作的。如:

public AwesomeBrush : Brush
{

    protected override Freezable CreateInstanceCore()
    {
        return new AwesomeBrush();
    }

    ... // concrete brush stuff

}
4

4 回答 4

10

我使用Reflector快速浏览了现有的画笔。看起来他们的实现非常封闭,并且依赖于大量的internal管道。虽然可以实现自己的画笔,但它似乎不是一个受支持的选项。甚至可能是 WPF 控件与现有画笔紧密相关,无法与自定义画笔一起使用。

实现类似于自定义画笔的最佳方式很可能是使用带有一些复杂绘图逻辑的DrawingBrush 。您可以使用其他画笔从复杂的形状组成绘图画笔,这样您就可以实现所需的目标。

修改后更新

由于这是用于教育,您最好下载反射器并使用它来查看画笔的工作原理。它们并不是要自行实现的,而且由于它们依赖于internal程序员通常无法访问的某些类,因此很难做到这一点。

虽然有趣的是,Brush 文档确实有一条注释供继承者以正确的方式从 Brush 继承。

更多更新

当我四处寻找时,我发现了一种在中文博客上实现类似目标的非常巧妙的方法。诀窍是使用标记扩展,所以它看起来就像一个画笔。实际上,它会根据其属性创建一个新的图像画笔。似乎他得出了同样的结论,即有一些内部类阻碍了简单的实现。

于 2009-04-27T18:34:45.613 回答
5

要回答为什么您可能想要自定义画笔的问题,请考虑一个复杂的几何图形,并且您希望使用与形状匹配的渐变填充它,同时从形状的中心(或任何任意起点)径向更改颜色。

没有办法用静态填充来做到这一点(这几乎消除了所有现有的画笔)。没有一遍又一遍地复制对象并将它们嵌套(并制定外壳以使其看起来都正确),用不同的颜色填充每个对象,唯一实用的方法是使用可以查看正在填充的对象的刷子.

这实际上在 Forms 中是可行的。

但看起来在 WPF 中没有任何方法可以做到这一点,这是不幸的。

事实上,WPF 的画笔同时具有惊人的强大功能和惊人的局限性。它们显然是为某些概念模型设计的,但我完全不确定它是否有用,除了一些非常微不足道的视觉效果,而且像往常一样,它变得更加复杂,带有奇怪的(记录不充分的)参数,这使得做简单,有些复杂。

于 2012-02-15T17:34:52.943 回答
4

我尝试了所有可能的角度来寻找制作自定义画笔的解决方案,从使用 MarkupExtensions 到弄乱 TypeConverter 属性,然后它让我大吃一惊:您只需创建一个基于 DependencyObject 的包装类,创建一个 Brush 类型的 DependencyProperty,实现您的自定义然后绑定到 Brush DependencyProperty。

然后,将自定义画笔放在资源中

  <l:CustomBrush x:Key="CustomBrush" Brush="Magenta" />

然后绑定到它:

  <Line X1="0" Y1="-5" X2="200" Y2="-5" 
        Stroke="{Binding Source={StaticResource CustomBrush}, Path=Brush}" 
        StrokeThickness="12"/>

我认为这比 MarkupExtension 解决方案更好,因为您不能在 Resources 中放置一个,因此每次使用它时都必须重新定义自定义设置。

无论如何,这似乎是从任何 Wpf 对象继承的简单解决方案,并且借助 Bindings 的灵活性,您还可以绑定到包装的 Wpf 对象本身的成员。

这是简单的类:

public class CustomBrush : DependencyObject
{
   public CustomBrush()
   {
      this.Brush = Brushes.Azure;      
   }

   #region Brush DependencyProperty

   [BindableAttribute(true)]
   public Brush Brush
   {
     get { return (Brush)GetValue(BrushProperty); }
     set { SetValue(BrushProperty, value); }
   }
   public static readonly DependencyProperty BrushProperty =
      DependencyProperty.Register(
         "Brush",
         typeof(Brush),
         typeof(CustomBrush),
         new UIPropertyMetadata(null));

   #endregion         
}
于 2010-03-18T21:18:54.477 回答
3

您不能通过从System.Windows.Media.Brush类继承来制作自定义 WPF 画笔,因为该类包含内部的抽象成员。

如果使用 Reflector 查看System.Windows.Media.Brush类的源代码,会看到如下内部抽象方法:

internal abstract DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel);
internal abstract DUCE.Channel GetChannelCore(int index);
internal abstract int GetChannelCountCore();
internal abstract DUCE.ResourceHandle GetHandleCore(DUCE.Channel channel);
internal abstract void ReleaseOnChannelCore(DUCE.Channel channel);

这些必须被覆盖,但不能被覆盖,因为它们是内部的。

注意:编辑了我的答案,因为之前的答案是关于System.Drawing.Brush这个问题并且与这个问题无关。特别感谢 Mikko Rantanen 的评论。

于 2009-04-27T18:15:59.623 回答