Пользовательская панель рисования Aero без расширения в клиентскую область - PullRequest
2 голосов
/ 22 февраля 2010

Мое приложение WinForms имеет стандартный внешний вид Aero Glass в Vista / Windows 7.

Я хочу нарисовать строку заголовка окна, чтобы она сохраняла внешний вид стекла Aero с кнопками min / max / close стекла, но без текста заголовка и значка окна. Я попробовал это, переопределив WM_NCPAINT, но переопределение этого события всегда приводит к удалению стекла.

Кто-нибудь знает, как переопределить WM_NCPAINT со стеклом на месте, чтобы эффективно рисовать поверх области стекла?

1 Ответ

8 голосов
/ 10 марта 2010

У меня нет решения, включающего WM_NCPAINT, но у меня есть решение, которое делает то, что вы хотите, и, возможно, чище, чем WM_NCPAINT -версия.

Сначала определите этот класс. Вы будете использовать его типы и функции для достижения желаемой функциональности:

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 );
}

Далее, в своей форме, вы просто делаете это:

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 ) ) );
    }
}

Вот результат:

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

Обычно я делаю базовый класс, который реализует Form со всем моим расширенным поведением, и затем позволяю моим фактическим формам реализовывать этот базовый класс, но если он вам нужен только для одной формы, просто поместите все это туда.

...