2016-05-07 4 views
1

Ich bin die QPainter::drawText() Funktion einer Qt5-Anwendung unter Windows. Mein Ziel ist es, das native Handle des Toplevel-Fensters zu identifizieren, auf das der Text gemalt wird. Zuerst erhalte ich das zugehörige Widget.Erste-Ebene-Fenster von Widget

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

So sollte es möglich sein, das entsprechende Top-Level-Fenster/Widget zu finden. Aber es ist schwieriger als ich dachte. Das habe ich bisher versucht:

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

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

Kein Erfolg. Der oberste Elternteil ist niemals das gewünschte Fenster.

QApplication::topLevelWidgets() 

zeigte mir, dass ein einzelne Fenster mehr Top-Level-Widgets (einschließlich dem ich suche) enthält.

Ich habe auch versucht QApplication::topLevelAt(widget->mapToGlobal(QPoint()))

In einigen Fällen ist dies tatsächlich funktioniert, aber nicht zuverlässig. Je nach Text und Fensterposition bekomme ich eine AccessViolationException, , also ist dies keine Option.

Durch Testen widget->testAttribute(Qt::WA_NativeWindow) fand ich heraus, dass die meisten Widgets nicht native Alien Widgets sind.

So bekomme ich das (was ich nenne) Top-Level-Fenster.

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

Dann prüfe ich die Fenstertitel die Griffe finden Ich habe Interesse an.

Ich bin nicht in der Lage eine Beziehung von jedem (Low-Level) Widget in die (Top-Level zu finden) Widget, das den Fenstertitel enthält.

+1

Zur Verdeutlichung: Suchen Sie nach dem Handle des ersten "Container 'Client'" oder Ihres "Top-Level-Window"? Können Sie Code anzeigen oder beschreiben, wie sich Ihre "Top-Level-Widgets" auf dieses einzelne Fenster beziehen? – JKSH

+0

Bitte beachten Sie, dass die Verwendung der Windows-API oder eines Dienstprogramms eines Drittanbieters zum Zeichnen in Qt höchstwahrscheinlich nicht zuverlässig funktioniert, wenn Sie nicht ein natives Widget einbetten und darauf malen. –

+0

Ich möchte nichts zeichnen. Ich fange die gesamte Textausgabe der Anwendung ab und vergleiche jede Zeichenfolge mit einigen Schlüsselwörtern. Wenn ich eine Übereinstimmung finde, möchte ich sie einem der geöffneten Fenster der Anwendung zuordnen. – m1st4x

Antwort

1

Es ist fertig! Ich habe eine Lösung für mein Problem gefunden.

Jedes Fenster hat seinen eigenen Thread.

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

Damit ich EnumThreadWindows eine Liste aller Fenstergriffe durch diesen Thread erstellt zu bekommen.

Schließlich überprüfe ich, ob widget->effectiveWinId() in der Liste ist.

So kann ich jedes Widget zum entsprechenden Fenster zuordnen!

3

Für die QWidget, die als Top-Level-Fenster fungiert, call QWidget::window().

Für das nächste übergeordnete Element mit einem systemeigenen Handle, call QWidget::nativeParentWidget().

Aufruf winId()zwingt das Widget, ein natives Fensterhandle zu erwerben, wenn es kein hat, was nicht Ihr Ziel ist. Ein Top-Level-Fenster wird immer eine native ID haben, also (HWND)window()->winId() ist in Ordnung. Beachten Sie, dass dies ist, normalerweise das gleiche wie calling QWidget::effectiveWinId().

+0

Sehr guter Hinweis! Wenn Sie mit nicht-nativen (Alien-) Widgets arbeiten, vermeiden Sie QWidget :: winId() zu Debugging-Zwecken, wie ich es tat: P – m1st4x

+0

Ja. 'widget-> nativeParentWidget() -> effectiveWinId()' gibt mir das nächste native Eltern-Handle. Aber leider ist es nie das gewollt :( – m1st4x

Verwandte Themen