繁体   English   中英

通过小部件获取顶层窗口

[英]Getting top-level window by widget

我挂在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->mapToGlobal(QPoint()))

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

通过测试widget->testAttribute(Qt::WA_NativeWindow)我发现大多数小部件都是非本地Alien Widgets

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

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

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

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

对于QWidget充当顶层窗口, 调用QWidget::window()

对于具有本地句柄的最近的父级, 请调用QWidget::nativeParentWidget()

调用winId() 强制窗口小部件获取本机窗口句柄(如果它没有窗口句柄) ,这不是您的目标。 顶层窗口将始终具有本机ID,因此(HWND)window()->winId()很好。 请注意,这通常调用QWidget::effectiveWinId()

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

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

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

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

最后,我检查了清单中的widget widget->effectiveWinId()

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM