Click here to Skip to main content
13,344,016 members (99,460 online)
Click here to Skip to main content
Add your own
alternative version


120 bookmarked
Posted 19 Jun 2007

Transparent drop shadow in C# (GDI+)

, 3 Jul 2007
Rate this:
Please Sign up or sign in to vote.
How to create a transparent drop shadow effect for a panel control

Screenshot - dropshadow.png


For a project I'm working on, I had to create transparent fuzzy drop shadows similar to those found in various Windows applications. Want to have them too? Then read on! Or just download the sources...


Unfortunately, there's no support at all for these drop shadows in Visual Studio 2005/WinForms, but there is in WPF! Fortunately, I only needed panels with shadows and shadows for rectangular shapes are easy. I just took the method I use for web pages and applied it to WinForms. The trick is as follows: Using strategically placed and tiled pictures of a shadow, we can simulate a shadow effect. When transparent PNGs are used, it looks just like the real thing. The image parts we need are outlined in red below:

Screenshot - shadow4.png

Normally, I'd start with creating these images. Luckily for you, I've already done it and have provided them with the source. Now it's time to start coding!

The project

Go to File > New > Project and select Class Library. Call it ShadowPanel and click OK. Now rename class1.cs to ShadowPanel.cs. That's the file we'll work with. It's always handy to create a test project. So, right click the solution in the solution explorer and select Add > New Project. Pick Windows Application this time and call it ShadowPanelTest.


First, we need some properties. It would be nice to provide at least a border and a background color. So, it's time to open ShadowPanel.cs and add the following:

using System;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;         

namespace ShadowPanel
    public class ShadowPanel : Panel
        private Color _panelColor;         

        public Color PanelColor
            get { return _panelColor; }
            set { _panelColor = value; }

        private Color _borderColor;         

        public Color BorderColor
            get { return _borderColor; }
            set { _borderColor = value; }

We can't use the original panel BackgroundColor property because that's for the entire panel, including the shadow area! So, I created a PanelColor property that defines the color for the area inside the shadow. About those references to System.Drawing and System.Drawing.Drawing2D: You might have to add them manually by right-clicking on References in the Solution Explorer and selecting them in the list.


Now for the images that we can use to actually draw the shadow. You can download them with the sources if you didn't do this already. Create a folder in the project called Images and add the tshadowXXXX.png files. Select them in the solution explorer and change the Build Action to Embedded Resource. That way, the files will be compiled into the DLL and you won't need to distribute them with your application.

I added the images as static in the code; kudos go to Remco Schrijvers for proposing this. I also added two private members to describe the size of the images -- they are 5×5 pixel images -- and the offset (margin) of the shadow from the left and top. Please add the following code to the ShadowPanel class:

private int shadowSize = 5;
private int shadowMargin = 2;

// static for good performance
static Image shadowDownRight =
    new Bitmap(typeof(ShadowPanel), "Images.tshadowdownright.png");
static Image shadowDownLeft =
    new Bitmap(typeof(ShadowPanel), "Images.tshadowdownleft.png");
static Image shadowDown =
    new Bitmap(typeof(ShadowPanel), "Images.tshadowdown.png");
static Image shadowRight =
    new Bitmap(typeof(ShadowPanel), "Images.tshadowright.png");
static Image shadowTopRight =
    new Bitmap(typeof(ShadowPanel), "Images.tshadowtopright.png");


Everything is now prepared for us to do the cool stuff: Creating GDI+ drawing code! Let's override the OnPaint method of the Panel base class.

protected override void OnPaint(PaintEventArgs e)

    // Get the graphics object. We need something to draw with
    Graphics g = e.Graphics;

First, we'll do the tiled images on the bottom and the right:

Screenshot - shadow1.png

I think the code says it all. Just add the following after Graphics.g = e.Graphics;:

// Create tiled brushes for the shadow on the
// right and at the bottom.
TextureBrush shadowRightBrush =
    new TextureBrush(shadowRight, WrapMode.Tile);
TextureBrush shadowDownBrush =
    new TextureBrush(shadowDown, WrapMode.Tile);

// Translate (move) the brushes so the top or
// left of the image matches the top or left of the
// area where it's drawed. If you don't understand why
// this is necessary, comment it out.
// Hint: The tiling would start at 0,0 of the control, so
// the shadows will be offset a little.
shadowDownBrush.TranslateTransform(0, Height - shadowSize);
shadowRightBrush.TranslateTransform(Width - shadowSize, 0);

// Define the rectangles that will be filled with the brush.
// (where the shadow is drawn)
Rectangle shadowDownRectangle = new Rectangle(
    shadowSize + shadowMargin,              // X
    Height - shadowSize,                    // Y
    Width - (shadowSize * 2 + shadowMargin),// width (stretches)
    shadowSize                              // height

Rectangle shadowRightRectangle = new Rectangle(
    Width - shadowSize,                      // X
    shadowSize + shadowMargin,               // Y
    shadowSize,                              // width
    Height - (shadowSize * 2 + shadowMargin) // height (stretches)

// And draw the shadow on the right and at the bottom.
g.FillRectangle(shadowDownBrush, shadowDownRectangle);
g.FillRectangle(shadowRightBrush, shadowRightRectangle);

You can add ShadowPanel to the test project by opening the Form1.cs designer. If you build the project once, ShadowPanel should appear in the toolbox. Just drag it to the form and run it. You'll hopefully get the following result:

Screenshot - shadow2.png

By the way: I set my form's background color to white, so it might look different for you.

Bring in the corners

To draw the small bitmaps in the corners, just add the following:

// Now for the corners, draw the 3 5×5 pixel images.
g.DrawImage(shadowTopRight, new Rectangle(Width - shadowSize,
    shadowMargin, shadowSize, shadowSize));
g.DrawImage(shadowDownRight, new Rectangle(Width - shadowSize,
    Height - shadowSize, shadowSize, shadowSize));
g.DrawImage(shadowDownLeft, new Rectangle(shadowMargin,
    Height - shadowSize, shadowSize, shadowSize));

It's almost too easy.

Filling and bordering

We already have the PanelColor and BorderColor properties. Now it's time to put them to use.

// Fill the area inside with the color in the PanelColor property.
// 1 pixel is added to everything to make the rectangle smaller.
// This is because the 1 pixel border is actually
// drawn outside the rectangle.
Rectangle fullRectangle = new Rectangle(
    1,                                              // X
    1,                                              // Y
    Width - (shadowSize + 2),                       // Width
    Height - (shadowSize + 2)                       // Height

if (PanelColor != null)
    SolidBrush bgBrush = new SolidBrush(_panelColor);
    g.FillRectangle(bgBrush, fullRectangle);

// Draw a nice 1 pixel border it a BorderColor is specified
if (_borderColor != null)
    Pen borderPen = new Pen(BorderColor);
    g.DrawRectangle(borderPen, fullRectangle);

Time to check our results so far:

Screenshot - shadow3.png

Well, that's about it. We're almost done.

Finishing up

As a formality, end the OnPaint method with:

    // Memory efficiency

    shadowDownBrush = null;
    shadowRightBrush = null;

To make sure the control repaints correctly when resized, we need to override the OnResize method. Thanks, BobishKindaGuy!

        // Correct resizing
        protected override void OnResize(EventArgs e)


Points of interest

Of course, I won't stop you from adding more functionality. Please do! Also, let me know if you appreciated this tutorial!


  • June 17th, 2007 - First version
  • June 30th, 2007 - Added OnResize


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Mark de Haan
Web Developer
Netherlands Netherlands
I'm a UI designer living in The Netherlands. Currently I'm using C# and Visual Studio 2005 with ASP.NET and Windows Forms.

I'm looking forward to working with WPF professionally (expression blend is just fantastic!)

You may also be interested in...

Comments and Discussions

GeneralMy vote of 1 Pin
xcvsdfsdf9-Feb-09 21:06
memberxcvsdfsdf9-Feb-09 21:06 
GeneralApply Transparent Drop Shadow to a WinForm Pin
Member 98222311-Feb-08 5:43
memberMember 98222311-Feb-08 5:43 
GeneralRe: Apply Transparent Drop Shadow to a WinForm Pin
iorchwaters21-Aug-09 16:27
memberiorchwaters21-Aug-09 16:27 
QuestionCustomize Shadow Size... Pin
claudiocas10-Aug-07 10:45
memberclaudiocas10-Aug-07 10:45 
AnswerRe: Customize Shadow Size... Pin
Mark de Haan11-Sep-07 13:22
memberMark de Haan11-Sep-07 13:22 
Generalcool gradient panel Pin
OwfAdmin5-Aug-07 10:30
memberOwfAdmin5-Aug-07 10:30 
Generalwell done! Pin
blue.pan@163.com24-Jul-07 23:02
memberblue.pan@163.com24-Jul-07 23:02 
GeneralNicely Done Pin
Paul Conrad15-Jul-07 8:50
memberPaul Conrad15-Jul-07 8:50 
GeneralAnother solution Pin
nguyenthanhtungtinbk5-Jul-07 15:31
membernguyenthanhtungtinbk5-Jul-07 15:31 
GeneralShadow in Web Application Pin
Jay Khanpara28-Jun-07 20:03
memberJay Khanpara28-Jun-07 20:03 
GeneralRe: Shadow in Web Application Pin
Mark de Haan30-Jun-07 13:04
memberMark de Haan30-Jun-07 13:04 
GeneralRe: Shadow in Web Application Pin
Pascal Ganaye18-Jul-07 6:28
memberPascal Ganaye18-Jul-07 6:28 
GeneralExcellent article! Pin
MangeA26-Jun-07 18:38
memberMangeA26-Jun-07 18:38 
GeneralRun-time resizing problem Pin
iro197722-Jun-07 23:17
memberiro197722-Jun-07 23:17 
GeneralRe: Run-time resizing problem Pin
xfUSiONx26-Jun-07 3:26
memberxfUSiONx26-Jun-07 3:26 
GeneralRe: Run-time resizing problem [modified] Pin
BobishKindaGuy26-Jun-07 8:52
memberBobishKindaGuy26-Jun-07 8:52 
GeneralRe: Run-time resizing problem [modified] Pin
Mark de Haan30-Jun-07 12:53
memberMark de Haan30-Jun-07 12:53 
AnswerRe: Run-time resizing problem Pin
Thomas Freudenberg5-Jul-07 4:58
memberThomas Freudenberg5-Jul-07 4:58 
GeneralSimilar Control Pin
Prasad Khandekar19-Jun-07 22:37
memberPrasad Khandekar19-Jun-07 22:37 
Generalvery nice article Pin
vito_19-Jun-07 12:30
membervito_19-Jun-07 12:30 
GeneralRe: very nice article Pin
Mark de Haan20-Jun-07 0:39
memberMark de Haan20-Jun-07 0:39 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.180111.1 | Last Updated 3 Jul 2007
Article Copyright 2007 by Mark de Haan
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid