Click here to Skip to main content
15,891,863 members
Articles / Desktop Programming / WPF
Article

Creating a dynamic drop shadow

Rate me:
Please Sign up or sign in to vote.
4.75/5 (12 votes)
24 May 2012CPOL1 min read 37K   951   26   9
How to create and style a container control that can be used to create completely ridiculous drop shadows on any contained control.

DynamicDropshadow test application

Introduction

This article illustrates how to create and style a container control that can be used to create completely ridiculous drop shadows on any contained control. It also shows the principles of how to create a custom WPF control. The shadows might just bring that extra bit of attention to your application or perhaps ruin it - if used on all controls.

Background

I saw a jQuery example displaying dynamic drop shadows and thought it would look much better in WPF. Therefore I decided to try it out...

The Solution

I have created a single project containing the custom WPF container control. The class MainWindow holds a DependencyProperty MousePosition. All of the container controls bind to this property for updates on the mouse position.

The class diagram:

The class diagram


Using the DynamicDropshadow control:

XML
<Window x:Class="Dk.Nmt.Development.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:my="clr-namespace:Dk.Nmt.Development"
    Title="MainWindow" Height="449" Width="567">
  <Grid>
    <my:DynamicDropshadow Height="131" HorizontalAlignment="Left" Margin="325,63,0,0" 
        x:Name="dynamicDropshadow1" VerticalAlignment="Top" Width="178" 
        MousePosition="{Binding Path=MousePosition, RelativeSource={RelativeSource AncestorType=Window}}">
      <Label>Wrapped control goes here...</Label>
    </my:DynamicDropshadow>
...

The style of the DynamicDropshadow implements a control template that uses a border to place the drop shadow on:

XML
<Style x:Key="DynamicDropshadowStyle" TargetType="{x:Type Development:DynamicDropshadow}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="FontFamily" Value="Tahoma" />
    <Setter Property="FontSize" Value="11px" />
    <Setter Property="Padding" Value="6" />
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type Development:DynamicDropshadow}">
            <Border x:Name="PART_DropShadowBorder" CornerRadius="5" 
                Background="{TemplateBinding Background}">
                <Border.Effect>
                    <DropShadowEffect 
                        Color="{Binding ShadowColor, RelativeSource={RelativeSource TemplatedParent}}" 
                        Opacity="{Binding ShadowOpacity, RelativeSource={RelativeSource TemplatedParent}}"
                        Direction="{Binding Direction, RelativeSource={RelativeSource TemplatedParent}}" 
                        ShadowDepth="{Binding ShadowDepth, RelativeSource={RelativeSource TemplatedParent}}"
                        BlurRadius="{Binding ShadowBlur, RelativeSource={RelativeSource TemplatedParent}}"/> 
                </Border.Effect>
                <ContentPresenter x:Name="PART_DropShadowContent" 
                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
            </Border>
        </ControlTemplate>
    </Setter.Value>
    </Setter>
</Style>

Calculating the dropshadow is done when the mouse is moved. The calculation is done on the basis of the direction and distance to the mouse pointer:

C#
public void CalcDropShadow()
{
    // Get the position to the mouse, relative to the center of the control
    var p = Mouse.GetPosition(this); 
    p.Offset(-Width / 2, -Height / 2);
    // Calculate the angle to the mouse position
    if (p.X > 0 && p.Y < 0)
    Direction = Math.Atan(-p.Y / p.X) * (180f / Math.PI) - 180;
    if (p.X < 0)
    Direction = Math.Atan(-p.Y / p.X) * (180f / Math.PI);
    if (p.X > 0 && p.Y > 0)
    Direction = Math.Atan(-p.Y/p.X)*(180f/Math.PI) + 180;
    // Calculate distance, depth and blur
    double distance = Math.Sqrt(Math.Pow(p.X, 2) + Math.Pow(p.Y, 2));
    ShadowDepth = 1 + .1 * distance;
    ShadowBlur = Math.Max(20 - .1 * distance,5); 
}

I chose to let the shadow become deeper and less blurry with the distance to the mouse.

Points of Interest

Some controls like Calendar apparently lose ClearType when effects are applied to them.

History

This is version 1.0.0.0.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Denmark Denmark
Name: Niel Morgan Thomas
Born: 1970 in Denmark
Education:
Dataengineer from Odense Technical University.
More than 20 years in IT-business.
Current employment:
Cloud architect at University College Lillebaelt

Comments and Discussions

 
GeneralMy vote of 5 Pin
Gary Wheeler29-May-12 1:41
Gary Wheeler29-May-12 1:41 
QuestionCool Pin
BillW3325-May-12 2:56
professionalBillW3325-May-12 2:56 
GeneralAhem... Pin
Vitaly Tomilov24-May-12 15:08
Vitaly Tomilov24-May-12 15:08 
GeneralRe: hmm? Pin
Niel M.Thomas24-May-12 19:12
professionalNiel M.Thomas24-May-12 19:12 
GeneralRe: hmm? Pin
Sacha Barber25-May-12 0:02
Sacha Barber25-May-12 0:02 
GeneralIt was kind of a trick reply - from my side. Pin
Niel M.Thomas25-May-12 1:24
professionalNiel M.Thomas25-May-12 1:24 
GeneralRe: It was kind of a trick reply - from my side. Pin
Sacha Barber25-May-12 2:35
Sacha Barber25-May-12 2:35 
GeneralYes a cube with buttons and a single combobox. Pin
Niel M.Thomas25-May-12 3:41
professionalNiel M.Thomas25-May-12 3:41 
GeneralMy vote of 5 Pin
Karl Sanford24-May-12 12:19
professionalKarl Sanford24-May-12 12:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.