Click here to Skip to main content
Click here to Skip to main content

Creating a dynamic drop shadow

By , 24 May 2012
 

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:

<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:

<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:

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)

About the Author

Niel M.Thomas
Software Developer (Senior)
Denmark Denmark
Member
Name: Niel Morgan Thomas
Born: 1970 in Denmark
Education:
Dataengineer from Odense Technical University.
More than 15 years in IT-business.
Current employment:
Working with application development in a major Danish company that produce medical equipment.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberGary Wheeler29 May '12 - 1:41 
QuestionCoolmemberCIDev25 May '12 - 2:56 
GeneralAhem...memberVitaly Tomilov24 May '12 - 15:08 
GeneralRe: hmm?memberNiel M.Thomas24 May '12 - 19:12 
GeneralRe: hmm?mvpSacha Barber25 May '12 - 0:02 
GeneralIt was kind of a trick reply - from my side.memberNiel M.Thomas25 May '12 - 1:24 
GeneralRe: It was kind of a trick reply - from my side.mvpSacha Barber25 May '12 - 2:35 
GeneralYes a cube with buttons and a single combobox.memberNiel M.Thomas25 May '12 - 3:41 
GeneralMy vote of 5memberKarl Sanford24 May '12 - 12:19 

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 24 May 2012
Article Copyright 2012 by Niel M.Thomas
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid