【问题标题】:Custom draw Aero title bar without extending into client area自定义绘制 Aero 标题栏而不延伸到客户区
【发布时间】:2010-02-22 04:44:47
【问题描述】:

我的 WinForms 应用程序在 Vista/Windows 7 上具有标准 Aero 玻璃外观。

我想自定义绘制窗口标题栏,使其保留带有玻璃最小/最大/关闭按钮但没有标题文本和窗口图标的 Aero 玻璃外观。我已经通过覆盖 WM_NCPAINT 进行了尝试,但覆盖此事件总是会导致玻璃被移除。

有谁知道如何用玻璃覆盖 WM_NCPAINT 以便有效地正确绘制玻璃区域?

【问题讨论】:

    标签: winforms aero aero-glass


    【解决方案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

    我通常会创建一个基类,用我所有时髦的扩展行为实现 Form,然后让我的实际表单实现该基类,但如果您只需要一个 Form,只需将其全部放在那里。

    【讨论】:

    • 这看起来比简单地清除图标和窗口标题属性要复杂得多。从截图看不出有什么区别。
    • 你看不到窗口图标和标题不见了?它们通常绘制在左上角,以防您不知道。
    • 是的,明白了。如果您在设计器中清除图标和窗口标题属性,它们不会在那里绘制。这个问题关于 WinForms 的,对吧?这就是标签所说的。
    • 我可以发誓我会先尝试,呵呵。无论如何,暂时无法测试您的陈述,我下班时是Linux用户。他的问题是如何“自定义绘制窗口标题栏,使其保留带有玻璃最小/最大/关闭按钮但没有标题文本和窗口图标的 Aero 玻璃外观”。我的解决方案(或者你的,如果你是对的)结合扩展客户区将让你在标题区域自定义绘制任何你想要的东西。
    • 等等,现在我想起来了为什么你要使用我的解决方案而不是你的解决方案:它让你在任务栏中有一个图标和一个标题。如果我没记错的话,您的解决方案将不允许这样做。
    猜你喜欢
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 2016-03-22
    • 1970-01-01
    相关资源
    最近更新 更多