简体   繁体   English

创建QWidget宽度为HWND的父对象

[英]create QWidget width HWND parent

OS Windows. 操作系统Windows。 Qt 5.5.1 I made library (dll) with GUI on Qt. Qt 5.5.1我在Qt上使用GUI制作了库(dll)。 I connected it to new project. 我将其连接到新项目。 I have parent's hwnd. 我有父母的房子。 How to set parent for library-window (Qwidget)? 如何设置库窗口(Qwidget)的父级? If use winapi SetParent(), then child window does not leave bounds the parent window. 如果使用winapi SetParent(),则子窗口不会超出父窗口的范围。 I tried QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow), but it is not working, because according to documentation the parameter window is ignored in Qt 5. 我尝试了QWidget :: create(WId window,bool initializeWindow,bool destroyOldWindow),但是它不起作用,因为根据文档,在Qt 5中会忽略参数window。

Unfortunately, this is a long-running issue with Qt on Windows (and other platforms). 不幸的是,这是Windows(和其他平台)上Qt的长期运行问题。 You'll have to find a way to hook into the parent window to catch mouse and keyboard events, etc. to propagate to your Qt child window. 您将必须找到一种挂接到父窗口的方法,以捕获鼠标和键盘事件等,以传播到Qt子窗口。 The internal Qt code for this is perpetually a work in progress. 内部的Qt代码永远都在进行中。

There's a good page about these issues and the subject in general here . 关于这些问题和总体主题, 这里有一个不错的页面。 Here's the bug report discussing the issue, as well. 这也是讨论该问题的错误报告

Note: QAxWidget isn't exactly helpful, either. 注意: QAxWidget也不完全有用。 It looks promising, but suffers the same issues with event propagation. 它看起来很有希望,但是在事件传播方面也遇到了同样的问题。

I found a way that works, but there are unknown messages on the screen 我找到了一种可行的方法,但是屏幕上有未知消息

windowsProc: No Qt Window found for event 0x24 (WM_GETMINMAXINFO), hwnd=0x0x110956.
windowsProc: No Qt Window found for event 0x83 (WM_NCCALCSIZE), hwnd=0x0x110956.
windowsProc: No Qt Window found for event 0x5 (WM_SIZE), hwnd=0x0x110956.
windowsProc: No Qt Window found for event 0x3 (WM_MOVE), hwnd=0x0x110956.
setGeometryDp: Unable to set geometry 640x480+0+0 on QWindow/''. Resulting geometry:  640x480+-760+-370 (frame: 8, 30, 8, 8, custom margin: 0, 0, 0, 0, minimum size: 0x0, maximum size: 16777215x16777215).
setGeometryDp: Unable to set geometry 640x480+0+0 on QWindow/''. Resulting geometry:  640x480+-760+-370 (frame: 8, 30, 8, 8, custom margin: 0, 0, 0, 0, minimum size: 0x0, maximum size: 16777215x16777215).
listLabels.size() 4

Let a parent window be an ownerWin, and a child one QWidget-window named childWin; 假设父窗口为ownerWin,子窗口为QWidget窗口,名为childWin;

If to use SetWindowLongPtr, the desirable result is achieved (the child window overlaps the parent one), but the child window still is in the memory when the parent window closes. 如果使用SetWindowLongPtr,则可以达到预期的效果(子窗口与父窗口重叠),但是当父窗口关闭时,子窗口仍在内存中。

To fix a problem I create one more child window (middleWin with a parent ownerWin.) using WinApi. 为了解决问题,我使用WinApi创建了另一个子窗口(带有父ownerWin的MiddleWin)。 After wrapping this window with QWidget using createWindowContainer() it stops working normally. 使用createWindowContainer()使用QWidget包装此窗口后,它将停止正常工作。 Then using standard Qt methods we can link our QWidget window. 然后,使用标准的Qt方法,我们可以链接我们的QWidget窗口。 So we have three windows: parent, intermediate and mine. 因此,我们有三个窗口:父窗口,中间窗口和我的窗口。 Then I close middleWin using close().All that manipulations needs to insure that when ownerWin closes, also childWin closes as well. 然后我使用close()关闭middleWin。所有这些操作都需要确保ownerWin关闭时,childWin也关闭。 If SetWindowLongPtr is used, then childWin will always be above the parent window, but it works only if called after function show() in child window. 如果使用SetWindowLongPtr,则childWin将始终位于父窗口上方,但仅在子窗口中的函数show()之后调用时,它才起作用。

Below are the functions I use. 以下是我使用的功能。 First call setWinParent(), then showWindow(). 首先调用setWinParent(),然后调用showWindow()。 In setWinParent() lines 1 through 5 is "black box" for me. 在setWinParent()中,第1到5行对我来说是“黑匣子”。 I don't know why window is created that way. 我不知道为什么以这种方式创建窗口。

void setWinParent(HWND ownerWin)
{
    HWND hwnd = (HWND)this->winId();
    DWORD exStyle = GetWindowLong(hwnd, GWL_EXSTYLE) ;//1
    DWORD style   = GetWindowLong(hwnd, GWL_STYLE);//2
    WCHAR className[256];//3
    GetClassName(hwnd, className,256);//4
    HWND newHwnd = CreateWindowEx(exStyle, className, NULL, style,//5
                                  CW_USEDEFAULT, CW_USEDEFAULT,
                                  CW_USEDEFAULT, CW_USEDEFAULT,
                                  ownerWin, NULL, qWinAppInst(), NULL);
    QWindow *qw=QWindow::fromWinId((WId)newHwnd);
    QWidget* qWidget = createWindowContainer(qw);
    qWidget->show();
    this->setParent(qWidget);
    this->setWindowFlags(Qt::Window);
    qWidget->close();    
}
void showWindow(HWND ownerHwnd)
{
    show();
    SetWindowLongPtr((HWND)this->winId(), GWLP_HWNDPARENT, (LONG)ownerHwnd);
}

The parameter window is ignored in Qt 5. Please use QWindow::fromWinId() to create a QWindow wrapping a foreign window and pass it to QWidget::createWindowContainer() instead. Qt 5中将忽略参数window。请使用QWindow :: fromWinId()创建一个包装外部窗口的QWindow,并将其传递给QWidget :: createWindowContainer()。

What's unclear about the Qt documentation? Qt文档尚不清楚吗?

QWindow *wndParent = QWindow::fromWinId(hwnd); // hwnd - your WId
if(wndParent) 
{
    QWidget *parent = QWidget::createWindowContainer(wndParent);
    if(parent)
        // ...
}
else
{
    // unsupported window...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM