C++ 使用Areo捕捉、阴影、最小化动画和抖动的无边界窗口

C++ 使用Areo捕捉、阴影、最小化动画和抖动的无边界窗口,c++,windows,qt,aero,borderless,C++,Windows,Qt,Aero,Borderless,我正在使用Windows上的无边框窗口制作应用程序。但是,由于窗口是无边界的,因此我没有areo阴影、捕捉、最小化动画或抖动。我环顾四周,没有发现任何网站解释如何实现这一点。然而,我知道这是可能的,因为Office2013、VisualStudio2012和Steam都具有这些功能,并且是无边界的。我特别使用QT和C++,但是如果你已经解决了另一个窗口库,我也想听到你的解决方案。任何一个我所说的areo shadow并不是指两边都有阴影,而是指所有活动的本机areo windows应用程序的四周

我正在使用Windows上的无边框窗口制作应用程序。但是,由于窗口是无边界的,因此我没有areo阴影、捕捉、最小化动画或抖动。我环顾四周,没有发现任何网站解释如何实现这一点。然而,我知道这是可能的,因为Office2013、VisualStudio2012和Steam都具有这些功能,并且是无边界的。我特别使用QT和C++,但是如果你已经解决了另一个窗口库,我也想听到你的解决方案。任何一个我所说的areo shadow并不是指两边都有阴影,而是指所有活动的本机areo windows应用程序的四周都有发光的阴影。

在使用Spy++检查Steam的窗口(其窗口样式、它如何回复窗口消息)并尝试匹配它所做的一切之后,再加上来自此应用程序的DWMAPI调用,我想我知道了

要隐藏窗口边框,请在WindowProc中处理
WM\u NCCALCSIZE
消息:

case WM_NCCALCSIZE: {
    if (window->is_borderless) {
        return 0;
    } else {
        return DefWindowProc(hwnd, msg, wparam, lparam);
    }
}
要启用阴影,只需执行以下操作:

MARGINS borderless = {1,1,1,1};
DwmExtendFrameIntoClientArea(hwnd, &borderless);
要将其关闭,请恢复默认的边距
窗口边距={0,0,0}。
可能会加入一个
SetWindowPos(hwnd,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_asynchWindowPos | SWP_NOSIZE | SWP|NOMOVE)另外,确保重新绘制帧

但是,这似乎并不适用于所有窗口样式,显然,您的窗口样式不能包含标题栏。标题栏工作正常,添加标题栏似乎可以启用最小化动画

我使用的阴影最简单的窗口样式是
WS|u POPUP | WS|u THICKFRAME
,它还可以获得空气动力学捕捉、最大化、最小化以及我使用的平滑最小化动画
WS|u POPUP | WS|u THICKFRAME | WS|u MINIMIZEBOX | WS|最大化box | WS| u字幕

通过
DwmSetWindowAttribute
更改
DWMWA\u nRendering\u策略
DWMWA\u ALLOW\u NCPAINT
似乎不是必需的,默认设置似乎有效

警告一句:
dwmextendframeintoclienterea
完全按照名称所示,因此,如果您使用alpha通道直接在客户端区域绘制图像(例如使用opengl、direct3d/2d),则会看到一个小帧:

因此,您可能需要在透明元素后面放置一个非透明的小部件、画笔或其他东西

如果一切顺利,它应该是这样的:


,F11切换无边界/窗口模式,F12切换无边界阴影的打开和关闭。

感谢melak47的回答

对于那些正在寻找C++/Qt示例的人来说,这个GitHub profect基于melak47代码完成了这项工作,非常有魅力(感谢deimos1877)!

请确保使用visual studio编译器(>=2010)获取所需的DLL,它应该可以工作。
此示例包括aerosnap支持、无边框窗口、最小化效果、aero阴影。

我创建了一个响应为photoshop的示例


我读到了DWMWA\u ALLOW\u NCPAINT。所以Word2013和VS2012吸引了边界来隐藏它?正如我看到的,很多人都在寻找这个问题的答案。我刚才是他们中的一员。我尝试了这些实现,在这篇文章中已经给出了答案,但由于一些原因,它们并不完全适合。在谷歌搜索和修改deimos1877的BodrelessWindow示例一段时间后,我最终得到了更轻量级的Qt解决方案。这是一个简单的Qt项目,只有QMainWindow。您可以根据自己的需要随意使用和采用它。主要的优点是-Qt窗口和本机WinAPI之间没有代理类,Aero关闭时没有窗口标题闪烁。蒸汽仍然有一个与空气动力学相同的阴影。它也有Aero Snap/Shake/Stuff,但缺少最小化动画。@RandomUser我的解决方案除了最小化过渡之外,什么都做——这是使阴影工作所需的窗口样式的结果。即使是Outlook 2013也缺少这一点,因此我认为,如果不像Visual Studio那样假装它会发光,这是不可能的。(有时您可以看到窗口框架在“客户端”区域内变得可见-因此它们确实看起来像是在框架上绘制的)Visual Studio的最小化动画看起来完全像一个带边框的窗口。他们真的做得很好吗?你知道我们该怎么假装吗?看起来是这样的。我认为这将是一个很大的努力,只是得到最小化动画,虽然-你不会得到空气动力学阴影;你得画画而不是画框。此外,可能有许多特殊情况需要处理,以保持边境不存在的欺骗。比如说,确保Alt+PrintScreen只捕获客户端区域,而不是aero snap的帧、窗口大小(因为透明边框,所以没有间隙)…我认为除了最小化动画之外的所有内容。我想说,这是最好的答案,希望有新朋友来这里使用此演示。使用Qt5.8,您会在第257行的
qwinhost.cpp
中遇到编译器错误,抱怨找不到
qWinAppInst()
标识符
qWinAppInst()
已从Qt5.8中的QtCore中删除(请参阅),因此您必须将其替换为
GetModuleHandle(0)
我没有说否决票,我只是想告诉您链接应该只支持,因为如果链接断开,您的答案将变为无用SGPL2。我更喜欢实现我自己的。它工作得很完美,如果有人有机会改进它,甚至更多。他是受欢迎的。