2012-07-11 17 views
5

Estoy creando una aplicación Qt/C++ utilizando QML para algunas partes. En Windows, me gustaría hacer uso de ventanas translúcidas utilizando ExtendFrameIntoClientArea como se ve en este fragmento de mi clase de ventana.QT Ventana translúcida y escritorio remoto

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

El código está funcionando muy bien con una excepción. Si el sistema de ventana transparente está apagado, el fondo se vuelve negro, y como parte de mi IU es transparente, también se oscurece. Lo mismo sucede al iniciar sesión en una computadora remota que ejecuta la aplicación, incluso si el sistema de ventanas transparentes se reinicializa inmediatamente, el fondo permanece en negro hasta que se ejecute nuevamente el código anterior. Esto se demuestra en esta imagen: Comparison of failed rendering (in background) and correct (in front).

El problema es encontrar una señal para conectarse a la reinicialización de la ventana transparente, o mejor aún para detectar cuándo las ventanas se dibujan de forma transparente y dibujar la UI en consecuencia. Cualquier solución alternativa también es bienvenida.

Respuesta

2

Después de excavar tanto en Qt como en MSDN Aero documentation, se me ocurrió una solución de dos pasos. Al anular el método winEvent de mi ventana principal, pude recibir la señal que se activa cada vez que se habilita o deshabilita el sistema de ventanas translúcidas.

#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; 
} 

Eso me llevó bastante cerca, pero no me dijo si DWM estaba dibujando actualmente ventanas transparentes o no. Mediante el uso de dwmapi.dll yo era capaz de encontrar un método que hace exactamente eso, y se puede acceder, como a continuación:

// 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; 
} 

Mi aplicación es ahora capaz de reaccionar a los cambios en Aero y dibujar la interfaz gráfica de usuario en consecuencia. Al iniciar sesión en el escritorio remoto, la ventana se dibuja usando transparencia, donde esté disponible.

0
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; 
} 
Cuestiones relacionadas