Пользовательская панель заголовка Draw Aero без расширения в клиентскую область

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

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

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


person Phil Wright    schedule 22.02.2010    source источник


Ответы (1)


У меня нет решения с 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

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

person Alex    schedule 10.03.2010
comment
Это выглядит намного сложнее, чем просто очистить значок и свойства заголовка окна. По скриншоту не могу сказать, в чем разница. - person Cody Gray; 26.03.2011
comment
Вы не видите, что значок и заголовок окна исчезли? Обычно они рисуются в верхнем левом углу, на случай, если вы не заметили. - person Alex; 26.03.2011
comment
Ага, понял. Они также не отображаются там, если вы очистите свойства значка и заголовка окна в дизайнере. Этот вопрос касается WinForms, верно? Так написано на бирках. - person Cody Gray; 26.03.2011
comment
Я мог бы поклясться, что сначала попробовал бы это, хех. В любом случае, пока не могу проверить ваше утверждение, я пользуюсь Linux, когда не работаю. Его вопрос заключался в том, как настроить отображение строки заголовка окна, чтобы она сохраняла внешний вид стекла Aero с кнопками минимального / максимального / закрытого окна, но без текста заголовка и значка окна. Мое решение (или ваше, если вы правы) в сочетании с расширением клиентской области позволит вам рисовать все, что вы хотите, в области заголовка. - person Alex; 26.03.2011
comment
Подождите, теперь я вспомнил, почему вы хотите использовать мое решение вместо своего: оно позволяет иметь значок и заголовок на панели задач. Если я правильно помню, ваше решение этого не допускает. - person Alex; 26.03.2011
comment
Конечно конечно. Я не хотел сказать, что ваши предложения или код были неправильными. Я наткнулся на этот вопрос только потому, что весь день писал код для обработки WM_NCPAINT и WM_NCHITTEST самостоятельно. Я просто заметил, что, насколько я могу судить, существует гораздо более простой способ добиться эффекта, показанного на скриншоте. Windows не будет рисовать текст заголовка или значок, если вы этого не скажете. Что касается нестандартного рисования во фрейме, то он действительно усложняется ... - person Cody Gray; 26.03.2011