Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using Blur Behind on Windows with Qt 5
Forum Updated to NodeBB v4.3 + New Features

Using Blur Behind on Windows with Qt 5

Scheduled Pinned Locked Moved General and Desktop
13 Posts 3 Posters 7.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Stian Andre Olsen
    wrote on 1 Oct 2013, 13:10 last edited by
    #4

    Thanks "T3STY":http://qt-project.org/member/139603. I have tested my program (32-bit) on Windows 7 32-bit, Windows 7 64-bit and Windows 8 64-bit and it seems to work on all platforms.

    Below you can find my modified versions of the original code posted by "Jens Bache-Wiig":http://blog.qt.digia.com/blog/author/jbache/.

    qtwin.h:
    @
    /****************************************************************************
    **
    ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    **
    ** Use, modification and distribution is allowed without limitation,
    ** warranty, liability or support of any kind.
    **
    ****************************************************************************/

    #ifndef QTWIN_H
    #define QTWIN_H

    #include "SaoQt.h"
    #include <QtGui/QColor>
    #include <QtWidgets/QWidget>

    /*

    • This is a helper class for using the Desktop Window Manager
    • functionality on Windows 7 and Windows Vista. On other platforms
    • these functions will simply not do anything.
      */

    class WindowNotifier;

    class SAOQT_EXPORT QtWin
    {
    public:
    static bool enableBlurBehindWindow(QWidget* widget, bool enable = true);
    static bool extendFrameIntoClientArea(QWidget* widget, int left = -1, int top = -1, int right = -1, int bottom = -1);
    static bool isCompositionEnabled();
    static QColor colorizationColor();
    private:
    static WindowNotifier* windowNotifier();
    };

    #endif // QTWIN_H
    @

    Stian Andre Olsen

    1 Reply Last reply
    0
    • S Offline
      S Offline
      Stian Andre Olsen
      wrote on 1 Oct 2013, 13:11 last edited by
      #5

      qtwin.cpp:
      @
      /****************************************************************************
      **
      ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
      **
      ** Use, modification and distribution is allowed without limitation,
      ** warranty, liability or support of any kind.
      **
      ****************************************************************************/

      #include "qtwin.h"
      #include <QtCore/QLibrary>
      #include <QtCore/QList>
      #include <QtCore/QPointer>
      #include <QtWidgets/QApplication>
      #include <QtWidgets/QWidget>

      #ifdef Q_OS_WIN

      #include <QtCore/qt_windows.h>

      // Blur behind data structures
      #define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
      #define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified
      #define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified
      #define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message

      typedef struct _DWM_BLURBEHIND
      {
      DWORD dwFlags;
      BOOL fEnable;
      HRGN hRgnBlur;
      BOOL fTransitionOnMaximized;
      } DWM_BLURBEHIND, *PDWM_BLURBEHIND;

      typedef struct _MARGINS
      {
      int cxLeftWidth;
      int cxRightWidth;
      int cyTopHeight;
      int cyBottomHeight;
      } MARGINS, *PMARGINS;

      typedef HRESULT (WINAPI* PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
      typedef HRESULT (WINAPI* PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
      typedef HRESULT (WINAPI* PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
      typedef HRESULT (WINAPI* PtrDwmGetColorizationColor)(DWORD* pcrColorization, BOOL* pfOpaqueBlend);

      static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled = 0;
      static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
      static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
      static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;

      /*

      • Internal helper class that notifies windows if the
      • DWM compositing state changes and updates the widget
      • flags correspondingly.
        /
        class WindowNotifier : public QWidget
        {
        public:
        WindowNotifier() { winId(); }
        void addWidget(QWidget
        widget) { widgets.append(widget); }
        void removeWidget(QWidget* widget) { widgets.removeAll(widget); }
        bool winEvent(MSG* message, long* result);
        private:
        QWidgetList widgets;
        };

      static bool resolveLibs()
      {
      if (!pDwmIsCompositionEnabled)
      {
      QLibrary dwmLib(QStringLiteral("dwmapi"));
      pDwmIsCompositionEnabled = (PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
      pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
      pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
      pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
      }
      return pDwmIsCompositionEnabled != 0;
      }

      #endif // Q_OS_WIN

      /*!

      • Checks and returns true if Windows DWM composition
      • is currently enabled on the system.
        */
        bool QtWin::isCompositionEnabled()
        {
        #ifdef Q_OS_WIN
        if (resolveLibs())
        {
        BOOL isEnabled = false;
        HRESULT hr = pDwmIsCompositionEnabled(&isEnabled);
        if (SUCCEEDED(hr))
        return isEnabled;
        }
        #endif // Q_OS_WIN

      return false;
      }

      /*!

      • Enables Blur behind on a Widget.
      • \a enable tells if the blur should be enabled or not
        /
        bool QtWin::enableBlurBehindWindow(QWidget
        widget, bool enable)
        {
        Q_ASSERT(widget);
        bool result = false;

      #ifdef Q_OS_WIN
      if (resolveLibs())
      {
      DWM_BLURBEHIND bb = {0};
      bb.fEnable = enable;
      bb.dwFlags = DWM_BB_ENABLE;
      bb.hRgnBlur = NULL;
      widget->setAttribute(Qt::WA_TranslucentBackground, enable);
      widget->setAttribute(Qt::WA_NoSystemBackground, enable);
      HRESULT hr = pDwmEnableBlurBehindWindow(reinterpret_cast<HWND>(widget->winId()), &bb);
      if (SUCCEEDED(hr))
      {
      result = true;
      windowNotifier()->addWidget(widget);
      }
      }
      #endif // Q_OS_WIN

      return result;
      }

      /*!

      • ExtendFrameIntoClientArea.
      • This controls the rendering of the frame inside the window.
      • Note that passing margins of -1 (the default value) will completely
      • remove the frame from the window.
      • \note You should not call enableBlurBehindWindow before calling
      •   this functions
        

      /
      bool QtWin::extendFrameIntoClientArea(QWidget
      widget, int left, int top, int right, int bottom)
      {
      Q_ASSERT(widget);
      Q_UNUSED(left);
      Q_UNUSED(top);
      Q_UNUSED(right);
      Q_UNUSED(bottom);

      bool result = false;

      #ifdef Q_OS_WIN
      if (resolveLibs())
      {
      MARGINS m = {left, top, right, bottom};
      HRESULT hr = pDwmExtendFrameIntoClientArea(reinterpret_cast<HWND>(widget->winId()), &m);
      if (SUCCEEDED(hr))
      {
      result = true;
      windowNotifier()->addWidget(widget);
      }
      widget->setAttribute(Qt::WA_TranslucentBackground, result);
      }
      #endif // Q_OS_WIN

      return result;
      }

      /*!

      • Returns the current colorizationColor for the window.
        */
        QColor QtWin::colorizationColor()
        {
        QColor resultColor = QApplication::palette().window().color();

      #ifdef Q_OS_WIN
      if (resolveLibs())
      {
      DWORD color = 0;
      BOOL opaque = FALSE;
      HRESULT hr = pDwmGetColorizationColor(&color, &opaque);
      if (SUCCEEDED(hr))
      resultColor = QColor(color);
      }
      #endif // Q_OS_WIN

      return resultColor;
      }

      #ifdef Q_OS_WIN

      WindowNotifier* QtWin::windowNotifier()
      {
      static WindowNotifier* windowNotifierInstance = 0;
      if (!windowNotifierInstance)
      windowNotifierInstance = new WindowNotifier();
      return windowNotifierInstance;
      }

      /* Notify all enabled windows that the DWM state changed */
      bool WindowNotifier::winEvent(MSG *message, long result)
      {
      if (message && message->message == WM_DWMCOMPOSITIONCHANGED)
      {
      bool compositionEnabled = QtWin::isCompositionEnabled();
      foreach(QWidget
      widget, widgets)
      {
      if (widget)
      widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
      widget->update();
      }
      }
      return QWidget::nativeEvent("windows_generic_MSG", message, result);
      }

      #endif // Q_OS_WIN
      @

      Stian Andre Olsen

      1 Reply Last reply
      0
      • S Offline
        S Offline
        Stian Andre Olsen
        wrote on 1 Oct 2013, 13:11 last edited by
        #6

        SaoQt.h:
        @
        #ifndef SAOQT_SAOQT_H
        #define SAOQT_SAOQT_H

        #include <QtCore/QtGlobal>

        #if defined(SAOQT_LIB)

        define SAOQT_EXPORT Q_DECL_EXPORT

        #else

        define SAOQT_EXPORT Q_DECL_IMPORT

        #endif

        #endif // SAOQT_SAOQT_H
        @

        Stian Andre Olsen

        1 Reply Last reply
        0
        • T3STYT Offline
          T3STYT Offline
          T3STY
          wrote on 4 Dec 2013, 19:04 last edited by
          #7

          I was just testing this code in an app today and I got a few issues.
          First is in qtwin.h when the class QtWin is declared with SAOQT_EXPORT:
          http://img.networkdigitale.com/di/EVMM/SAOQT_EXPORT.png
          If I remove SAOQT_EXPORT from QtWin's declaration the code compiles just fine.
          Second is glitches:
          http://img.networkdigitale.com/di/JKDP/glitches.png
          In this image I have a QWidget parent, and 10 QSlider + QLabel childs. As soon as I move the sliders I get those glitches you see in the image. They go away as soon as I resize the window, probably because resizing invokes a window redraw.

          How do I fix those issues?

          1 Reply Last reply
          0
          • S Offline
            S Offline
            Stian Andre Olsen
            wrote on 5 Dec 2013, 08:26 last edited by
            #8

            SAOQT_EXPORT handles the magic needed when building a dynamic link library and is defined in SaoQt.h (my library is called SaoQt, that's why). When building the library SAOQT_LIB is defined and when using the library in an application SAOQT_LIB is not defined.

            The original code worked without problems using Qt 4.8. However, after moving to Qt 5 I have update problems for a transparent menu button. I haven't really investigated the problem so I can't help you. After I read about the "Qt Windows Extras":http://doc-snapshot.qt-project.org/qt5-stable/qtwinextras-index.html that will be introduced in "Qt 5.2":http://blog.qt.digia.com/blog/2013/11/29/qt-5-2-release-candidate-1-available/ I decided to wait for Qt 5.2 before spending more time on this.

            Stian Andre Olsen

            1 Reply Last reply
            0
            • S Offline
              S Offline
              Stian Andre Olsen
              wrote on 8 Jan 2014, 11:41 last edited by
              #9

              I have now switched to the Qt Windows Extras found in Qt 5.2 and my application works without any update problems (glitches). To avoid the glitches I had to use:

              @
              setStyleSheet("QMainWindow { background: transparent; }");
              @

              Without it, I experienced the same glitches as I had with the old code.

              I have also tested the old code with the same call to styleSheet but the old code still had the glitches.

              Stian Andre Olsen

              1 Reply Last reply
              0
              • S Offline
                S Offline
                Serenity
                wrote on 29 Jan 2014, 13:33 last edited by
                #10

                Can you also post the original source code of the Qt4 version please?

                Thank you in advance!

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  Stian Andre Olsen
                  wrote on 3 Feb 2014, 06:56 last edited by
                  #11

                  My latest version for Qt 4.x (compiled with Qt 4.8.1):

                  qtwin.h:

                  @
                  /****************************************************************************
                  **
                  ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
                  **
                  ** Use, modification and distribution is allowed without limitation,
                  ** warranty, liability or support of any kind.
                  **
                  ****************************************************************************/

                  #ifndef QTWIN_H
                  #define QTWIN_H

                  #include "SaoQt.h"
                  #include <QColor>
                  #include <QWidget>

                  /*

                  • This is a helper class for using the Desktop Window Manager
                  • functionality on Windows 7 and Windows Vista. On other platforms
                  • these functions will simply not do anything.
                    */

                  class WindowNotifier;

                  class SAOQT_EXPORT QtWin
                  {
                  public:
                  static bool enableBlurBehindWindow(QWidget* widget, bool enable = true);
                  static bool extendFrameIntoClientArea(QWidget* widget, int left = -1, int top = -1, int right = -1, int bottom = -1);
                  static bool isCompositionEnabled();
                  static QColor colorizationColor();
                  private:
                  static WindowNotifier* windowNotifier();
                  };

                  #endif // QTWIN_H
                  @

                  Stian Andre Olsen

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    Stian Andre Olsen
                    wrote on 3 Feb 2014, 06:57 last edited by
                    #12

                    qtwin.cpp:

                    @
                    /****************************************************************************
                    **
                    ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
                    **
                    ** Use, modification and distribution is allowed without limitation,
                    ** warranty, liability or support of any kind.
                    **
                    ****************************************************************************/

                    #include "qtwin.h"
                    #include <QLibrary>
                    #include <QApplication>
                    #include <QWidget>
                    #include <QList>
                    #include <QPointer>

                    #ifdef Q_WS_WIN

                    #include <qt_windows.h>

                    // Blur behind data structures
                    #define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
                    #define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified
                    #define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified
                    #define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message

                    typedef struct _DWM_BLURBEHIND
                    {
                    DWORD dwFlags;
                    BOOL fEnable;
                    HRGN hRgnBlur;
                    BOOL fTransitionOnMaximized;
                    } DWM_BLURBEHIND, *PDWM_BLURBEHIND;

                    typedef struct _MARGINS
                    {
                    int cxLeftWidth;
                    int cxRightWidth;
                    int cyTopHeight;
                    int cyBottomHeight;
                    } MARGINS, *PMARGINS;

                    typedef HRESULT (WINAPI* PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
                    typedef HRESULT (WINAPI* PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
                    typedef HRESULT (WINAPI* PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
                    typedef HRESULT (WINAPI* PtrDwmGetColorizationColor)(DWORD* pcrColorization, BOOL* pfOpaqueBlend);

                    static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled = 0;
                    static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
                    static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
                    static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;

                    /*

                    • Internal helper class that notifies windows if the
                    • DWM compositing state changes and updates the widget
                    • flags correspondingly.
                      /
                      class WindowNotifier : public QWidget
                      {
                      public:
                      WindowNotifier() { winId(); }
                      void addWidget(QWidget
                      widget) { widgets.append(widget); }
                      void removeWidget(QWidget* widget) { widgets.removeAll(widget); }
                      bool winEvent(MSG* message, long* result);
                      private:
                      QWidgetList widgets;
                      };

                    static bool resolveLibs()
                    {
                    if (!pDwmIsCompositionEnabled)
                    {
                    QLibrary dwmLib(QString::fromAscii("dwmapi"));
                    pDwmIsCompositionEnabled = (PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
                    pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
                    pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
                    pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
                    }
                    return pDwmIsCompositionEnabled != 0;
                    }

                    #endif // Q_WS_WIN

                    /*!

                    • Checks and returns true if Windows DWM composition
                    • is currently enabled on the system.
                      */
                      bool QtWin::isCompositionEnabled()
                      {
                      #ifdef Q_WS_WIN
                      if (resolveLibs())
                      {
                      BOOL isEnabled = false;
                      HRESULT hr = pDwmIsCompositionEnabled(&isEnabled);
                      if (SUCCEEDED(hr))
                      return isEnabled;
                      }
                      #endif // Q_WS_WIN

                    return false;
                    }

                    /*!

                    • Enables Blur behind on a Widget.
                    • \a enable tells if the blur should be enabled or not
                      /
                      bool QtWin::enableBlurBehindWindow(QWidget
                      widget, bool enable)
                      {
                      Q_ASSERT(widget);
                      bool result = false;

                    #ifdef Q_WS_WIN
                    if (resolveLibs())
                    {
                    DWM_BLURBEHIND bb = {0};
                    bb.fEnable = enable;
                    bb.dwFlags = DWM_BB_ENABLE;
                    bb.hRgnBlur = NULL;
                    widget->setAttribute(Qt::WA_TranslucentBackground, enable);
                    widget->setAttribute(Qt::WA_NoSystemBackground, enable);
                    HRESULT hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb);
                    if (SUCCEEDED(hr))
                    {
                    result = true;
                    windowNotifier()->addWidget(widget);
                    }
                    }
                    #endif // Q_WS_WIN

                    return result;
                    }

                    /*!

                    • ExtendFrameIntoClientArea.
                    • This controls the rendering of the frame inside the window.
                    • Note that passing margins of -1 (the default value) will completely
                    • remove the frame from the window.
                    • \note You should not call enableBlurBehindWindow before calling
                    •   this functions
                      

                    /
                    bool QtWin::extendFrameIntoClientArea(QWidget
                    widget, int left, int top, int right, int bottom)
                    {
                    Q_ASSERT(widget);
                    Q_UNUSED(left);
                    Q_UNUSED(top);
                    Q_UNUSED(right);
                    Q_UNUSED(bottom);

                    bool result = false;

                    #ifdef Q_WS_WIN
                    if (resolveLibs())
                    {
                    MARGINS m = {left, top, right, bottom};
                    HRESULT hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
                    if (SUCCEEDED(hr))
                    {
                    result = true;
                    windowNotifier()->addWidget(widget);
                    }
                    widget->setAttribute(Qt::WA_TranslucentBackground, result);
                    }
                    #endif // Q_WS_WIN

                    return result;
                    }

                    /*!

                    • Returns the current colorizationColor for the window.
                      */
                      QColor QtWin::colorizationColor()
                      {
                      QColor resultColor = QApplication::palette().window().color();

                    #ifdef Q_WS_WIN
                    if (resolveLibs())
                    {
                    DWORD color = 0;
                    BOOL opaque = FALSE;
                    HRESULT hr = pDwmGetColorizationColor(&color, &opaque);
                    if (SUCCEEDED(hr))
                    resultColor = QColor(color);
                    }
                    #endif // Q_WS_WIN

                    return resultColor;
                    }

                    #ifdef Q_WS_WIN

                    WindowNotifier* QtWin::windowNotifier()
                    {
                    static WindowNotifier* windowNotifierInstance = 0;
                    if (!windowNotifierInstance)
                    windowNotifierInstance = new WindowNotifier();
                    return windowNotifierInstance;
                    }

                    /* Notify all enabled windows that the DWM state changed */
                    bool WindowNotifier::winEvent(MSG *message, long result)
                    {
                    if (message && message->message == WM_DWMCOMPOSITIONCHANGED)
                    {
                    bool compositionEnabled = QtWin::isCompositionEnabled();
                    foreach(QWidget
                    widget, widgets)
                    {
                    if (widget)
                    widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
                    widget->update();
                    }
                    }
                    return QWidget::winEvent(message, result);
                    }

                    #endif // Q_WS_WIN
                    @

                    Stian Andre Olsen

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      Stian Andre Olsen
                      wrote on 3 Feb 2014, 06:59 last edited by
                      #13

                      SaoQt.h is identical to the version given above.

                      Stian Andre Olsen

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved