2010-12-31 9 views
4

Betrachten Sie das folgende Stück XAMLInvert OpacityMask

<Grid Background="Blue"> 
    <Border Width="100" Height="60" BorderBrush="Black" BorderThickness="2"> 
     <Border Background="Red"> 
      <Border.OpacityMask> 
       <VisualBrush> 
        <VisualBrush.Visual> 
         <TextBlock Text="Text" 
            Foreground="#FF000000" 
            Background="#00000000"/> 
        </VisualBrush.Visual> 
       </VisualBrush> 
      </Border.OpacityMask> 
     </Border> 
    </Border> 
</Grid> 

Es wird wie folgt aussehen wegen der OpacityMask whos nur nicht-transparenten Teil der Vordergrund des Textblock ist.
alt text

Nun, wenn ich die Farben für den Vordergrund und Hintergrund im Textblock wie diese

<TextBlock Text="Text" 
      Foreground="#00000000" 
      Background="#FF000000"/> 

ich dies, weil das, obwohl der Vordergrund wechseln ist transparent der Hintergrund dahinter ist nicht, in einem resultierenden nutzlos OpacityMask :)
alt text

Gibt es sowieso ich kann das bekommen? Grundsätzlich eine invertierte OpacityMask

Fehle ich eine andere Möglichkeit, dies hier zu tun?

aktualisieren
Um zu klären, obwohl mein Beispiel über eine TextBlock- ist, könnte es alles sein. Ellipse/Bild/Pfad etc. Das Feature, das ich bin nach ist "Invert OpacityMask"

Antwort

3

können Sie meine verwenden HollowTextBlock die unterschiedliche Antwort auf die gleiche question ist:

<Grid Background="Blue"> 
    <Border Width="100" Height="60" BorderBrush="Black" BorderThickness="2"> 
     <Border Background="Red"> 
      <Border.OpacityMask> 
       <VisualBrush Stretch="None"> 
        <VisualBrush.Visual> 
         <local:HollowTextBlock Width="200" Height="50" Text="Text" Background="White" HorizontalAlignment="Center"/> 
        </VisualBrush.Visual> 
       </VisualBrush> 
      </Border.OpacityMask> 
     </Border> 
    </Border> 
</Grid> 

Update:

Hier ist eine ausgefeiltere Version von HollowTextBlock mit geeigneter Messfunktionalität, Vererbung von Eigenschaftswerten für die üblichen Texteigenschaften und einer neuen Eigenschaft VerticalTextAlignment für die vertikale Zentrierung des Texts in seinem zugewiesenen Bereich:

public class HollowTextBlock : FrameworkElement 
{ 
    public string Text 
    { 
     get { return (string)GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 

    public static readonly DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", typeof(string), typeof(HollowTextBlock), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(HollowTextBlock.OnTextChanged), new CoerceValueCallback(HollowTextBlock.CoerceText))); 

    public Brush Background 
    { 
     get { return (Brush)GetValue(BackgroundProperty); } 
     set { SetValue(BackgroundProperty, value); } 
    } 

    public static readonly DependencyProperty BackgroundProperty = 
     TextElement.BackgroundProperty.AddOwner(typeof(HollowTextBlock), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); 

    public double FontSize 
    { 
     get { return (double)GetValue(FontSizeProperty); } 
     set { SetValue(FontSizeProperty, value); } 
    } 

    public static readonly DependencyProperty FontSizeProperty = 
     TextElement.FontSizeProperty.AddOwner(typeof(HollowTextBlock)); 

    public FontFamily FontFamily 
    { 
     get { return (FontFamily)GetValue(FontFamilyProperty); } 
     set { SetValue(FontFamilyProperty, value); } 
    } 

    public static readonly DependencyProperty FontFamilyProperty = 
     TextElement.FontFamilyProperty.AddOwner(typeof(HollowTextBlock)); 

    public FontStyle FontStyle 
    { 
     get { return (FontStyle)GetValue(FontStyleProperty); } 
     set { SetValue(FontStyleProperty, value); } 
    } 

    public static readonly DependencyProperty FontStyleProperty = 
     TextElement.FontStyleProperty.AddOwner(typeof(HollowTextBlock)); 

    public FontWeight FontWeight 
    { 
     get { return (FontWeight)GetValue(FontWeightProperty); } 
     set { SetValue(FontWeightProperty, value); } 
    } 

    public static readonly DependencyProperty FontWeightProperty = 
     TextElement.FontWeightProperty.AddOwner(typeof(HollowTextBlock)); 

    public FontStretch FontStretch 
    { 
     get { return (FontStretch)GetValue(FontStretchProperty); } 
     set { SetValue(FontStretchProperty, value); } 
    } 

    public static readonly DependencyProperty FontStretchProperty = 
     TextElement.FontStretchProperty.AddOwner(typeof(HollowTextBlock)); 

    public TextAlignment TextAlignment 
    { 
     get { return (TextAlignment)GetValue(TextAlignmentProperty); } 
     set { SetValue(TextAlignmentProperty, value); } 
    } 

    public static readonly DependencyProperty TextAlignmentProperty = 
     Block.TextAlignmentProperty.AddOwner(typeof(HollowTextBlock)); 

    public VerticalAlignment VerticalTextAlignment 
    { 
     get { return (VerticalAlignment)GetValue(VerticalTextAlignmentProperty); } 
     set { SetValue(VerticalTextAlignmentProperty, value); } 
    } 

    public static readonly DependencyProperty VerticalTextAlignmentProperty = 
     DependencyProperty.Register("VerticalTextAlignment", typeof(VerticalAlignment), typeof(HollowTextBlock), new FrameworkPropertyMetadata(VerticalAlignment.Top, FrameworkPropertyMetadataOptions.AffectsRender)); 

    private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     OnTextChanged(d, (string)e.NewValue); 
    } 

    private static void OnTextChanged(DependencyObject d, string newText) 
    { 
    } 

    private static object CoerceText(DependencyObject d, object baseValue) 
    { 
     return baseValue; 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     var face = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch); 
     var size = FontSize; 
     var ft = new FormattedText(Text, Thread.CurrentThread.CurrentUICulture, FlowDirection.LeftToRight, face, size, Brushes.Black); 
     return new Size(ft.Width, ft.Height); 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 
     var extent = new RectangleGeometry(new Rect(0.0, 0.0, RenderSize.Width, RenderSize.Height)); 
     var face = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch); 
     var size = FontSize; 
     var ft = new FormattedText(Text, Thread.CurrentThread.CurrentUICulture, FlowDirection.LeftToRight, face, size, Brushes.Black); 
     var originX = GetHorizontalOrigin(ft.Width, RenderSize.Width); 
     var originY = GetVerticalOrigin(ft.Height, RenderSize.Height); 
     var hole = ft.BuildGeometry(new Point(originX, originY)); 
     var combined = new CombinedGeometry(GeometryCombineMode.Exclude, extent, hole); 
     drawingContext.PushClip(combined); 
     drawingContext.DrawRectangle(Background, null, new Rect(0.0, 0.0, RenderSize.Width, RenderSize.Height)); 
     drawingContext.Pop(); 
    } 

    private double GetHorizontalOrigin(double textWidth, double renderWidth) 
    { 
     switch (TextAlignment) 
     { 
      case TextAlignment.Center: 
       return (renderWidth - textWidth)/2; 
      case TextAlignment.Left: 
       return 0; 
      case TextAlignment.Right: 
       return renderWidth - textWidth; 
     } 
     return 0; 
    } 

    private double GetVerticalOrigin(double textHeight, double renderHeight) 
    { 
     switch (VerticalTextAlignment) 
     { 
      case VerticalAlignment.Center: 
       return (renderHeight - textHeight)/2; 
      case VerticalAlignment.Top: 
       return 0; 
      case VerticalAlignment.Bottom: 
       return renderHeight - textHeight; 
     } 
     return 0; 
    } 
} 
+1

+1, sehr cool! Ich habe es ausprobiert und es funktioniert :) Aber diese Lösung fühlt sich auch ein wenig "hacky" genau wie meine und ich wünschte, es wäre etwas in das Framework eingebaut, das es Ihnen erlauben würde, einfach "InvertOpacityMask =" True "' oder Nun, ich weiß, dass es kein solches Feature gibt und wenn jemand eine Möglichkeit hat, zu arbeiten, werde ich das in ein paar Tagen als akzeptiert markieren –

Verwandte Themen