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. Customize window frame
Forum Updated to NodeBB v4.3 + New Features

Customize window frame

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 8 Posters 46.0k 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.
  • A Offline
    A Offline
    Adelost
    wrote on 11 Apr 2013, 19:44 last edited by A Former User
    #1

    Is it somehow possible to customize the window frame?

    Such as changing the color to make it more similar to the new look of Photoshop and Visual Studio 2012.

    Customize Qt window frame

    1 Reply Last reply
    1
    • B Offline
      B Offline
      bodzio131
      wrote on 11 Apr 2013, 19:58 last edited by
      #2

      Probably QStyle class is what you are looking for.

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on 11 Apr 2013, 20:17 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 11 Apr 2013, 20:23 last edited by
          #4

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

          1 Reply Last reply
          0
          • A Offline
            A Offline
            Adelost
            wrote on 12 Apr 2013, 05:30 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
            • R Offline
              R Offline
              raven-worx
              Moderators
              wrote on 12 Apr 2013, 07:20 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 12 Apr 2013, 07:29 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
                • T Offline
                  T Offline
                  TDHound
                  wrote on 24 May 2014, 09:22 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
                  • A Offline
                    A Offline
                    Adelost
                    wrote on 24 May 2014, 11:33 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
                    • T Offline
                      T Offline
                      TDHound
                      wrote on 24 May 2014, 16:41 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 12 Jan 2017, 08:10 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 17 Feb 2017, 20:14 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 Extensions
                          • Unsolved