Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-40578

Windows: Painting/resizing issues with windows made frameless by handling WM_NCCALCSIZE

    XMLWordPrintable

Details

    • Workaround for frameless case: 2df293267ee3cdc111191dad2f3551d9fa05c88d (qtbase/5.4, 5.12.2014, 5.4.1), reimplementation: c9e1cf516fdce567e54b5d5f4ea9d44164b3e28c (qtbase/dev, 20.,11.2016, 5.9)

    Description

      In the example, the window is made frameless by handling WM_NCCALCSIZE to return 0 margins in conjunction with style=WS_THICKFRAME (additionally implementing hit tests to obtain resize handles) This ensures Aero left snap (Windows Key + Left Arrow) still works as opposed to using plain Qt::FramelessWindowHint .

      mainwindow.cpp
      #include "mainwindow.h"
      #include <QApplication>
      #ifdef Q_OS_WIN
      #include <Windows.h>
      #include <windowsx.h>
      #endif //Q_OS_WIN
      
      MainWindow::MainWindow(QWidget *parent)
          : QWidget(parent)
      {
          setStyleSheet("background-color: rgb(83, 83, 83);");
      }
      
      void MainWindow::showEvent(QShowEvent *event)
      {
          QWidget::showEvent(event);
      #ifdef Q_OS_WIN
          windowBorderless();
      #endif
      }
      
      #ifdef Q_OS_WIN
      void MainWindow::windowBorderless()
      {
          if (isVisible())
          {
              SetWindowLong((HWND)winId(), GWL_STYLE,
                            GetWindowLong((HWND)winId(), GWL_STYLE) & ~WS_CAPTION);
              SetWindowPos(reinterpret_cast<HWND>(winId()), NULL, 0, 0, 0, 0,
                           SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
                           SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
          }
      }
      
      bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
      {
          MSG *msg = static_cast<MSG *>(message);
          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((HWND)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;
                  }
              }
      
              if (*result != 0)
                  return true;
      
              QWidget *action = QApplication::widgetAt(QCursor::pos());
              if (action == this){
                  *result = HTCAPTION;
                  return true;
              }
              break;
          } //end case WM_NCHITTEST
          }
      
          return QWidget::nativeEvent(eventType, message, result);
      }
      #endif //Q_OS_WIN
      
      

      Run result:

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              kleint Friedemann Kleint
              flucheng fenglc
              Votes:
              2 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes