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

Screen not detected in certain configuration

    XMLWordPrintable

Details

    • Windows

    Description

      Hi all !

      First QT is a great framework and diligently help for making app quicker!

      I've a problem with the screen detection with a specific multi-screen arrangement.

      My screens are configured this way :

      ************  ************
      * SCREEN 3 *  * SCREEN 2 *
      ************  ************
             ************
             * SCREEN 1 *
             ************
      

      Screen 1 is my laptop Screen and Screen 2 / 3 are external screen.

      When I try to detect screen using this code to show the Application in the screen containing the cursor :

      MainWindow w ;
          QPoint pos = QCursor::pos();
          for (int i = 0; i < QGuiApplication::screens().count();++i) {
              QScreen *screen = QGuiApplication::screens().at(i);
              QRect screenRect = screen->geometry();
              if (screenRect.contains(pos)) {
                   qDebug() << "Showing application on screen named '" << screen->name() << "' [index " << i << "]";
                   w.setGeometry(QStyle};
          }
          w.show();
      

      It works fine with Screen 1 and 3 but when cursor is inside Screen 2, it doesn't center the windows.
      More exactly, the screenRect.contains(pos) is never attained when the mouse is in Screen 2.

      The same way, my application have a dropdown combobox, clicking to show the dropdown works fine in Screen 1 and 3 but when the application is located in Screen 2, clicking to show the dropdown make the dropdown to appear on Screen 3, totally outside of the application, It's the same behaviour for right click menu.

      Strangely, when using a ColorPicker Dialog it's with different screen : When using the button 'Pick screen color', moving the cursor in Screen 1 and 2 show the color under the cursor but in Screen 3, it just show black color.

      These are my workaround :
      For the right click menu I have to modify the control_customContextMenuRequested this way :

      void
      MainWindow::on_FolioListeINFO_customContextMenuRequested(const QPoint& pos)
      {
          Q_UNUSED(pos);
          QMenu* menu = new QMenu(this);
      
          menu->addAction(QString("PDF Information"));
          menu->addSeparator();
          menu->addAction(QIcon(":/Copier"), QString(" Copy this line in the clipboard"), this, [&](bool) {
              QApplication::clipboard()->setText(ui->FolioListeINFO->currentItem()->text());
          });
          menu->actions()[0]->setEnabled(false);
          QCursor mCursor;
          POINT Mouse;
          GetCursorPos(&Mouse);
          mCursor.setPos(Mouse.x, Mouse.y);
          menu->popup(mCursor.pos());
          RECT ActualWindow;
          GetWindowRect((HWND)menu->winId(), &ActualWindow);
          MoveWindow((HWND)menu->winId(), Mouse.x, Mouse.y, (ActualWindow.right - ActualWindow.left), (ActualWindow.bottom - ActualWindow.top), TRUE);
      }
      

      For the dropdown problem, I subclassed the QComboBox / showPopup():

      #ifndef customQComboBox_H
      #define customQComboBox_H
      #include <QComboBox>
      #include <QWidget>
      #include <windows.h>
      
      class QComboBox_custom : public QComboBox
      {
        public:
          QComboBox_custom(QWidget* parent = nullptr) { this->setParent(parent); }
          virtual void showPopup()
          {
              QComboBox::showPopup();
              RECT ActualWindow;
              GetWindowRect((HWND)this->winId(), &ActualWindow);
              QWidget* popup = this->findChild<QFrame*>();
              MoveWindow((HWND)popup->winId(), ActualWindow.left, ActualWindow.top, popup->width(), popup->height(), true);
          }
      };
      #endif // customQComboBox_H
      

      Anf for showing / centering the window in the screen containing the cursor, I crezte a MonitorRecs structure to retrieve Windows screen and a CenteringByHWND function to cycle through the screen enumerated and detect if Cursor is inside :

          struct MonitorRects
          {
              QVector<RECT> rcMonitors;
              QVector<QString> qvName;
      
              static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
              {
                  Q_UNUSED(hdc);
                  MonitorRects* pThis = reinterpret_cast<MonitorRects*>(pData);
                  pThis->rcMonitors.push_back(*lprcMonitor);
                  MONITORINFOEXW miex;
                  miex.cbSize    = sizeof(MONITORINFOEXW); // set cbSize member
                  miex.rcMonitor = { 0, 0, 0, 0 };
                  miex.rcWork    = { 0, 0, 0, 0 };
                  if (GetMonitorInfoW(hMon, &miex)) {
                      pThis->qvName.push_back(QString::fromWCharArray(miex.szDevice));
                  };
                  return TRUE;
              }
      
              MonitorRects() { EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this); }
          };
      
      bool CenteringByHWND(HWND WindowHWND)
      {
          MainWindow::MonitorRects monitors;
          int NumScreen = 0;
          RECT WindowWithMouse;
          SetRect(&WindowWithMouse, 0, 0, 0, 0);
          foreach (auto var, monitors.rcMonitors) {
              POINT Mouse;
              GetCursorPos(&Mouse);
              RECT InterRect;
              RECT rMouse;
              SetRect(&rMouse, Mouse.x, Mouse.y, Mouse.x + 10, Mouse.y + 10);
              if (IntersectRect(&InterRect, &var, &rMouse) == TRUE) {
                  qDebug() << QString("Centering: Mouse inside screen n°%1 [%2]").arg(QString::number(NumEcran), monitors.qvName[NumScreen]);
                  SetRect(&WindowWithMouse, var.left, var.top, var.right, var.bottom);
              }
              NumScreen++;
          }
          if ((WindowWithMouse.right - WindowWithMouse.left) > 0) { // We can center
              RECT ActualWindow;
              GetWindowRect(WindowHWND, &ActualWindow);
              MoveWindow(WindowHWND,
                         /*Left*/ WindowWithMouse.left + ((WindowWithMouse.right - WindowWithMouse.left) /*Screen Width*/ / 2) -
                           ((ActualWindow.right - ActualWindow.left) /*Width*/ / 2),
                         /*top*/ WindowWithMouse.top + ((WindowWithMouse.bottom - WindowWithMouse.top) /*Screen height*/ / 2) -
                           ((ActualWindow.bottom - ActualWindow.top) /*Height*/ / 2),
                         /*width*/ ActualWindow.right - ActualWindow.left,
                         /*height*/ ActualWindow.bottom - ActualWindow.top,
                         TRUE);
          }
          return true;
      }
      

      I hope you understand me well, I'm French.

      Thanks QT Team !

      Attachments

        1. Color picker - Always black.png
          1.47 MB
          Grégory WENTZEL
        2. Color picker - Correct.png
          1.46 MB
          Grégory WENTZEL
        3. Dropdown correctly draw.png
          1.11 MB
          Grégory WENTZEL
        4. Dropdown outside screen.png
          1.43 MB
          Grégory WENTZEL

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            alwendya Grégory WENTZEL
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: