在 Windows 上可以通过 Qt API 实现吗?我需要这样的功能/行为因为我想将我的 Qt 代码作为插件集成到第 3 方应用程序中,并且我希望尽可能无缝地进行。例如,我不想在任务栏上有另一个项目代表我的 Qt 窗口。我说的是单进程应用程序。
我找到了一种使用 WinAPI 和 HWND 的方法:
// The Qt frame is "alien". We need its HWND so transform it (and all its ancestors,
// which is probably fine for me) to a "native" widget first.
Q_ASSERT(!frame->testAttribute(Qt::WA_NativeWindow));
frame->setAttribute(Qt::WA_NativeWindow);
Q_ASSERT(frame->testAttribute(Qt::WA_NativeWindow));
// Get the HWND.
QWindow* frameHandle = frame->windowHandle();
Q_ASSERT(frameHandle);
HWND frameHwnd = HWND(frameHandle->winId());
Q_ASSERT(frameHwnd);
// And use it to set the frame's "owner" (not "parent" because WS_CHILD bit is not set).
Q_ASSERT((GetWindowLongPtr(frameHwnd, GWL_STYLE) & WS_CHILD) == 0);
SetWindowLongPtr(frameHwnd, GWLP_HWNDPARENT, LONG_PTR(getOtherNonQtWindowHwnd()));
如果在显示框架之后完成,这似乎会按预期工作。但这样的解决方案有点奇怪,恐怕更危险。此外,设置可能会在以后随时被 Qt 本身覆盖。
如上面的代码片段所示,我能够检索第 3 方应用程序主窗口的 HWND。所以一般来说,从 WinAPI 的角度来看,它应该是可行的。拜托,有一些 Qt 方法可以做到这一点吗?或者至少是更好的解决方案?
最佳答案
另一种方法是将您的代码公开为 ActiveX 控件,使用 ActiveQt模块。这样,Qt 将为您处理所有细节问题。
您的解决方案也很好。这是您可以获得的最“Qt”的方式。有两个挑剔:
由于 Qt 负责子窗口的生命周期,因此您不能设置所有者。改为设置父级。在这种情况下,由您来设置
WS_CHILD
样式 - 毕竟,您要将窗口设置为子窗口。框架
不应有任何祖先窗口作为开头。您必须确保框架有自己的窗口。
因此:
bool reparentToNativeWindow(QWidget * widget, HWND newParent) {
widget->setWindowFlags(Qt::Window);
if (!widget->testAttribute(Qt::WA_NativeWindow));
widget->setAttribute(Qt::WA_NativeWindow);
auto childHandle = widget->windowHandle();
if (!childHandle)
return false;
auto child = HWND(widgetHandle->winId());
if (!child)
return false;
auto style = GetWindowLongPtr(child, GWL_STYLE);
if (!style)
return false;
if ((style & WS_CHILD) == 0) {
Q_ASSERT(style & WS_POPUP);
style &= ~WS_POPUP;
style |= WS_CHILD;
if (SetWindowLongPtr(child, GWL_STYLE, style) == 0)
return false;
}
SetParent(child, newParent);
}
关于c++ - 单个进程内其他非Qt窗口使Qt顶层窗口 "owned",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43789620/