alacrity in action
| Tags: , , ,

Ever since I started writing windows applications, even though most of them were not in C or C++, almost every time I would refer back to Charles Petzold’s Programming Windows. Whether it was Visual Basic, Delphi, .NET or even Java, there would eventually come a point, where the only way to achieve something would be to dig into the Win32 API and hook into the message loop directly.

I don’t know why I thought writing a WPF application in .NET 4 for Windows 7 would be any different.

If you start with a default empty window it is rendered nicely with a drop shadow around it (like all other windows).

However, I wanted to achieve an alternative layout, without the frame but with the shadow still on. Unfortunately setting WindowStyle="None" creates a rather blunt rectangle.

There is always the option to do something inside the client window to pretend your window actually does have a shadow but it is somewhat messy and just not as pretty (or perhaps I wasn’t ready to tinker with the Canvas and Effects enough). So will say it also comes with a performance penalty (since you would require transparent background).

Finally, with a little bit of Interop spice by calling Desktop Window Manager APIs I got the desired effect:

Mind you it only works if DWM is available (that is in Vista and Windows7) but I’m fine with that.

Here is the required code:

[DllImport("dwmapi.dll", PreserveSig = true)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);

[DllImport("dwmapi.dll")]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset);

void ShellWindow_SourceInitialized(object sender, EventArgs e)
{
var helper = new WindowInteropHelper(this);
int val = 2;
DwmSetWindowAttribute(helper.Handle, 2, ref val, 4);
var m = new Margins
{
bottomHeight = -1,
leftWidth = -1,
rightWidth = -1,
topHeight = -1
};

DwmExtendFrameIntoClientArea(helper.Handle, ref m);
}

If you want to dig deeper there is WPF Shell Integration Library that does some of this heavy lifting for you.

P.S. Seems like Java folks have similar challenges.


Comments7

  1. Would you mind posting an example project for this?

  2. Does this method work on C? I tried but failed…

    HRESULT EnableShadow(HWND hWnd)
    {
    int val = DWMNCRP_ENABLED;
    DwmSetWindowAttribute(hWnd, 2, &val, 4);
    MARGINS m;
    m.cxLeftWidth = -1;
    m.cxRightWidth = -1;
    m.cyBottomHeight = -1;
    m.cyTopHeight = -1;
    return DwmExtendFrameIntoClientArea(hWnd, &m);
    }

  3. Well, I made it at last…
    Modify the window style after the function will do the good…
    thanks a lot!

  4. Here is an alternative solution that can be completed in XAML only. No code 🙂

    http://stackoverflow.com/questions/7369115/maximum-custom-window-loses-drop-shadow-effect

  5. in c++ i tried , din’t work.
    int val = DWMNCRP_ENABLED;
    DwmSetWindowAttribute(hwnd, 2, &val, 4);
    MARGINS m;
    m.cxLeftWidth = 0;
    m.cxRightWidth = 0;
    m.cyBottomHeight = 0;
    m.cyTopHeight = 0;
    return DwmExtendFrameIntoClientArea(hwnd, &m);
    which window style we need to modify.

  6. HI

    CAN WE ACHEIVE THIS RESULT IN EXCEL USERFORMS ALSO WITH VBA.
    PLS HELP !!!
    I HAVE A BORDERLESS USERFORM TO WHICH I INTEND TO GIVE A DROP SHADOW EFFECT.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.