2010-12-30 5 views
4

У меня есть серебряная рамка с текстом сверху, которую я бы хотел исключить (вырезать текст вдали от границы), чтобы увидеть фон за границей, на котором применен метод dropshadow bitmapeffect. Возможно ли это, без перехода в Photoshop, чтобы создать изображение, которое в основном делает то же самое, не будучи столь гибким?Исключить текст ярлыка с границы

Если возможно, как бы я решил выполнить такую ​​задачу?

+1

Я не совсем понимаю, что вы пытаетесь сделать. Не могли бы вы опубликовать скриншот или какой-нибудь пример кода? –

+0

Спасибо за ваш ответ ... Я бросил это вместе в фотошопе и надеюсь, что это поможет ... http://users.indytel.com/~jsmain/downloads/NowPlaying.png. Я хочу увидеть фон через серебряную границу, а также тени эффект границы, как на этом изображении. Я не могу понять, как исключить геометрию текста из границы в xaml. –

ответ

3

Я немного поиграл с этим и получил следующее.
Трудной частью было «инвертировать» OpacityMask для границы. Я создал класс, который происходит из Image, который добавляет несколько свойств зависимостей, таких как Text, FontFamily и EmSize. Затем он превращает текст в геометрию с использованием подхода от this link.

Вы можете играть с текстом, FontFamily, EmSize, Width и Height, пока не получите требуемый результат. Разумеется, вы также можете добавить дополнительные DP для InvertOpacityText для повышения гибкости.

Я закончил с этим

alt text

<Grid Background="Blue"> 
    <Border Background="Gray" CornerRadius="8,8,8,8" Width="240" Height="220"> 
     <Border.Effect> 
      <DropShadowEffect ShadowDepth="10" 
           Direction="310" 
           Color="Black" 
           Opacity="0.8" 
           BlurRadius="4"/> 
     </Border.Effect> 
     <Border.OpacityMask> 
      <VisualBrush> 
       <VisualBrush.Visual> 
        <local:InvertOpacityText Text=" Now Playing" 
              EmSize="70" 
              Stretch="Fill" 
              Width="510" 
              Height="414" 
              FontFamily="Broadway"> 
         <local:InvertOpacityText.LayoutTransform> 
          <RotateTransform Angle="-90"/> 
         </local:InvertOpacityText.LayoutTransform> 
        </local:InvertOpacityText> 
       </VisualBrush.Visual> 
      </VisualBrush> 
     </Border.OpacityMask> 
     <Image Margin="45,5,5,5" Source="C:\PhilCollins.png"/> 
    </Border> 
</Grid> 

InvertOpacityText.cs

public class InvertOpacityText : Image 
{ 
    public static readonly DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", 
            typeof(string), 
            typeof(InvertOpacityText), 
            new FrameworkPropertyMetadata(string.Empty, 
                    TargetPropertyChanged)); 
    public static readonly DependencyProperty EmSizeProperty = 
     DependencyProperty.Register("EmSize", 
            typeof(double), 
            typeof(InvertOpacityText), 
            new FrameworkPropertyMetadata(70.0, 
                    TargetPropertyChanged)); 
    public static readonly DependencyProperty FontFamilyProperty = 
     DependencyProperty.Register("FontFamily", 
            typeof(FontFamily), 
            typeof(InvertOpacityText), 
            new FrameworkPropertyMetadata(new FontFamily(), 
                    TargetPropertyChanged)); 

    private static void TargetPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
    { 
     InvertOpacityText invertOpacityText = (InvertOpacityText)source; 
     invertOpacityText.OnTextChanged(); 
    } 

    public string Text 
    { 
     get { return (string)base.GetValue(TextProperty); } 
     set { base.SetValue(TextProperty, value); } 
    } 
    public double EmSize 
    { 
     get { return (double)base.GetValue(EmSizeProperty); } 
     set { base.SetValue(EmSizeProperty, value); } 
    } 
    public FontFamily FontFamily 
    { 
     get { return (FontFamily)base.GetValue(FontFamilyProperty); } 
     set { base.SetValue(FontFamilyProperty, value); } 
    } 

    private void OnTextChanged() 
    { 
     if (Source == null) 
     { 
      Source = CreateBitmapSource(); 
     } 

     FormattedText tx = new FormattedText(Text, 
              Thread.CurrentThread.CurrentUICulture, 
              FlowDirection.LeftToRight, 
              new Typeface(FontFamily, 
                  FontStyles.Normal, 
                  FontWeights.Bold, 
                  FontStretches.Normal), 
              EmSize, 
              Brushes.Black); 
     Geometry textGeom = tx.BuildGeometry(new Point(0, 0)); 
     Rect boundingRect = new Rect(new Point(-100000, -100000), new Point(100000, 100000)); 
     RectangleGeometry boundingGeom = new RectangleGeometry(boundingRect); 
     GeometryGroup group = new GeometryGroup(); 
     group.Children.Add(boundingGeom); 
     group.Children.Add(textGeom); 
     Clip = group; 
    } 
    private BitmapSource CreateBitmapSource() 
    { 
     int width = 128; 
     int height = width; 
     int stride = width/8; 
     byte[] pixels = new byte[height * stride]; 
     List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>(); 
     colors.Add(System.Windows.Media.Colors.Red); 
     colors.Add(System.Windows.Media.Colors.Blue); 
     colors.Add(System.Windows.Media.Colors.Green); 
     BitmapPalette myPalette = new BitmapPalette(colors); 
     return BitmapSource.Create(width, 
            height, 
            96, 
            96, 
            PixelFormats.Indexed1, 
            myPalette, 
            pixels, 
            stride); 
    } 
} 
+0

Meleak, Это абсолютно избито! Спасибо! –

2

Вот решение, которое работает путем создания нового FrameworkElement под названием HollowTextBlock, который заполняет его размер выделенного с его Background и скрепок прочь от Text оставляя его прозрачным. Полноценная реализация потребует поддержки гораздо большего количества свойств, но это доказывает, что концепция работает.

Во-первых, здесь приведен пример XAML:

<Grid> 
    <Grid> 
     <Grid.Background> 
      <LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> 
       <GradientStop Color="#FF0000" Offset="0" /> 
       <GradientStop Color="#0000FF" Offset="1" /> 
      </LinearGradientBrush> 
     </Grid.Background> 
    </Grid> 
    <Grid> 
     <local:HollowTextBlock Width="200" Height="50" Text="Hello, world!" Background="White" HorizontalAlignment="Center"/> 
    </Grid> 
</Grid> 

который определяет красочный фон градиент позади текста таким образом, мы можем видеть, что это работает. Затем создадим наш HollowTextBlock и в прототипе Width, Height, Text и Background все должны быть указаны.

Тогда вот наша реализация HollowTextBlock:

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 UIPropertyMetadata(string.Empty)); 

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

    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("Arial"); 
     var size = 32; 
     var ft = new FormattedText(Text, Thread.CurrentThread.CurrentUICulture, FlowDirection.LeftToRight, face, size, Brushes.Black); 
     var hole = ft.BuildGeometry(new Point((RenderSize.Width - ft.Width)/2, (RenderSize.Height - ft.Height)/2)); 
     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(); 
    } 
} 

и просчитанный результат выглядит следующим образом:

HollowTextBlock

нотабене Когда вы используете его, вы должны быть осторожны, чтобы не поставить его поверх чего-то, что затмило бы реальный фон, который вы хотели бы показать.

+0

Спасибо, Рик! Я отдам это! Приложите свою помощь. –

+0

Не уверен, могу ли я на самом деле работать так, чтобы делать то, что хочу после игры с ним.Боюсь, я еще не понимаю, что там происходит. Мне нужно повернуть текст, как в моем примере, и было бы желательно, чтобы он находился на границе с динамическим размером, чтобы разместить обложки альбомов (CD и DVD). –

Смежные вопросы