簡體   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