2009-04-27 11 views
12

Où puis-je trouver suffisamment d'informations sur la façon dont les pinceaux fonctionnent pour implémenter mon propre System.Windows.Media.Brush? Je peux gérer tous les bagages en congélation, mais ce n'est pas vraiment évident ce que j'ai besoin de passer outre pour le faire fonctionner.Comment implémenter un pinceau personnalisé dans WPF?


Oui, donc je ne voulais pas dire que je voulais utiliser un pinceau prédéfini. Je veux étendre System.Windows.Media.Brush, qui est une classe abstraite. Tout cela est purement pour ma propre édification. Je ne suis même pas sûr du genre de brosse que je pourrais faire. J'essayais juste d'apprendre comment fonctionnent les pinceaux. Comme dans:

public AwesomeBrush : Brush 
{ 

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

    ... // concrete brush stuff 

} 
+0

Il peut être utile de fournir un peu plus d'informations sur ce que vous essayez de faire. Vous ne savez pas exactement ce que créer un pinceau, mais voici une bonne liste des pinceaux construits dans wpf: http://msdn.microsoft.com/en-us/library/aa970904.aspx –

Répondre

3

Vous ne pouvez pas faire une brosse WPF personnalisé en héritant de la classe System.Windows.Media.Brush, car cette classe contient des membres abstraits qui sont internes.

Si vous utilisez réflecteur pour voir le code source de System.Windows.Media.Brush classe, vous verrez les méthodes abstraites internes suivantes:

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

Ceux-ci doivent être remplacés, mais ne peuvent pas être parce qu'ils sont internes.

Note: Édité ma réponse parce que la réponse précédente était sur System.Drawing.Brush et sans rapport avec cette question. Un merci spécial à Mikko Rantanen pour son commentaire.

+4

Vous pouvez hériter de la classe Pinceau - Comme vous l'avez dit, les classes abstraites et abstraites DOIVENT être héritées. –

+0

Qu'est-ce qui fait que Brush ne peut pas être hérité? Je sais que toutes les implémentations sont scellées, mais nous devrions pouvoir dériver de Brush, n'est-ce pas? – MojoFilter

+1

Merde vous les constructeurs internes! J'ai été déjoué par vous avant! – MojoFilter

9

J'ai eu un coup d'œil sur les brosses existantes avec le Reflector. Il semble que leur mise en œuvre est assez fermée et dépend de beaucoup de plomberie internal. Bien qu'il soit possible d'implémenter votre propre pinceau, il semble que ce n'est pas une option supportée. Il se pourrait même que les contrôles WPF soient étroitement liés aux pinceaux existants et ne fonctionneront pas avec un contrôle personnalisé.

Très probablement la meilleure façon de réaliser quelque chose qui ressemble à pinceaux personnalisés est d'utiliser la DrawingBrush avec une certaine logique de dessin complexe. Vous pouvez composer un pinceau de dessin à partir de formes complexes en utilisant d'autres pinceaux, ce qui devrait vous permettre d'atteindre l'objectif requis.

Mise à jour après modification

Comme cela est pour l'éducation, vous pourriez être mieux loti télécharger le réflecteur et en utilisant que pour voir comment les brosses fonctionnent. Ils ne sont pas destinés à être auto-implémentés et puisqu'ils s'appuient sur certaines classes auxquelles les programmeurs n'ont normalement pas accès, il sera assez difficile de le faire.

Bien que ce qui le rend intéressant est que le Brush documentation a une remarque pour les héritiers à guider dans la façon correcte d'hériter de la brosse.

Autres mises à jour

Lorsque farfouillé j'ai trouvé une façon assez nette pour obtenir quelque chose de similaire sur un chinese blog. L'astuce consiste à utiliser une extension de balisage afin qu'elle ressemble à un pinceau. En réalité, il crée une nouvelle brosse d'image basée sur ses attributs. Semble qu'il est arrivé à la même conclusion qu'il existe des classes internes qui empêchent la mise en œuvre facile.

+0

Je pense que c'est aussi le cas. Je ne peux pas imaginer quoi que ce soit qui ne puisse pas être fait avec les implémentations de pinceaux fournies dans le framework, je me demandais juste s'il pourrait y avoir des façons amusantes de classer de telles choses pour qu'elles soient vraiment faciles à réutiliser. – MojoFilter

+0

Ajout d'une mise à jour qui réalise quelque chose de similaire sans étendre le pinceau. –

+1

Je me demande si la note dans la documentation de la brosse pour les héritiers était pour Microsoft personnel et n'était pas censé en faire le document final. Comme je regarde Reflector, il semble que beaucoup de domaines essentiels dans Brush et aussi GradientBrush sont marqués interne. Donc nous ne pouvons pas les atteindre. –

3

J'ai essayé tous les angles possibles pour créer une brosse personnalisée, depuis l'utilisation de MarkupExtensions avec les attributs de TypeConverter, puis j'ai créé une classe wrapper basée sur DependencyObject, créer une DependencyProperty de type Brush , implémentez votre personnalisation puis liez à la propriété DependencyPush.

Ensuite, mettre la brosse sur mesure dans les ressources

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

Rabattre lui:

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

Je pense que cela vaut mieux que la solution MarkupExtension parce que vous ne pouvez pas mettre un en ressources et par conséquent, vous devez redéfinir les paramètres personnalisés chaque fois que vous l'utilisez.

Dans tous les cas, cela semble être une solution simple pour hériter de n'importe quel objet Wpf, et avec la flexibilité des liaisons, vous pouvez également lier aux membres de l'objet Wpf encapsulé lui-même.

Voici la classe 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

Pour répondre à la question de savoir pourquoi vous voudrez peut-être avoir une brosse sur mesure, envisager une géométrie complexe et que vous voulez le remplir avec un dégradé qui correspond à la forme tout en changeant couleurs radialement à partir du centre de la forme (ou tout point de départ arbitraire).

Il n'y a aucun moyen de le faire avec un remplissage statique (qui élimine à peu près tous les pinceaux existants). À court de reproduire l'objet encore et encore et de les imbriquer (et de travailler sur la coque pour que tout ait l'air correct), en remplissant chacun d'une couleur différente, le seul moyen pratique est d'avoir une brosse qui peut regarder l'objet à remplir .

Ceci est réellement réalisable dans Forms.

Mais il ne semble pas possible de le faire dans WPF, ce qui est regrettable.

En fait, les brosses de WPF sont à la fois étonnamment puissantes et étonnamment limitées. Ils sont clairement conçus pour un modèle conceptuel, mais je ne suis pas du tout sûr que ce soit utile au-delà de certains effets visuels plutôt triviaux, et comme d'habitude, il est rendu plus complexe avec des paramètres étranges (mal documentés). simple, un peu compliqué.

Questions connexes