2009-04-27 23 views
12

¿Dónde puedo encontrar información suficiente sobre cómo funcionan los Pinceles para implementar mi propio System.Windows.Media.Brush? Puedo manejar todo el equipaje congelable, pero no es realmente obvio lo que necesito anular para que funcione.¿Cómo implemento un pincel personalizado en WPF?


Sí, así que no quise decir que quiero usar un pincel predefinido. Quiero extender System.Windows.Media.Brush, que es una clase abstracta. Todo esto es puramente para mi propia edificación. Ni siquiera estoy seguro de qué tipo de cepillo podría hacer. Solo estaba tratando de aprender cómo funcionan los pinceles. Como en:

public AwesomeBrush : Brush 
{ 

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

    ... // concrete brush stuff 

} 
+0

Puede ser útil proporcionar un poco más de información sobre lo que está tratando de hacer. No estoy seguro de qué sería lo que crearía un pincel, pero esta es una buena lista de los muchos pinceles integrados en wpf: http://msdn.microsoft.com/en-us/library/aa970904.aspx –

Respuesta

3

No se puede hacer un cepillo de WPF personalizado heredando de la clase System.Windows.Media.Brush, porque esa clase contiene miembros abstractos que son internos.

Si utiliza reflector para ver el código fuente de la clase System.Windows.Media.Brush, verá los siguientes métodos abstractos internos:

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); 

Estos deben ser anulados, pero no puede ser debido a que son internos.

Nota: Edité mi respuesta porque la respuesta anterior fue aproximadamente System.Drawing.Brush e irrelevante para esta pregunta. Un agradecimiento especial a Mikko Rantanen por su comentario.

+4

Puede heredar de la clase Pincel - como dijiste, sus clases abstractas y abstractas DEBEN ser heredadas. –

+0

¿Qué tiene Pincel que hace que no se pueda heredar? Sé que todas las implementaciones están selladas, pero deberíamos poder derivar de Brush, ¿verdad? – MojoFilter

+1

¡Malditos seas, constructores internos! ¡Fui frustrado por ti antes! – MojoFilter

9

He echado un vistazo rápido a las escobillas existentes usando el Reflector. Parece que su implementación está bastante cerrada y depende de muchas tuberías internal. Si bien es posible implementar su propio pincel, parece que no es una opción compatible. Incluso podría ser que los controles WPF estén estrechamente vinculados a los pinceles existentes y no funcionarán con uno personalizado.

Lo más probable es que la mejor manera de lograr algo parecido a los pinceles personalizados es usar el DrawingBrush con una lógica de dibujo compleja. Puede componer un pincel de dibujo de formas complejas con otros pinceles, de modo que esto le permita alcanzar el objetivo deseado.

Update después de editar

ya que esto es para la educación, que podría ser mejor fuera de la descarga del reflector y utilizarlo para ver cómo funcionan los cepillos. No están destinados a implementarse por sí mismos y dado que dependen de algunas clases internal a las que los programadores no tienen acceso normalmente, será bastante difícil hacerlo.

Aunque lo que lo hace interesante es que el Brush documentation tiene un comentario para que los herederos guíen en la forma correcta de heredar del Pincel.

Más actualizaciones

Cuando hurgando he encontrado una manera bastante ordenada para lograr algo similar en una chinese blog. El truco es usar una extensión de marcado para que parezca un pincel. En realidad, crea un nuevo pincel de imagen basado en sus atributos. Parece que llegó a la misma conclusión de que hay algunas clases internas que impiden la fácil implementación.

+0

Sospecho que ese es el caso, también. No puedo imaginarme nada que no se pueda hacer con las implementaciones de pincel provistas en el marco, solo me preguntaba si podría haber formas divertidas de componer esas cosas para que sean realmente perfectas para su reutilización. – MojoFilter

+0

Se agregó una actualización que logra algo similar sin extender Brush. –

+1

Me pregunto si la nota en la documentación del cepillo para los herederos era para Microsoft personal y no debía llegar al documento final. Cuando miro Reflector, parece que muchos de los campos esenciales en Brush y también GradientBrush están marcados como internos. Entonces no podemos llegar a ellos. –

3

Probé todos los ángulos posibles para encontrar una solución para crear un pincel personalizado, usar MarkupExtensions para mezclar con los atributos TypeConverter, y luego me impresionó: simplemente creaste una clase contenedora basada en DependencyObject, creaste una DependencyProperty de tipo Pincel , implemente su personalización y luego Vincúlese a Brush DependencyProperty.

A continuación, poner el pincel personalizado en Recursos

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

se unen entonces a la misma:

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

creo que esto es mejor que la solución MarkupExtension porque no se puede poner uno en Recursos y por lo tanto, debe redefinir la configuración personalizada cada vez que la usa.

En cualquier caso, esto parecería ser una solución simple para heredar de cualquier objeto Wpf, y con la flexibilidad de los enlaces también puede vincular a los miembros del objeto Wpf envuelto.

Aquí está la clase simple:

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   
} 
4

Para responder a la pregunta de por qué es posible que desee tener un pincel personalizado, considere una geometría compleja y quiere llenarlo con un degradado que coincide con la forma mientras se cambia colores radialmente desde el centro de la forma (o cualquier punto de partida arbitrario).

No hay forma de hacerlo con un relleno estático (que elimina casi todas las escobillas existentes). Sin replicar el objeto una y otra vez y anidarlo (y calcular el descascarado para que todo se vea bien), llenando cada uno con un color diferente, la única forma práctica es tener un pincel que pueda mirar el objeto que se está llenando .

Esto es factible en las formas.

Pero no parece que haya forma de hacerlo en WPF, lo cual es desafortunado.

De hecho, los cepillos de WPF son a la vez sorprendentemente potentes Y sorprendentemente limitados. Están claramente diseñados para algún modelo de concepto, pero no estoy del todo seguro de que sea útil más allá de algunos efectos visuales bastante triviales, y como de costumbre, se ha vuelto más complejo con parámetros extraños (pobremente documentados) que hacen que el simple, algo complicado.

Cuestiones relacionadas