我正在使用QML创build一些Qt / C ++应用程序。 在Windows下,我想利用使用ExtendFrameIntoClientArea的半透明窗口,就像从我的窗口类中看到的那样。
#ifdef Q_WS_WIN if ( QSysInfo::windowsVersion() == QSysInfo::WV_VISTA || QSysInfo::windowsVersion() == QSysInfo::WV_WINDOWS7 ) { EnableBlurBehindWidget(this, true); ExtendFrameIntoClientArea(this); } #else
代码运行良好,只有一个例外。 如果透明窗口系统closures,背景变黑,而且由于我的UI部分透明,它也变得很暗。 login到运行应用程序的远程计算机时也会发生同样的情况,即使透明窗口系统被重新初始化,背景仍然保持黑色,直到再次执行上述代码。 这是在这个图像中演示: 比较失败的渲染(在后台)和正确的(在前面)。
问题是find一个连接信号来重新初始化透明窗口,或者更好地检测何时透明地绘制窗口并相应地绘制UI。 任何替代scheme也是受欢迎的。
在Qt和MSDN Aero文档中进行深入研究后,我提出了两步解决方案。 通过覆盖我的主窗口的winEvent
方法,我可以接收每次启用或禁用半透明窗口系统时触发的信号。
#define WM_DWMCOMPOSITIONCHANGED 0x031E bool MainWindow::winEvent(MSG *message, long *result) { if ( message->message == WM_DWMCOMPOSITIONCHANGED ) { // window manager signaled change in composition return true; } return false; }
这让我非常接近,但它并没有告诉我DWM是否正在绘制透明的窗口。 通过使用dwmapi.dll
我能够找到一个完全相同的方法,并且可以像下面这样访问:
// QtDwmApi.cpp extern "C" { typedef HRESULT (WINAPI *t_DwmIsCompositionEnabled)(BOOL *pfEnabled); } bool DwmIsCompositionEnabled() { HMODULE shell; shell = LoadLibrary(L"dwmapi.dll"); if (shell) { BOOL enabled; t_DwmIsCompositionEnabled is_composition_enabled = \ reinterpret_cast<t_DwmIsCompositionEnabled>( GetProcAddress (shell, "DwmIsCompositionEnabled") ); is_composition_enabled(&enabled); FreeLibrary (shell); if ( enabled ) { return true; } else { return false; } } return false; }
现在,我的实现能够对Aero中的更改作出反应,并相应地绘制GUI。 在远程桌面上登录时,窗口也使用透明度进行绘制。
The function should be written as follows to avoid the GPA failure // QtDwmApi.cpp extern "C" { typedef HRESULT (WINAPI *t_DwmIsCompositionEnabled)(BOOL *pfEnabled); } bool DwmIsCompositionEnabled() { HMODULE shell; BOOL enabled=false; shell = LoadLibrary(L"dwmapi.dll"); if (shell) { t_DwmIsCompositionEnabled is_composition_enabled = \ reinterpret_cast<t_DwmIsCompositionEnabled>( GetProcAddress (shell, "DwmIsCompositionEnabled") ); if (is_composition_enabled) is_composition_enabled(&enabled); FreeLibrary (shell); } return enabled; }