Custom draw Aero title bar without extending into client area
Asked Answered
R

1

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?

Rist answered 22/2, 2010 at 4:44 Comment(0)
B
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.

Bracken answered 10/3, 2010 at 9:13 Comment(6)
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.Didymium
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.Bracken
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.Didymium
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.Bracken
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.Bracken
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...Didymium

© 2022 - 2024 — McMap. All rights reserved.