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
Qt 6.11 is out! See what's new in the release blog

Using Blur Behind on Windows with Qt 5

Scheduled Pinned Locked Moved General and Desktop
13 Posts 3 Posters 9.8k 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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #2

    It looks like this functionality will be part of the new module called "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/09/30/qt-5-2-alpha-available/.

    1 Reply Last reply
    0
    • 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
      • ? Offline
        ? Offline
        A Former User
        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
        @

        1 Reply Last reply
        0
        • ? Offline
          ? Offline
          A Former User
          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
          @

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            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
            @

            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
              • ? Offline
                ? Offline
                A Former User
                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.

                1 Reply Last reply
                0
                • ? Offline
                  ? Offline
                  A Former User
                  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.

                  1 Reply Last reply
                  0
                  • ? Offline
                    ? Offline
                    A Former User
                    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
                    • ? Offline
                      ? Offline
                      A Former User
                      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
                      @

                      1 Reply Last reply
                      0
                      • ? Offline
                        ? Offline
                        A Former User
                        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
                        @

                        1 Reply Last reply
                        0
                        • ? Offline
                          ? Offline
                          A Former User
                          wrote on last edited by
                          #13

                          SaoQt.h is identical to the version given above.

                          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