如何强制 Aero 绘制无边框窗口,就好像它处于活动状态一样,即使它不是?

Posted

技术标签:

【中文标题】如何强制 Aero 绘制无边框窗口,就好像它处于活动状态一样,即使它不是?【英文标题】:How can I force Aero to draw a borderless window as if it were active, even if it's not? 【发布时间】:2011-12-29 08:13:15 【问题描述】:

我想要和 windows 7 任务栏一样的效果。 我看过这个问题: Keep Window Looking Active 它工作得很好,但前提是窗口有非客户区。

我的窗口是无边框的,无论我做什么,它的内容(只是黑色背景)都会呈现为非活动状态。

我已将我的窗口标志设置为 Windows 7 任务栏,但它没有帮助。

我目前唯一的想法是用边框绘制它并剪掉它们,有没有更好的方法来实现我想要的?

编辑 1: 裁剪不起作用,裁剪边框后,窗口内容被呈现为非活动窗口。 那么 Windows 7 任务栏到底是如何工作的呢?

EDIT2: 添加一些照片更好地解释自己,以下窗口内容是黑色背景。

这是一个非活动窗口(内容呈现有点暗):

这是一个活动窗口:

如果窗口没有客户区,则内容始终呈现为非活动窗口,但是 Windows 任务栏始终呈现为活动窗口并且它没有任何 NC 区域(至少根据 spy++)。这就是我想要模仿的。

EDIT3: 分享我最近的发现。 explorer.exe 主窗口是无框架的,并具有以下标志:

我深入研究了资源管理器的进程 dwmapi.dll 导出函数:

它使用 DwmEnableBlurBehindWindow,就像我一样。 我检查了未记录的序数函数,它们都与将航空玻璃渲染为活动状态有关。

会不会是 DWM 规则不适用于资源管理器?

【问题讨论】:

您如何注意到无边框窗口处于非活动状态? 添加了一些照片以更清晰。 我在最后一段中写道“如果窗口没有客户区,则内容总是呈现为非活动窗口”,无边框窗口看起来就像非活动窗口,即使它是活动的。 @Omer,既然你想模仿任务栏,我想你的窗口有WS_EX_TOPMOSTWS_EX_TOOLWINDOW 样式?当您依赖WM_NCACTIVATE 技巧时,您是否致电DwmExtendFrameIntoClientArea() 将玻璃扩展到您的客户区域? @Omer:你说过你想做,但你没有说为什么。您似乎正在努力颠覆 Windows 的设计工作方式。是什么让您的应用(或至少该窗口)如此特别,以至于用户无法一眼看出它是否处于活动状态? 【参考方案1】:

棘手的一个.. 使用“DwmSetWindowAttribute”API 将 NCRenderingPolicy 设置为 Enabled。http://msdn.microsoft.com/en-us/library/windows/desktop/aa969524(v=vs.85).aspx

    [DllImport("dwmapi.dll", PreserveSig = false)]
    public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);

    [Flags]
    public enum DwmWindowAttribute
    
        NCRenderingEnabled = 1,
        NCRenderingPolicy,
        TransitionsForceDisabled,
        AllowNCPaint,
        CaptionButtonBounds,
        NonClientRtlLayout,
        ForceIconicRepresentation,
        Flip3DPolicy,
        ExtendedFrameBounds,
        HasIconicBitmap,
        DisallowPeek,
        ExcludedFromPeek,
        Last
    

    [Flags]
    public enum DwmNCRenderingPolicy
    
        UseWindowStyle,
        Disabled,
        Enabled,
        Last
    

    public static bool SetNCRenderingActive(IntPtr Handle)
    
        int renderPolicy = (int)DwmNCRenderingPolicy.Enabled;            
        return (DwmSetWindowAttribute(Handle, (int)DwmWindowAttribute.NCRenderingPolicy, ref renderPolicy, sizeof(int)  ) == 0);
    

【讨论】:

以上是关于如何强制 Aero 绘制无边框窗口,就好像它处于活动状态一样,即使它不是?的主要内容,如果未能解决你的问题,请参考以下文章

qt按钮边框的问题

运行 Aero 时如何确定实际窗口窗体大小(包含所有非客户端元素)?

这种无边框的弹出窗口如何用JS实现?

在win32中更改无边框窗口的颜色

如何将窗体边框更改为 Windows Basic 而不是 Aero 样式?

VB 2013:在无边界表单上启用 Aero