2

My WinForms application has the standard Aero glass appearance on Vista/Windows 7.

I want to custom draw the window title bar so it retains the Aero glass appearance with the glass min/max/close buttons but without the title text and window icon. I have tried this by overriding WM_NCPAINT but overriding this event always causes the glass to be removed.

Does anyone know how to override WM_NCPAINT with glass in place in order to effectively draw over the glass area correctly?

Phil Wright
  • 22,580
  • 14
  • 83
  • 137

1 Answers1

8

I don't have a solution involving WM_NCPAINT, but I have a solution that does what you want it to do, and perhaps cleaner than the WM_NCPAINT-version would be.

First define this class. You'll use its types and functions to achieve your desired functionality:

internal class NonClientRegionAPI
{
    [DllImport( "DwmApi.dll" )]
    public static extern void DwmIsCompositionEnabled( ref bool pfEnabled );

    [StructLayout( LayoutKind.Sequential )]
    public struct WTA_OPTIONS
    {
        public WTNCA dwFlags;
        public WTNCA dwMask;
    }

    [Flags]
    public enum WTNCA : uint
    {
        NODRAWCAPTION = 1,
        NODRAWICON = 2,
        NOSYSMENU = 4,
        NOMIRRORHELP = 8,
        VALIDBITS = NODRAWCAPTION | NODRAWICON | NOSYSMENU | NOMIRRORHELP
    }

    public enum WINDOWTHEMEATTRIBUTETYPE : uint
    {
        /// <summary>Non-client area window attributes will be set.</summary>
        WTA_NONCLIENT = 1,
    }

    [DllImport( "uxtheme.dll" )]
    public static extern int SetWindowThemeAttribute(
        IntPtr hWnd,
        WINDOWTHEMEATTRIBUTETYPE wtype,
        ref WTA_OPTIONS attributes,
        uint size );
}

Next, in your form, you simply do this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // Set your options. We want no icon and no caption.
        SetWindowThemeAttributes( NonClientRegionAPI.WTNCA.NODRAWCAPTION | NonClientRegionAPI.WTNCA.NODRAWICON );
    }

    private void SetWindowThemeAttributes( NonClientRegionAPI.WTNCA attributes )
    {
        // This tests that the OS will support what we want to do. Will be false on Windows XP and earlier,
        // as well as on Vista and 7 with Aero Glass disabled.
        bool hasComposition = false;
        NonClientRegionAPI.DwmIsCompositionEnabled( ref hasComposition );
        if( !hasComposition )
            return;

        NonClientRegionAPI.WTA_OPTIONS options = new NonClientRegionAPI.WTA_OPTIONS();
        options.dwFlags = attributes;
        options.dwMask = NonClientRegionAPI.WTNCA.VALIDBITS;

        // The SetWindowThemeAttribute API call takes care of everything
        NonClientRegionAPI.SetWindowThemeAttribute(
            this.Handle,
            NonClientRegionAPI.WINDOWTHEMEATTRIBUTETYPE.WTA_NONCLIENT,
            ref options,
            (uint)Marshal.SizeOf( typeof( NonClientRegionAPI.WTA_OPTIONS ) ) );
    }
}

Here's the result:

http://img708.imageshack.us/img708/1972/noiconnocaptionform.png

I normally make a base class that implements Form with all my funky extended behavior and then let my actual forms implement that base class, but if you only need it for one Form, just put it all in there.

Alex
  • 3,429
  • 4
  • 36
  • 66
  • This looks far more complicated than simply clearing the icon and the window title properties. From the screenshot, I can't tell what the difference is. – Cody Gray - on strike Mar 26 '11 at 10:19
  • You can't see that the window icon and title are gone? They are normally drawn in the upper-left corner, in case you were unaware. – Alex Mar 26 '11 at 16:01
  • Yup, got that. They're *also* not drawn there if you clear the icon and window title properties in the designer. This question *is* about WinForms, right? That's what the tags say. – Cody Gray - on strike Mar 26 '11 at 16:02
  • I could've sworn I would've tried that first, heh. In any case, can't test your statement at the moment, I'm a Linux user when I'm off work. His question was how to "custom draw the window title bar so it retains the Aero glass appearance with the glass min/max/close buttons but without the title text and window icon". My solution (or yours, given you're right) combined with extending the client area will let you custom draw whatever you want in the title region. – Alex Mar 26 '11 at 16:12
  • 1
    Wait, now I remember why you would want to use my solution instead of yours: It lets you have an icon and a title in the task bar. If I recall correctly, your solution won't allow for that. – Alex Mar 26 '11 at 16:14
  • Sure, sure. My point wasn't that your suggestions or code was wrong. I only stumbled across this question because I spent the day writing code to handle `WM_NCPAINT` and `WM_NCHITTEST` myself. I was merely observing that, from what I could tell, there was a far simpler way to achieve the effect shown in the screenshot. Windows won't draw caption text or an icon if you don't tell it to. As for *custom* drawing in the frame, well, it *does* get more complicated... – Cody Gray - on strike Mar 26 '11 at 16:15