1

这是关于Windows下两个Qt程序的通信。一个程序,我们称他为客户端,另一个程序,称为服务器。情况:我想将客户端放在服务器的 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 没有冻结,但键盘现在在客户端窗口中不起作用 - 在内部窗口中。例如 - 如果内部窗口是记事本 - 我不能在里面输入,但我可以使用鼠标。知道可以做什么吗?

4

2 回答 2

0

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

当您重新定位孩子时,它应该在父母的客户坐标中。您使用屏幕坐标这一事实很好地暗示了您没有正确的父/子关系。(这也与在屏幕左上角附近工作的 UI 一致,屏幕坐标将非常接近客户端坐标。)

尽管有负面评论,但可以使一切都与跨进程父/子窗口一起工作。也就是说,要做到正确可能具有挑战性

于 2014-06-09T20:32:56.177 回答
0

您可以尝试通过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如果您打算与它交互,您还需要允许它是可聚焦的。

于 2014-06-09T18:32:31.783 回答