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. How to round the corners of a frameless QWidget, when also applying acrylic effects?
Forum Update on Monday, May 27th 2025

How to round the corners of a frameless QWidget, when also applying acrylic effects?

Scheduled Pinned Locked Moved Unsolved General and Desktop
questionsqwidgetstylecustomplugin
7 Posts 4 Posters 125 Views
  • 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.
  • G Offline
    G Offline
    grainyblob
    wrote last edited by
    #1

    Hello everyone! I like to make a dock in Qt for Windows. I have the general idea of how to do it, and I would first like to focus on making the window look pretty. Now I would like to provide the user with an option to change the corner radius of the dock, and also allow for Acrylic or Mica (introduced in W11.) Basically, I want to achieve custom border radii on a frameless window with acrylic.

    Now, I attempted some stuff:

    1. Set stylesheet with border radius property.
    // inside the constructor
    setStyleSheet("border-radius: 32px;");
    
    1. Add a custom mask
    Dock::Dock(QWidget *parent):QWidget(parent)
    {
        // after other methods are called.
        roundZeCorners();
    }
    
    void Dock::roundZeCorners(int radius) {
        QPainterPath path;
        path.addRoundedRect(rect(), radius, radius);
        setMask(QRegion(path.toFillPolygon().toPolygon()));
    }
    
    void Dock::paintEvent(QPaintEvent *event) {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        
        QPainterPath path;
        path.addRoundedRect(rect(), border_radius, border_radius);
        
        painter.setClipPath(path);
        painter.fillPath(path, Qt::transparent);
    }
    

    These are the only two solutions I came across to make custom window as described, but neither work. The stylesheet was obvious, because I read that qwidget not support styling border radius, and besides, it is top level window.

    Here is how I apply my window effects:

    #ifdef Q_OS_WIN
    void Dock::applyWindowEffect(uint tint_color) 
    {
        const HINSTANCE hModule = LoadLibraryA("user32.dll");
        if (hModule) {
            struct ACCENTPOLICY
            {
                int nAccentState;
                int nFlags;
                DWORD nColor;
                int nAnimationId;
            };
            struct WINCOMPATTRDATA
            {
                int nAttribute;
                PVOID pData;
                ULONG ulDataSize;
            };
    
            typedef BOOL(WINAPI* pSetWindowCompositionAttribute)(HWND, WINCOMPATTRDATA*);
            const auto SetWindowCompositionAttribute = (pSetWindowCompositionAttribute)GetProcAddress(hModule, "SetWindowCompositionAttribute");
    
            if (SetWindowCompositionAttribute)
            {
                ACCENTPOLICY policy = { 4, 0, tint_color, 0 }; // 4 = ACCENT_ENABLE_ACRYLICBLURBEHIND
                WINCOMPATTRDATA data = { 19, &policy, sizeof(ACCENTPOLICY) }; // 19 = WCA_ACCENT_POLICY
                SetWindowCompositionAttribute((HWND)winId(), &data);
            }
            FreeLibrary(hModule);
        }
    }
    #endif
    

    How would I add the rounded corners? Sorry if this is a stupid post.

    Axel SpoerlA 1 Reply Last reply
    0
    • G grainyblob

      Hello everyone! I like to make a dock in Qt for Windows. I have the general idea of how to do it, and I would first like to focus on making the window look pretty. Now I would like to provide the user with an option to change the corner radius of the dock, and also allow for Acrylic or Mica (introduced in W11.) Basically, I want to achieve custom border radii on a frameless window with acrylic.

      Now, I attempted some stuff:

      1. Set stylesheet with border radius property.
      // inside the constructor
      setStyleSheet("border-radius: 32px;");
      
      1. Add a custom mask
      Dock::Dock(QWidget *parent):QWidget(parent)
      {
          // after other methods are called.
          roundZeCorners();
      }
      
      void Dock::roundZeCorners(int radius) {
          QPainterPath path;
          path.addRoundedRect(rect(), radius, radius);
          setMask(QRegion(path.toFillPolygon().toPolygon()));
      }
      
      void Dock::paintEvent(QPaintEvent *event) {
          QPainter painter(this);
          painter.setRenderHint(QPainter::Antialiasing);
          
          QPainterPath path;
          path.addRoundedRect(rect(), border_radius, border_radius);
          
          painter.setClipPath(path);
          painter.fillPath(path, Qt::transparent);
      }
      

      These are the only two solutions I came across to make custom window as described, but neither work. The stylesheet was obvious, because I read that qwidget not support styling border radius, and besides, it is top level window.

      Here is how I apply my window effects:

      #ifdef Q_OS_WIN
      void Dock::applyWindowEffect(uint tint_color) 
      {
          const HINSTANCE hModule = LoadLibraryA("user32.dll");
          if (hModule) {
              struct ACCENTPOLICY
              {
                  int nAccentState;
                  int nFlags;
                  DWORD nColor;
                  int nAnimationId;
              };
              struct WINCOMPATTRDATA
              {
                  int nAttribute;
                  PVOID pData;
                  ULONG ulDataSize;
              };
      
              typedef BOOL(WINAPI* pSetWindowCompositionAttribute)(HWND, WINCOMPATTRDATA*);
              const auto SetWindowCompositionAttribute = (pSetWindowCompositionAttribute)GetProcAddress(hModule, "SetWindowCompositionAttribute");
      
              if (SetWindowCompositionAttribute)
              {
                  ACCENTPOLICY policy = { 4, 0, tint_color, 0 }; // 4 = ACCENT_ENABLE_ACRYLICBLURBEHIND
                  WINCOMPATTRDATA data = { 19, &policy, sizeof(ACCENTPOLICY) }; // 19 = WCA_ACCENT_POLICY
                  SetWindowCompositionAttribute((HWND)winId(), &data);
              }
              FreeLibrary(hModule);
          }
      }
      #endif
      

      How would I add the rounded corners? Sorry if this is a stupid post.

      Axel SpoerlA Offline
      Axel SpoerlA Offline
      Axel Spoerl
      Moderators
      wrote last edited by
      #2

      @grainyblob
      Why does addRoundedRect not work? What's the desired and actual outcome?
      Have you tried to draw it directly with QPainter::drawRoundedRect()?
      Maybe also set an explicit brush, just for testing.

      Software Engineer
      The Qt Company, Oslo

      G 1 Reply Last reply
      0
      • V Offline
        V Offline
        Vitalii777
        wrote last edited by
        #3

        Please try to call 'setMask' to round borders in 'resizeEvent' and 'changeEvent -> QEvent::WindowStateChange event' too.

        G 1 Reply Last reply
        0
        • Axel SpoerlA Axel Spoerl

          @grainyblob
          Why does addRoundedRect not work? What's the desired and actual outcome?
          Have you tried to draw it directly with QPainter::drawRoundedRect()?
          Maybe also set an explicit brush, just for testing.

          G Offline
          G Offline
          grainyblob
          wrote last edited by grainyblob
          #4

          @Axel-Spoerl
          The desired outcome was to make a acrylic window with a custom border radius. (See attached image). Once I add a roundedRect to the path I set a mask from the path. Now in a normal QWidget, it will round the corners, but my guess is that because of the DWM code I'm using, it's overriding the composition and displaying a rect.


          9850f51e-4adb-47c6-a1de-6d2dadc1d57e-{63D78F5E-4D8E-4E42-91E7-AC709EB7B477}.png
          see above for desired result ↑

          Once again, sorry if my explaination of my issue is bad, I really struggle to explain things most of the time.

          Edit: I forgot to ask, what do you mean by "explicit brush"?

          jsulmJ 1 Reply Last reply
          0
          • G grainyblob

            @Axel-Spoerl
            The desired outcome was to make a acrylic window with a custom border radius. (See attached image). Once I add a roundedRect to the path I set a mask from the path. Now in a normal QWidget, it will round the corners, but my guess is that because of the DWM code I'm using, it's overriding the composition and displaying a rect.


            9850f51e-4adb-47c6-a1de-6d2dadc1d57e-{63D78F5E-4D8E-4E42-91E7-AC709EB7B477}.png
            see above for desired result ↑

            Once again, sorry if my explaination of my issue is bad, I really struggle to explain things most of the time.

            Edit: I forgot to ask, what do you mean by "explicit brush"?

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote last edited by
            #5

            @grainyblob said in How to round the corners of a frameless QWidget, when also applying acrylic effects?:

            I forgot to ask, what do you mean by "explicit brush"?

            Your own QBrush instance which you pass to the painter. https://doc.qt.io/qt-6/qbrush.html

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            G 1 Reply Last reply
            0
            • V Vitalii777

              Please try to call 'setMask' to round borders in 'resizeEvent' and 'changeEvent -> QEvent::WindowStateChange event' too.

              G Offline
              G Offline
              grainyblob
              wrote last edited by
              #6

              @Vitalii777
              have tried to call setMask() in all events, none of them caused any change.

              1 Reply Last reply
              0
              • jsulmJ jsulm

                @grainyblob said in How to round the corners of a frameless QWidget, when also applying acrylic effects?:

                I forgot to ask, what do you mean by "explicit brush"?

                Your own QBrush instance which you pass to the painter. https://doc.qt.io/qt-6/qbrush.html

                G Offline
                G Offline
                grainyblob
                wrote last edited by
                #7

                @jsulm

                Yes in that case, it works. The corners of the window are rounded as expected. It is only with my applyWindowEffects() method which fails to round corners in this method.

                Alternatively, since it might be a DWM level issue, I'm considering trying to replicate what I do with masking but with native DWM API.

                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