2

我想在 Windows 中嵌入一个 Qt 应用程序(不是相反,因为许多其他问题已经得到解答)。为了澄清我有一个 win32 应用程序,我启动了一个 qt python 进程;这个 qt python 进程必须嵌入到 win32 应用程序中。如何才能做到这一点?在 API for 中QWindow::fromWinId,它明确指出:

“创建由另一个进程或使用 Qt 下面的本机库创建的窗口的本地表示......”

“......这可以在支持它的平台上使用,将 QWindow 嵌入到本机窗口中,或将本机窗口嵌入到 QWindow 中。”

其次QWidget::createWindowContainer似乎只适用于在 Qt 中嵌入本机窗口(不是我想要的方式)。

我不确定我将如何创建一个QWidgetinside QWindow。从这个问题来看,似乎方法是QQuickView用 a 创建 a QWindow::fromWinId;但是,我似乎找不到如何将 QWidget 绑定到 QQuickView 中。

目前我实际上正在设置父级,::SetParent但是有一些奇怪的消息传递协议要处理,所以我想尝试用 Qt 的方法重构它。

到目前为止编写的一些基本代码(PySide2,但 C++ 或任何其他具有 Qt 绑定的语言都可以):

app = QApplication(sys.argv)
hwnd = int(sys.argv[1], 16)

nativeParentWindow = QWindow.fromWinId(hwnd)
quickview = QQuickView(nativeParentWindow)

# this part is incorrect (tries to embed native window into qt)
# I want this application to run embedded inside hwnd
wrongWidget = QWidget.createWindowContainer(quickview)
wrongWidget.show()

sys.exit(app.exec_())
4

1 回答 1

2

首先,您需要从 HWND 创建一个 QWindow 以便 Qt 可以处理它:

// C++
QWindow *nativeWindow = QWindow::fromWinId(hwnd);
// Python
nativeWindow = QWindow.fromWinId(hwnd);

然后创建 Qt Widget 界面:

// C++
QLabel *label = new QLabel("Hello from Qt");
label->show();
// Python
label = QLabel("Hello from Qt");
label.show();

然后将 Qt Widget 界面的顶部窗口作为原生窗口的父窗口:

// C++
label->windowHandle()->setParent(nativeWindow);
// Python
label.windowHandle().setParent(nativeWindow);

但是,您不能使用 Qt 来监听 HWND 窗口中的变化。引用Qt 文档

注意:生成的 QWindow 不应该用于操作底层的原生窗口(除了重新设置),或者观察原生窗口的状态变化。对此类操作的任何支持都是偶​​然的、高度依赖于平台且未经测试的。

在实践中,信号QWindow::widthChanged()QWindow::heightChanged()没有发出。

如果你想监听来自 HWND 的事件,你必须使用本地 Win32 方式使用SetWindowsHookEx()or SetWinEventHook()

如果您对调整大小事件感兴趣,您可以在 C 或 C++ 中进行:

targetHwnd = hwnd; // defined on global scope
DWORD processId;
DWORD threadId= GetWindowThreadProcessId(hwnd, &processId);
HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, 0, &Wineventproc, processId, threadId, WINEVENT_OUTOFCONTEXT);

具有以下内容Wineventproc

void WINAPI Wineventproc(
  HWINEVENTHOOK hWinEventHook,
  DWORD event,
  HWND hwnd,
  LONG idObject,
  LONG idChild,
  DWORD idEventThread,
  DWORD dwmsEventTime
)
{
    if(targetHwnd == hwnd) { // Filter events that are not for our window
        qDebug() << "event" << event;
        RECT rect;
        GetWindowRect(hwnd, &rect);
        qDebug() <<  "Height:" << rect.bottom - rect.top;
        qDebug() <<  "Width:" << rect.right - rect.left;
    }
}
于 2019-07-24T22:15:32.907 回答