Aero white glow in WPF? - wpf

How do I add the Aero white glow behind a control in WPF?
I mean the glow like in a window's caption bar in Vista/7.

This unrelated question seems to have the answer...
Outer bevel effect on text in WPF
I just needed a rectangle behind my text block...
<Rectangle Height="{Binding ElementName=textBlock1, Path=ActualHeight}" HorizontalAlignment="{Binding ElementName=textBlock1, Path=HorizontalAlignment}" Margin="{Binding ElementName=textBlock1, Path=Margin}" VerticalAlignment="{Binding ElementName=textBlock1, Path=VerticalAlignment}" Width="{Binding ElementName=textBlock1, Path=ActualWidth}" Fill="White" Opacity="0.5">
<Rectangle.Stroke>
<SolidColorBrush />
</Rectangle.Stroke>
<Rectangle.Effect>
<BlurEffect Radius="10" KernelType="Gaussian" />
</Rectangle.Effect>
</Rectangle>
This is gonna do the trick for any control when you replace all the "textBlock"s in the code!
And it looks exactly the same as the aero glow!

Does this help? The effect can be quite subtle but it does look alright.
I tried messing about with Pixel Shaders in WPF using Shazzam but it was a lot of work to achieve the same effect or better. They use a lot of "under the hood" stuff (such as double-pass shaders) of which the techniques aren't available to the WPF api.

Related

WPF - Size rectangle by its ImageBrush opacity mask

I have a rectangle which has an ImageBrush opacity mask (basically a coloured icon).
This is my current code:
<Rectangle Fill="Black">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="/Path/To/Icon.png"/>
</Rectangle.OpacityMask>
</Rectangle>
This produces no result without setting a fixed width and height for the rectangle. Is it possible to size the rectangle according to the ImageBrush image size?
Thanks for your help. Sorry if this is a silly question, I am still learning WPF.
Edit: To clarify, what I am trying to achieve is for the rectangle to behave same as this:
<Image Source="/Path/To/Icon.png"/>
It should be sized according to the dimensions of the image source file.
Stretch="None" keep image size. Rectangle with binding ActualWidth and ActualHeight resize from ImageBrush size. Result is same if we don't use both. On both case rectangle resize to true ImageBrush size. Hope I understand your problem.
<Rectangle Fill="Black" Width="{Binding ActualWidth, ElementName=image}" Height="{Binding ActualHeight, ElementName=image}">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="/Path/To/Icon.png" x:Name="image" Stretch="None">
</ImageBrush>
</Rectangle.OpacityMask>
</Rectangle>
<Rectangle Width="{Binding ActualWidth, ElementName=image}" Height="{Binding ActualHeight, ElementName=image}">
<Rectangle.Fill>
<ImageBrush ImageSource="C:\Users\neeraj\Pictures\Img1.jpg" x:Name="image" Stretch="None">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
Try this snippet. I am not sure why you wanted the fill black. If idea was to have a Black surrounding, use Background="Black" on the outer Grid.

Clipping behaviour on custom BorderBrush

I have a simple rounded border with a solid brush:
<Border BorderThickness="2,0,2,0" CornerRadius="10,10,10,10" BorderBrush="Green"/>
Looks as I expect. Now, I want the border to have a dashed stroke:
<Border BorderThickness="2,0,2,0" CornerRadius="10,10,10,10">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeThickness="1" Stroke="Green" StrokeDashArray="1 2"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"
StrokeDashCap="Square"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
</Border>
That somehow clips the border in a weird way I can't understand. I thought it would be the way the brush is painted, but I can't make out any pattern. There should be no clipping with the inner content of the border (the red thing you can partly see) as it looks doesn't clip in that way in any other case.
If I set the StrokeThickness a bit higher, I looks more acceptable:
<Border BorderThickness="2,0,2,0" CornerRadius="10,10,10,10">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle StrokeThickness="4" Stroke="Green" StrokeDashArray="1 2"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"
StrokeDashCap="Square"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
</Border>
Can someone explain why that looks so strange? The appearance also changes if I set a different width or height for the rectangle - also in a way I don't understand. The position of the strokes and gaps changes, but not in a way I can make sense of it.
It's because you're doing it via a brush. What you see would actually be expected.
#Clemens actually helped me with an explanation to an issue I had some time ago by being kind enough to show some Doc snippets.
A Brush "paints" or "fills" an area with its output. Different brushes have different types of output. Some brushes paint an area with a solid color, others with a gradient, pattern, image, or drawing.
•VisualBrush: Paints an area with a Visual object. A VisualBrush enables you to duplicate content from one portion of your application into another area; it's very useful for creating reflection effects and magnifying portions of the screen.
So the are being "painted" is determined by the area it's allowed, in this case from the parent panel providing the area within it's BorderBrush so we see a predictable pattern provided by the parent.
Hope this helps, cheers.

WPF zoom canvas and maintain scroll position

I have a Canvas element, contained within a ScrollViewer, which I'm zooming using ScaleTransform. However, I want to be able to keep the scroll position of the viewer focused on the same part of the canvas after the zoom operation has finished. Currently when I zoom the canvas the scroll position of the viewer stays where it was and the place the user was viewing is lost.
I'm still learning WPF, and I've been going backwards and forwards a bit on this, but I can't figure out a nice XAML based way to accomplish what I want. Any help in this matter would be greatly appreciated and would aid me in my learning process.
Here is the kind of code I'm using...
<Grid>
<ScrollViewer Name="TrackScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas Width="2560" Height="2560" Name="TrackCanvas">
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ElementName=ZoomSlider, Path=Value}"
ScaleY="{Binding ElementName=ZoomSlider, Path=Value}"/>
</Canvas.LayoutTransform>
<!-- Some complex geometry describing a motor racing circuit -->
</Canvas>
</ScrollViewer>
<StackPanel Orientation="Horizontal" Margin="8" VerticalAlignment="Top" HorizontalAlignment="Left">
<Slider Name="ZoomSlider" Width="80" Minimum="0.1" Maximum="10" Value="1"/>
<TextBlock Margin="4,0,0,0" VerticalAlignment="Center" Text="{Binding ElementName=ZoomSlider, Path=Value, StringFormat=F1}"/>
</StackPanel>
</Grid>
This is not a purely XAML way of doing it, but there is a very nice piece of work on Joeyw's blog titled Pan and Zoom (DeepZoom style) in WPF with links to the source. He has taken some inspiration from DeepZoom and it gives you smooth/animated panning and zooming of content. And if you're using WPF 4 you could probably modify it a little to add some easing functions to the animations to give it an even nicer feel.

How to prevent the Visual Brush from stretching its content

In my project I want to display a small logo on the side of a custom control. Since I have no canvas I thought maybe a Visual Brush would be a good Idea to place the logo in the background.
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Width="200" Height="200" Fill="Red" />
</VisualBrush.Visual>
</VisualBrush>
But the Rectangle I am using right now is not 200x200. It takes the complete available space. Thats not what I want. I also tried a Viewbox and set the stretch property but the result is the same because in the end I don't need a simple Rectangle but a canvas with many path objects as children. A Viewbox supports only one child.
This there any way to get around this problem?
You need to set TileMode, Stretch, AlignmentX and AlignmentY properties on your VisualBrush:
<VisualBrush TileMode="None" Stretch="None" AlignmentX="Left" AlignmentY="Top">
<VisualBrush.Visual>
<Rectangle Height="200" Width="200" Fill="Red"></Rectangle>
</VisualBrush.Visual>
</VisualBrush>
Add Grid and this Set Vertical alligment to Top and Horizontal alignment to Right
Sample code
<VisualBrush x:Key="myVisual">
<VisualBrush.Visual>
<Grid>
<Rectangle Height="200" Width="200" Fill="Red" HorizontalAlignment="Right" VerticalAlignment="Top" ></Rectangle>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
For me, I set the following attribute on the VisualBrush, and the VisualBrush now looks exactly like a MediaElement:
Stretch="Uniform"

blurred opacity

I need to create a transparent blurred background. Lets suppose I have a border with a white blurry transparent background. Everything that is behind the border is blurred.
I'm trying to avoid dependencies; I'm currently using .NET 3.0, and want it to run with XP too.
Mockup image:
A VisualBrush can be used to get close to what you want, but has some limitations.
As long as you only need the glass effect within the window (and not be an effect over other windows) and that the placement of the glass effect border is controlled tightly then you could you something like this:-
<Grid>
<Border x:Name="src" Background="Silver">
<Label HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50">Hello World</Label>
</Border>
<Border Background="White" Margin="40" >
<Border Opacity="0.5" >
<Border.Effect>
<BlurEffect Radius="10"/>
</Border.Effect>
<Border.Background>
<VisualBrush Visual="{Binding ElementName=src}" Stretch="None" />
</Border.Background>
</Border>
</Border>
</Grid>
I don't think that a child element within the visual tree is able to get the VisualBrush of it's parent so this might be a limitation for you. (i.e. the glass panel cannot be contained by the background panel)
I've used VisualBrushes many times usually with TranslateTransforms to move them around a bit to get the right image in the right place.
Update:
Altered XAML to use Effect and not BitmapEffect that is slower and now depreciated as mentioned in the comments below by Steven Robbins.
I would imagine you will need use an Effect for this, applied to a background rectangle or grid.
There's a decent library of effects here if that floats your boat.
Use Vista glass.

Resources