Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
qtws26_logo

The Qt Event of the Year: Qt World Summit 2026

Save Your Spot >
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Customize window frame
Qt 6.12 LTS is out! See what's new in the release blog

Customize window frame

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 8 Posters 49.3k Views 2 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.
  • B Offline
    B Offline
    bodzio131
    wrote on last edited by
    #2

    Probably QStyle class is what you are looking for.

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #3

      No, it's not. QStyle is for providing custom styles to the widgets. Window frame is an OS specific thing (some OSs don't have frames or windows) and is not drawn by Qt.

      On Windows you need to dive a little lower level than Qt offers, by responding to the native messages your window is getting. Implement the "nativeEvent":http://qt-project.org/doc/qt-5.0/qtwidgets/qwidget.html#nativeEvent and handle messages like "WM_NCPAINT":http://msdn.microsoft.com/pl-pl/library/windows/desktop/dd145212.aspx and "WM_NCHITTEST":http://msdn.microsoft.com/en-us/library/windows/desktop/ms645618.aspx
      Google for "drawing in non-client area", just keep in mind that it's not a Qt specific task.

      Other approach is disabling window frame entirely by setting Qt::FramelessWindowHint flag on your widget, and drawing the frame and buttons yourself. This gives you the ultimate control of the look of the frame, but is also a lot of work, because you need to handle all the windowing behavior like resizing, moving, maximizing or Aero Shake yourself.

      1 Reply Last reply
      1
      • B Offline
        B Offline
        bodzio131
        wrote on last edited by
        #4

        Uuups, I misunderstood the problem. Thanks for clearing this!

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

          Thanks! A bit harder than I had anticipated, but glad to know it's possible, even though it's OS specific.

          1 Reply Last reply
          0
          • raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on last edited by
            #6

            You don't really need to go that deep into the OS.

            Use "QWidget::setWindowFlags()":http://qt-project.org/doc/qt-4.8/qwidget.html#windowFlags-prop and set it to Qt::Window | Qt::FramelessWindowHint on your top-level widget.
            Now you need to do all the painting and handling (moving, resizing, minimizing, maximizing, closing) yourself, but this shouldn't be that hard to handle the specific events.

            EDIT: oops...sorry Krzysztof Kawa overread your last paragraph.

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0
            • S Offline
              S Offline
              Sam
              wrote on last edited by
              #7

              I dont know if this helps, but may be you can have a look at "Qt Tutorial: Creating a custom window":http://qt.developpez.com/tutoriels/braindeadbzh/customwindow/ , its in French just open the link in google chrome and it will translate to English.

              1 Reply Last reply
              0
              • ? Offline
                ? Offline
                A Former User
                wrote on last edited by A Former User
                #8
                #include "mainwindow.h"
                
                #ifdef Q_OS_WIN
                #include <WinUser.h>
                #include <windowsx.h>
                #include <dwmapi.h>
                #include <gdiplus.h>
                #include <GdiPlusColor.h>
                #endif
                
                MainWindow::MainWindow(QWidget *parent)
                    : QWidget(parent)
                {
                    setMinimumSize(450,405);
                }
                
                void MainWindow::showEvent(QShowEvent *event)
                {
                    QWidget::showEvent(event);
                #ifdef Q_OS_WIN
                    window_borderless();
                #endif
                }
                
                #ifdef Q_OS_WIN
                void MainWindow::window_borderless()
                {
                    if (isVisible())
                    {
                        //defaultStyle = (WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME)
                        SetWindowLongPtr(winId(), GWL_STYLE, WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX );
                
                        window_shadow();
                
                        SetWindowPos(winId(), 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
                    }
                }
                
                void MainWindow::window_shadow()
                {
                    const MARGINS shadow = { 1, 1, 1, 1 };
                    DwmExtendFrameIntoClientArea(winId(), &shadow);
                }
                
                bool MainWindow::winEvent(MSG *msg, long *result)
                {
                    switch (msg->message)
                    {
                    case WM_NCCALCSIZE:
                    {
                        //this kills the window frame and title bar we added with
                        //WS_THICKFRAME and WS_CAPTION
                        *result = 0;
                        return true;
                        break;
                    }
                    case WM_NCHITTEST:
                    {
                        *result = 0;
                        const LONG border_width = 8; //in pixels
                        RECT winrect;
                        GetWindowRect(winId(), &winrect);
                
                        long x = GET_X_LPARAM(msg->lParam);
                        long y = GET_Y_LPARAM(msg->lParam);
                
                        bool resizeWidth = minimumWidth() != maximumWidth();
                        bool resizeHeight = minimumHeight() != maximumHeight();
                
                        if(resizeWidth)
                        {
                            //left border
                            if (x >= winrect.left && x < winrect.left + border_width)
                            {
                                *result = HTLEFT;
                            }
                            //right border
                            if (x < winrect.right && x >= winrect.right - border_width)
                            {
                                *result = HTRIGHT;
                            }
                        }
                        if(resizeHeight)
                        {
                            //bottom border
                            if (y < winrect.bottom && y >= winrect.bottom - border_width)
                            {
                                *result = HTBOTTOM;
                            }
                            //top border
                            if (y >= winrect.top && y < winrect.top + border_width)
                            {
                                *result = HTTOP;
                            }
                        }
                        if(resizeWidth && resizeHeight)
                        {
                            //bottom left corner
                            if (x >= winrect.left && x < winrect.left + border_width &&
                                    y < winrect.bottom && y >= winrect.bottom - border_width)
                            {
                                *result = HTBOTTOMLEFT;
                            }
                            //bottom right corner
                            if (x < winrect.right && x >= winrect.right - border_width &&
                                    y < winrect.bottom && y >= winrect.bottom - border_width)
                            {
                                *result = HTBOTTOMRIGHT;
                            }
                            //top left corner
                            if (x >= winrect.left && x < winrect.left + border_width &&
                                    y >= winrect.top && y < winrect.top + border_width)
                            {
                                *result = HTTOPLEFT;
                            }
                            //top right corner
                            if (x < winrect.right && x >= winrect.right - border_width &&
                                    y >= winrect.top && y < winrect.top + border_width)
                            {
                                *result = HTTOPRIGHT;
                            }
                        }
                
                        //TODO: allow move?
                        if(*result==0)
                            *result = HTCAPTION ;
                
                        return true;
                        break;
                    } //end case WM_NCHITTEST
                    case WM_CLOSE:
                    {
                        return close();
                        break;
                    }
                    default:
                        return QWidget::winEvent(msg,result);
                    }
                
                    return false;
                }
                #endif
                
                1 Reply Last reply
                1
                • ? Offline
                  ? Offline
                  A Former User
                  wrote on last edited by A Former User
                  #9

                  Interesting @TDHound. A bit beyond my understanding, but I guess you can do anything with the native window exposed if you know what you are doing.

                  I tried out your code. I had to make some adjustments to make it work:

                  #ifdef Q_OS_WIN
                  #include <windows.h> // Fixes error C1189: #error :  "No Target Architecture"
                  #include <WinUser.h>
                  #include <windowsx.h>
                  #include <dwmapi.h>
                  #include <objidl.h> // Fixes error C2504: 'IUnknown' : base class undefined
                  #include <gdiplus.h>
                  #include <GdiPlusColor.h> 
                  #pragma comment (lib,"Dwmapi.lib") // Adds missing library, fixes error LNK2019: unresolved external symbol __imp__DwmExtendFrameIntoClientArea
                  #endif
                  

                  Qt4
                  This is what my result looks like in Qt4

                  Framless native windows Qt4

                  Qt5
                  Any idea if it can work in Qt 5 as well? "winEvent()" has been replaced in Qt5 with nativeEvent(), and I made it compile by making some changes.

                  bool MainWindow::nativeEvent(const QByteArray & eventType, MSG *msg, long *result) // Replaces winEvent()
                  
                  return QWidget::nativeEvent(eventType, msg, result); // Replaces winEvent()
                  

                  However it doesn't give the intended result.

                  Framless windows Qt5

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

                    See: https://bugreports.qt-project.org/browse/QTBUG-39268

                    1 Reply Last reply
                    0
                    • qwasder85Q Offline
                      qwasder85Q Offline
                      qwasder85
                      wrote on last edited by
                      #11

                      Whenever you use the FramelessWindowHint, you lose all Windows frame related features, such as docking, shortcuts, maximizing, etc.
                      You can implement some of them yourself, with great effort in some cases, other things will still just not work. Example: A frameless window cannot be maximized, it will instead go fullscreen, hiding the Windows task bar.
                      It's all a mess.

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        sbgk
                        wrote on last edited by
                        #12

                        That's why you explicitly override the native window style flags after setting Qt::FramelessWIndowHint. By restoring the style flags and handling the related native frame (nonclient area in Windows terms) events, you can have a custom frame (or no frame) and still retain the normal window behavior.

                        1 Reply Last reply
                        1

                        • Login

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