【问题标题】:Getting top-level window by widget通过小部件获取顶级窗口
【发布时间】:2016-05-07 23:03:19
【问题描述】:

我正在挂钩 Windows 上 Qt5 应用程序的 QPainter::drawText() 函数。 我的目标是识别绘制文本的顶级窗口的本机句柄。首先,我得到了相关的小部件。

QWidget *widget = static_cast<QWidget *>(painter->device());

所以应该可以找到对应的顶级窗口/小部件。 但这比我想象的要难。这是我迄今为止尝试过的:

while (widget->parentWidget())
    widget = widget->parentWidget();

HWND hwnd = (HWND) widget->winId();

没有成功。上父级永远不是所需的窗口。

QApplication::topLevelWidgets()

向我展示了一个窗口包含多个顶级小部件(包括我正在寻找的那个)。

我也试过QApplication::topLevelAt(widget-&gt;mapToGlobal(QPoint()))

在某些情况下,这确实有效,但并不可靠。 根据文本和窗口位置,我得到一个AccessViolationException, 所以这不是一个选择。

通过测试widget-&gt;testAttribute(Qt::WA_NativeWindow) 我发现大多数小部件都是非原生的Alien Widgets

这就是我获得(我称之为)顶级窗口的方式。

WinAPI.EnumChildWindows(
    WinAPI.GetDesktopWindow(),
    new EnumWindowsProc(this.EnumWindowsCallback), 0);

然后我检查窗口标题以找到我感兴趣的句柄。

我无法找到从任何(低级)小部件到包含窗口标题的(顶级)小部件的关系。

【问题讨论】:

  • 澄清一下:您是在寻找第一个“Container 'Client'”的句柄,还是您的“Top-Level-Window”?您能否展示一些代码或描述您的“顶级小部件”与该单个窗口的关系?
  • 请注意,使用 Windows API 或第三方实用程序在 Qt 中进行绘制不太可能可靠地工作,除非您嵌入本机小部件并在其上进行绘制。
  • 我不想画任何东西。我正在截取应用程序的整个文本输出并将每个字符串与一些关键字进行比较。如果找到匹配项,我想将其映射到应用程序打开的窗口之一。
  • 我没有任何我正在拦截的应用程序的源代码。

标签: c++ qt hook


【解决方案1】:

对于充当顶级窗口的QWidgetcall QWidget::window()

对于最近的具有本机句柄的父级,call QWidget::nativeParentWidget()

调用winId() 强制小部件获取本地窗口句柄(如果它没有),这不是您的目标。顶级窗口总是有一个本地 id,所以(HWND)window()-&gt;winId() 很好。请注意,这通常calling QWidget::effectiveWinId() 相同。

【讨论】:

  • 很好的提示!因此,如果您处理非本地(外来)小部件,请避免使用 QWidget::winId() 进行调试,就像我所做的那样:P
  • 是的。 widget-&gt;nativeParentWidget()-&gt;effectiveWinId() 给了我最近的本地父句柄。但不幸的是,它从来都不是想要的:(
【解决方案2】:

完成了!我找到了解决问题的方法。

每个窗口都有自己的线程。

int threadId = WinApi.GetWindowThreadProcessId(wndHandle, IntPtr.Zero)

我用它EnumThreadWindows 获取此线程创建的所有窗口句柄的列表。

最后我检查了widget-&gt;effectiveWinId() 是否在列表中。

所以我可以将每个小部件映射到其对应的窗口!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-24
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 2012-04-03
    相关资源
    最近更新 更多