Create custom UI appearance for WinForms Form with Shadow - part 6

July 31st, 2008 by ganton | Print

In my previous post I presented a how to use Win32 API functions and structures in order to create a Layered Form using a custom png image file.

(All posts in this series: Post 1, Post 2, Post 3, Post 4, Post 5, Post 6, Source Code)

Today, I plan to explain how to use LayeredForm class in order to create a shadow. The shadow is a separated class named ShadowedForm which inherits LayeredForm. It sets its IsTransparent property to true in order to be transparent for mouse events. This way the shadow becomes clickable like windows vista windows. Below is the class implementation.

[sourcecode language="csharp"]

public class ShadowedForm : LayeredForm
{
private Bitmap _shadowBitmap;
private Point _shadowOffset;

public ShadowedForm(Bitmap bitmap, Point offset)
: base()
{
_shadowBitmap = bitmap;
_shadowOffset = offset;
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
SetBitmap(_shadowBitmap);
Left = Owner.Left + _shadowOffset.X;
Top = Owner.Top + _shadowOffset.Y;
}
}

[/sourcecode]

It is a very simple cass which constructor accepts a bitmap of the shadow to draw and a shadow offset. We need shadow offset because we will use two png image files in order to create a layered form with shadow. For this purpose I’ve created a form with shadow using Photoshop and after that I’ve separated the form from the shadow. The png files are not very good but I’m not a designer and I found them quite good for my sample.

Now we are ready to create our form with shadow. The next step is to create a new form named TestShadowedWindowForm. It is quite similar to TestLayeredWindowForm from my previous post. It also contains events for closing it and for moving it. The first difference is that it also re-estimates shadow location in order to move both forms together. The second difference is the load event handler where intantiation and showing of shadow form is added. Below is its implementation

[sourcecode language="csharp"]

public partial class TestShadowedWindowForm : LayeredForm
{
private ShadowedForm _shadow;
private Point _startPoint = Point.Empty;

public TestShadowedWindowForm()
{
InitializeComponent();
Left = 100;
Top = 100;
}

private void TestShadowedWindowForm_Load(object sender, EventArgs e)
{
// Set bitmap of the main window
string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
Bitmap bitmap = (Bitmap)Bitmap.FromFile(directory + “\\window.png”);
SetBitmap(bitmap);

// Set bitmap of the shadow window
// and show it
_shadow = new ShadowedForm((Bitmap)Bitmap.FromFile(directory + “\\shadow.png”), new Point(-2, -2));
_shadow.IsTransparent = true;
// it is a must to provide current form to show it because shadowed form uses its Owner property
_shadow.Show(this);
}

private void TestShadowedWindowForm_MouseDown(object sender, MouseEventArgs e)
{
// store started point into private variable in order to use it in mouse move event handler
if (e.Button == MouseButtons.Left)
{
_startPoint = new Point(e.X, e.Y);
}
}

private void TestShadowedWindowForm_MouseMove(object sender, MouseEventArgs e)
{
// if the left button is clicked and it is still held move the form and its shadow
if (e.Button == MouseButtons.Left)
{
Top += e.Y - _startPoint.Y;
Left += e.X - _startPoint.X;
_shadow.Top += e.Y - _startPoint.Y;
_shadow.Left += e.X - _startPoint.X;
}
}

private void TestShadowedWindowForm_MouseDoubleClick(object sender, MouseEventArgs e)
{
// if left mouse button is double clicked the form is closed
if (e.Button == MouseButtons.Left)
{
Close();
}
}
}

[/sourcecode]

To start the sample download its code from source code link in the beginning of the post. Then build the solution and start the application. Press [show form with shadow] button and the form will be opened.

The result of application execution is present at the picture below.

Bigger image at the left presents the form when no mouse over the shadow. The smaller image presents the form when there is a mouse placed over the shadow where Visual Studio short cut is placed. You can not see the mouse pointer but you can trust me that it is the effect.

Leave a Reply