c++ - 单个进程内其他非Qt窗口使Qt顶层窗口 "owned"

标签 c++ qt winapi hwnd

在 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”的方式。有两个挑剔:

  1. 由于 Qt 负责子窗口的生命周期,因此您不能设置所有者。改为设置父级。在这种情况下,由您来设置 WS_CHILD 样式 - 毕竟,您要将窗口设置为子窗口。

  2. 框架 不应有任何祖先窗口作为开头。您必须确保框架有自己的窗口。

因此:

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/

相关文章:

c++ - glClear() 不工作

qt - 项目未正确分布在 GridLayout 中

c++ - 如何判断一个线程是否有消息队列?

c# - 从 c++ DLL 和 c# 中释放 SAFEARRAY

c++ - Windows SetThreadAffinityMask 无效

c++ - 从 Visual Studio 2008 链接的 SimpleITK

c++ - 如何将Qt文件路径从资源路径转换为绝对路径?

c++ - 跨整个项目方法的单例类

c - 在跨 dll 边界访问导出的全局变量时检测缺少的 __declspec(dllimport)

c++ - win32 API函数GetModuleFileName或GetModuleHandle中的 "Module"是什么?