Reputation: 31
I'm hooking the QPainter::drawText()
function of a Qt5 application on Windows.
My goal is to identify the native handle of the top-level-window to which the text is painted. First, I'm getting the associated widget.
QWidget *widget = static_cast<QWidget *>(painter->device());
So it should be possible to find the corresponding top-level window/widget. But it's harder than I thought. This is what I tried so far:
while (widget->parentWidget())
widget = widget->parentWidget();
HWND hwnd = (HWND) widget->winId();
No success. The top-parent is never the desired window.
QApplication::topLevelWidgets()
Showed me that one single window contains several top-level-widgets (including the one I'm looking for).
I also tried QApplication::topLevelAt(widget->mapToGlobal(QPoint()))
In some cases this actually works, but not reliably.
Depending on text and window position I'm getting a AccessViolationException
,
so this is not an option.
By testing widget->testAttribute(Qt::WA_NativeWindow)
I found out that most of the widgets are non-native Alien Widgets.
This is how I get the (what I call) top-level window.
WinAPI.EnumChildWindows(
WinAPI.GetDesktopWindow(),
new EnumWindowsProc(this.EnumWindowsCallback), 0);
Then I check the window titles to find the handles I'm interested in.
I'm not able to find a relation from any (low-level) widget to the (top-level) widget that holds the window title.
Upvotes: 2
Views: 7241
Reputation: 31
It's done! I found a solution for my problem.
Each windows has it's own thread.
int threadId = WinApi.GetWindowThreadProcessId(wndHandle, IntPtr.Zero)
With it I use EnumThreadWindows to get a list of all window-handles created by this thread.
Finally I check wheather widget->effectiveWinId()
is in the list.
So I can map each widget to its corresponding window!
Upvotes: 1
Reputation: 4367
For the QWidget
that acts as a top level window, call QWidget::window()
.
For the nearest parent with a native handle, call QWidget::nativeParentWidget()
.
Calling winId()
forces the widget to acquire a native window handle if it does not have one, which isn't your goal. A top level window will always have a native id, so (HWND)window()->winId()
is fine. Note that this is usually the same as calling QWidget::effectiveWinId()
.
Upvotes: 4