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.
  • T3STYT Offline
    T3STYT Offline
    T3STY
    wrote on last edited by
    #3

    The glass functionality is provided by DwmExtendFrameIntoClientArea() (MSDN link: http://msdn.microsoft.com/en-us/library/windows/desktop/aa969512(v=vs.85).aspx )which is available via a shared system DLL, dwmapi.dll, or by statically linking dwmapi.lib.

    Have a look at this post of mine:
    http://qt-project.org/forums/viewthread/32286/
    The code there uses the DLL method and it's properly working on 32-bit, while on 64-bit it crashes the application. I still have no clue why this happens. The statically linked version instead works fine on both 32 and 64 bit versions.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      Stian Andre Olsen
      wrote on 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 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 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 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 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 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 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 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 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 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