在 QApplication 上使用 Windows::SetParent 时 GUI 冻结 [英] GUI freeze when using Windows::SetParent on QApplication

查看:125
本文介绍了在 QApplication 上使用 Windows::SetParent 时 GUI 冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

It is about the communication two Qt programs under Windows. One program, let's call him Client, The other program, called Server. The situation: I want to place the Client inside a QWidget of the server. Windows already supplies some nice methods for removing the decoration (border,title bar etc..) and change the parent of a window so repainting, resizing, window activation is all taken care by Windows. When I start my Client using a QProcess I wait for it to be launched, so that there is a window I can talk to. Then I remove the decoration and set the QWidget of the Server as parent. All done with this code:

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);
 }

这一切都完美无缺,我的客户端很好地放置在我的选项卡顶部,所有重新绘制等都完美无缺.但是,我面临的问题是有时(并非总是如此!)服务器的按钮没有响应.我注意到当发生这种情况时,按钮不会响应只要它们位于屏幕中间.但是,最奇怪的是,如果我移动整个窗口,使按钮位于靠近屏幕边缘的位置 - 它们起作用了!如果我将它移回中心 - 他们会再次停止工作.任何想法??有人吗?

This all works perfectly, my Client is nicely placed on top of my tab and all the repainting etc. is working perfect. BUT, The problem I'm facing is that sometimes (not always!) the servers' buttons become not responding. I noticed that when such a case happens, the buttons don't respond as long as they are located in the middle of the screen. but, the weirdest thing is that if i move the whole window so the buttons are located close to the edge of the screen - they work! if i move it back to the center - they stop working again. any idea?? someone?

我也尝试了以下代码:

        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 不会冻结,但键盘现在在客户端窗口中不起作用 - 在内部窗口中.例如 - 如果内部窗口是记事本 - 我不能在里面打字,但我可以使用鼠标.知道可以做什么吗?

with this solution, the GUI didn't freeze but the keyboard doesn't work now in the client's window - in the internal window. for example - if the internal window is notepad - i cannot type inside it but i can use the mouse. any idea what can be done?

推荐答案

你可以尝试通过为原生窗口获取一个QWindow,然后创建一个QWidget来实现> 包装它.这至少需要 Qt 5.2.

You may try to do this by obtaining a QWindow for the native window, and then creating a QWidget wrapper for it. This needs at least 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 成为焦点.

You need to ask the winHandle about its minimum and maximum size and pass those onto the widget. You also need to allow the widget to be focusable if you intend to interact with it.

这篇关于在 QApplication 上使用 Windows::SetParent 时 GUI 冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆