在QApplication上使用Windows::SetParent时GUI冻结



这是关于两个Qt程序在Windows下的通信。一个程序,我们叫他客户端,另一个程序叫服务器。情况:我想把客户端放在服务器的QWidget中。Windows已经提供了一些很好的方法来删除装饰(边框、标题栏等(和更改窗口的父级,因此重新绘制、调整大小和激活窗口都由Windows负责。当我使用QProcess启动我的客户端时,我会等待它启动,这样就有一个窗口可以与我交谈。然后我删除装饰,并将服务器的QWidget设置为父级。所有这些都用这个代码完成:

winHandle = ::FindWindowA(NULL, "My Client");//get clients window id
if(winHandle != NULL)
{
   ::ShowWindow(winHandle, SW_HIDE);
    // Remove the window border
    LONG lStyle = GetWindowLong(winHandle, GWL_STYLE);
    lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU); 
    ::SetWindowLong(winHandle, GWL_STYLE, lStyle);
    ::SetParent(winHandle, (HWND)(ui->widget->effectiveWinId()));//set the server's widget to be the parent of the client win
    ::SetWindowPos(winHandle, HWND_TOP, ui->widget->pos().x(), ui->widget->pos().y(), 0, 0 , SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
     ::UpdateWindow(winHandle);
     ::ShowWindow(winHandle, SW_SHOW);
 }

这一切都很完美,我的客户很好地放在了我的标签上,所有的重新喷漆等都很完美。但是,我面临的问题是,有时(并非总是!(服务器的按钮没有响应。我注意到,当发生这种情况时,只要按钮位于屏幕中间,按钮就不会响应。但是,最奇怪的是,如果我移动整个窗口,使按钮靠近屏幕边缘,它们就会工作!如果我把它移回中心,它们就会再次停止工作。知道吗??某人

我还尝试了以下代码:

        QWindow * window = QWindow::fromWinId((WId) winHandle);
        QWidget * widget = QWidget::createWindowContainer(window);
        widget->setParent( ui->widget);
        QVBoxLayout *layout = new QVBoxLayout();
        layout->addWidget(widget);     
        ui->widget->setLayout(layout);

有了这个解决方案,GUI没有冻结,但键盘现在在客户端窗口(内部窗口(中无法工作。例如,如果内部窗口是记事本,我不能在里面打字,但我可以使用鼠标。知道能做什么吗?

您可以尝试通过为本机窗口获取QWindow,然后为其创建QWidget包装来实现这一点。这至少需要Qt 5.2。

例如:

HWND winHandle = ::FindWindowA(NULL, "My Client");
if (! winHandle) return;
QWindow * window = QWindow::fromWinId((WId)winHandle);
if (! window) return;
QWidget * widget = QWidget::createWindowContainer(window);
if (! widget) return;
// At this point you can use Qt to change window flags, reparent/embed, etc.

您需要询问winHandle的最小和最大大小,并将其传递给widget。如果您打算与widget交互,您还需要允许它是可聚焦的。

清除要重新排序的窗口的WS_POPUP样式,改为设置WS_CHILD位。否则,我认为SetParent实际上建立了一种所有者/所有者关系,而不是父母/子女关系。

重新定位子对象时,它应该位于父对象的客户端坐标中。您使用屏幕坐标这一事实很好地表明您没有合适的父子关系。(这也与在屏幕左上角附近工作的UI一致,屏幕坐标将非常接近客户端坐标。(

尽管有负面评论,但通过跨流程的父/子窗口,一切都可以正常工作。也就是说,要把它做好可能是一项挑战。

相关内容

  • 没有找到相关文章

最新更新