Инвертный OpacityMask
Рассмотрим следующий фрагмент Xaml
<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>
Это будет выглядеть так из-за OpacityMask, только непрозрачная часть которого является передним планом текстового блока.
Теперь, если я переключу цвета для переднего плана и фона в текстовом блоке, как это
<TextBlock Text="Text"
Foreground="#00000000"
Background="#FF000000"/>
Я получаю это, потому что, хотя передний план прозрачен, фон за ним не является, что приводит к бесполезной маске непрозрачности :)
Могу ли я вообще получить это? В основном перевернутая Маска непрозрачности
Я упускаю какой-то другой способ сделать это здесь?
Обновить
Чтобы пояснить, хотя мой пример касается текстового блока, это может быть что угодно. Эллипс / изображение / путь и т.д. Функция, которую я ищу, - "Invert OpacityMask"
1 ответ:
Вы можете использовать мой
HollowTextBlock
, который является другим ответом на тот же самый Вопрос :<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>
Обновление:
Вот более развернутая версия
HollowTextBlock
с соответствующими возможностями измерения, наследованием значений свойств для обычных свойств текста и новым свойствомVerticalTextAlignment
для центрирования текста по вертикали в выделенном пространстве: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; } }