5

一部に QML を使用して Qt/C++ アプリケーションを作成しています。ウィンドウの下では、ウィンドウ クラスのこのスニペットに見られるように、ExtendFrameIntoClientArea を使用して半透明のウィンドウを利用したいと考えています。

#ifdef Q_WS_WIN
    if ( QSysInfo::windowsVersion() == QSysInfo::WV_VISTA ||
         QSysInfo::windowsVersion() == QSysInfo::WV_WINDOWS7 )
    {
        EnableBlurBehindWidget(this, true);
        ExtendFrameIntoClientArea(this);
    }
#else

このコードは、1 つの例外を除いてうまく機能しています。透明なウィンドウ システムがオフになっていると、背景が黒くなり、UI の一部が透明になるため、背景も暗くなります。アプリケーションを実行しているリモート コンピューターにログインした場合も、透過ウィンドウ システムがすぐに再初期化されても、上記のコードが再度実行されるまで背景は黒のままです。これは、この画像で示されています:失敗したレンダリング (背景) と正しいレンダリング (前) の比較。

問題は、透過ウィンドウを再初期化するために接続する信号を見つけること、またはウィンドウが透過的に描画されるタイミングを検出して、それに応じて UI を描画することです。代替ソリューションも大歓迎です。

4

2 に答える 2

2

Qt とMSDN Aero の両方のドキュメントを調べた後、2 段階の解決策を思いつきました。メイン ウィンドウのメソッドをオーバーライドする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 を描画できるようになりました。リモート デスクトップ経由でログインする場合、ウィンドウは可能な場合は透明度を使用して描画されます。

于 2012-07-23T13:35:03.923 に答える