7

I'm using WPF 3.5 SP1 and I want to achieve something like this (the glass-part is already done):


(source: ggpht.com)

(Source)


(Source)

You can see nice blur around the text, which makes it very well readable. I also found out that correct approach is to use API DrawThemeTextEx, which renders the blur using recommended system options. However, how can I achieve the same effect using WPF?

I was able to find these links which contain helpful resources:
How to make WPF text on Aero glass background readable?
Glowing Label Controls On A Glass Surface

They do it by duplicating the TextBlock, and setting a Blur effect on it. However, this is not a real solution. Here is how it looks like:

Compare the result effect with the images above, and you will see the solution is still far away. So how can I properly get the desired effect using WPF? I'm fine with emulation (no use of DrawThemeTextEx API), as far as the result is pretty similar.

Thank you.

4 Answers 4

7
    <TextBlock ...>
        <TextBlock.Effect>
            <DropShadowEffect BlurRadius="10" Color="White" ShadowDepth="0" />
        </TextBlock.Effect>
    </TextBlock>
3
  • Thanks, this is a correct approach. In the final solution I use 3 nested Decorators with DropShadowEffect + cloned TextBlock with BlurEffect, and the result is pretty impressive.
    – Paya
    Commented Feb 11, 2011 at 20:05
  • Paja, could you please provide an answer on how you nested DropShadowEffect? I am unsure how to do this with a TextBlock as I don't know much about Decorators.
    – Luke
    Commented May 26, 2011 at 12:49
  • @Luke: Posted an answer per your request here.
    – Paya
    Commented May 26, 2011 at 23:24
7

As per Luke's request, I include the XAML for Decorators:

<Decorator>
    <Decorator.Effect>
        <DropShadowEffect BlurRadius="7" Color="White" ShadowDepth="0" />
    </Decorator.Effect>
    <Decorator>
        <Decorator.Effect>
            <DropShadowEffect BlurRadius="7" Color="White" ShadowDepth="0" />
        </Decorator.Effect>
        <Decorator>
            <Decorator.Effect>
                <DropShadowEffect BlurRadius="7" Color="White" ShadowDepth="0" />
            </Decorator.Effect>

            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
                    Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" 
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
        </Decorator>
    </Decorator>
</Decorator>

I created a ControlTemplate for a Label with the before-mentioned XAML, and used it everywhere I needed the text to glow.

1
  • I extended this answer to show what it could look like in a ready-to-use style for a label that dims the label on class when disabled: stackoverflow.com/a/21767564/88409
    – Triynko
    Commented Feb 13, 2014 at 23:10
2

How about something along these lines where you have a rectangle behind your text that blurs slightly, I have used this a few times. I find it makes it more readable because the blur covers a bigger area.

            <Grid>
                <Rectangle Fill="#8FFFFFFF"
                           Stroke="{x:Null}"
                           StrokeThickness="0"
                           VerticalAlignment="Center"
                           Width="{Binding ActualWidth, ElementName=PART_Title, Mode=Default}"
                           Height="{Binding ActualHeight, ElementName=PART_Title, Mode=Default}"
                           RadiusX="2"
                           RadiusY="2">
                    <Rectangle.Effect>
                        <BlurEffect Radius="10" />
                    </Rectangle.Effect>
                </Rectangle>

                <TextBlock x:Name="PART_Title"
                           Text="{Binding Title}"
                           Foreground="Black"
                           TextWrapping="NoWrap"
                           TextTrimming="CharacterEllipsis" />
            </Grid>
1
  • Well yeah, that works, but I would like as close emulation of the OS behavior as possible. Maybe stacking 50 blured TextBlocks could do the trick, but there must be a better way.
    – Paya
    Commented Feb 11, 2011 at 18:47
1

I was having trouble implementing the decorator as it stood in Paya's answer, so I show how it can be wrapped in a complete, ready-to-use style resource that can be applied to any label, which will display the glass effect, and will also dim the label when disabled and preserve the alignment, border, etc.:

<Style x:Key="GlassLabelStyle" TargetType="{x:Type Label}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Label}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}" 
                Background="{TemplateBinding Background}" 
                Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                    <Grid>
                        <Decorator>
                            <Decorator.Effect>
                                <DropShadowEffect BlurRadius="7" Color="White" ShadowDepth="0" />
                            </Decorator.Effect>
                            <Decorator>
                                <Decorator.Effect>
                                    <DropShadowEffect BlurRadius="7" Color="White" ShadowDepth="0" />
                                </Decorator.Effect>
                                <Decorator>
                                    <Decorator.Effect>
                                        <DropShadowEffect BlurRadius="7" Color="White" ShadowDepth="0" />
                                    </Decorator.Effect>
                                    <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                    Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" 
                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                    </ContentPresenter>
                                </Decorator>
                            </Decorator>
                        </Decorator>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        <Setter Property="Opacity" Value="0.5"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

If the style is in your window or app resources, then you can apply it like so:

<Label Style="{StaticResource GlassLabelStyle}"

And while I'm at it, I encountered an issue with TextBox's too, where you simply cannot alter the background color when the control is disabled (it just keeps reverting to white) so someone figured out that you have to override the entire template! See (https://stackoverflow.com/a/3752517/88409). So here is a ready-to-use style that will make a text box translucent when disabled (looks great on glass) and will make its background a semi-translucent white with a more visible border when enabled:

<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#01000000" />
<SolidColorBrush x:Key="DisabledBorderBrush" Color="#40000000" />
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#88ffffff" />

<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
    <Setter Property="Background" Value="#88ffffff"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Border Name="Bd" BorderThickness="{TemplateBinding BorderThickness}" 
                                    BorderBrush="{TemplateBinding BorderBrush}" 
                                    Background="{TemplateBinding Background}" 
                                    SnapsToDevicePixels="true">
                    <ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}" 
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Value="{StaticResource DisabledBackgroundBrush}" Property="Background" />
                        <Setter Value="{StaticResource DisabledBorderBrush}" Property="BorderBrush"/>
                        <Setter Value="{StaticResource DisabledForegroundBrush}" Property="Foreground" />
                        <Setter TargetName="PART_ContentHost" Property="Background" Value="{StaticResource DisabledBackgroundBrush}"/>
                        <Setter TargetName="PART_ContentHost" Property="BorderBrush" Value="{StaticResource DisabledBackgroundBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Not the answer you're looking for? Browse other questions tagged or ask your own question.