Details
-
Bug
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
6.2.3
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 !