在本机中嵌入 Qt window (Windows)
Embed Qt inside native window (Windows)
我想在 Windows 中嵌入一个 Qt 应用程序(不是相反,因为已经回答了许多其他问题)。澄清一下,我有一个 win32 应用程序,我启动了一个 qt python 进程;此 qt python 进程必须嵌入到 win32 应用程序中。如何才能做到这一点?在 API for QWindow::fromWinId
中,它明确指出:
"Creates a local representation of a window created by another process or by using native libraries below Qt...."
"...This can be used, on platforms which support it, to embed a QWindow inside a native window, or to embed a native window inside a QWindow."
其次,QWidget::createWindowContainer
似乎只适用于在 Qt 中嵌入本机 windows(不是我想要的方式)。
我不确定如何在 QWindow
中创建 QWidget
。从这个 question 看来,方法是用 QWindow::fromWinId
创建一个 QQuickView
;但是,我似乎找不到如何将 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_())
首先,您需要从 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 界面的顶部 window 设置为原生 window:
// C++
label->windowHandle()->setParent(nativeWindow);
// Python
label.windowHandle().setParent(nativeWindow);
但是,您不能使用 Qt 来监听 HWND window 中的变化。引用 Qt documentation:
Note: The resulting QWindow should not be used to manipulate the
underlying native window (besides re-parenting), or to observe state
changes of the native window. Any support for these kind of operations
is incidental, highly platform dependent and untested.
实际上,信号 QWindow::widthChanged()
和 QWindow::heightChanged()
不会发出。
如果你想监听来自 HWND 的事件,你必须使用 SetWindowsHookEx()
或 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;
}
}
我想在 Windows 中嵌入一个 Qt 应用程序(不是相反,因为已经回答了许多其他问题)。澄清一下,我有一个 win32 应用程序,我启动了一个 qt python 进程;此 qt python 进程必须嵌入到 win32 应用程序中。如何才能做到这一点?在 API for QWindow::fromWinId
中,它明确指出:
"Creates a local representation of a window created by another process or by using native libraries below Qt...."
"...This can be used, on platforms which support it, to embed a QWindow inside a native window, or to embed a native window inside a QWindow."
其次,QWidget::createWindowContainer
似乎只适用于在 Qt 中嵌入本机 windows(不是我想要的方式)。
我不确定如何在 QWindow
中创建 QWidget
。从这个 question 看来,方法是用 QWindow::fromWinId
创建一个 QQuickView
;但是,我似乎找不到如何将 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_())
首先,您需要从 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 界面的顶部 window 设置为原生 window:
// C++
label->windowHandle()->setParent(nativeWindow);
// Python
label.windowHandle().setParent(nativeWindow);
但是,您不能使用 Qt 来监听 HWND window 中的变化。引用 Qt documentation:
Note: The resulting QWindow should not be used to manipulate the underlying native window (besides re-parenting), or to observe state changes of the native window. Any support for these kind of operations is incidental, highly platform dependent and untested.
实际上,信号 QWindow::widthChanged()
和 QWindow::heightChanged()
不会发出。
如果你想监听来自 HWND 的事件,你必须使用 SetWindowsHookEx()
或 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;
}
}