[英]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.