Gibt es eine Möglichkeit, um zuverlässig das "aktive" (am weitesten vorne angeordnete) Fenster innerhalb meiner Anwendung festzustellen?
Kurz gesagt, wenn meine Anwendung gerade ein Popup-Fenster anzeigt, dann soll dieses Popup-Fenster zurück geliefert werden, andernfalls soll das Hauptfenster zurückgeliefert werden.
Insbesondere darf das Ergebnis nicht davon abhängen, ob meine Anwendung (als Ganzes) gerade "im Vordergrund" ist.
Folgende "Lösung" klappt leider nicht:
Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
Es klappt aus zwei Gründen nicht:* Manche Popup-Fenster, wie z.B. ein OpenFileDialog
, sind überhaupt nicht in Application.Current.Windows
enthalten 😡
IsActive
ist nur true, wenn das Fenster "aktive" ist und meine Anwendung gerade "im Vordergrund" ist. Wenn hingegen gerade eine andere Anwendung "im Vordergrund" ist, dann ist IsActive
einfach mal für alle meine Fenster false 🙁Was die Win32 API angeht, hab eich folgendes schon probiert:* GetActiveWindow()
und GetFocus()
funktionieren aus dem selben Grund nicht. Sie liefern NULL zurück, wenn meine Anwendung nicht gerade "im Vordergrund" ist.
GetForegroundWindow()
hilft leider auch nicht weiter, da es ggf. Fenster zurück liefert, die zu anderen Anwendungen gehören...Ein Popup gehört technisch nicht _innerhalb _ Deiner Anwendung, sondern zum Betriebssystem (zumindest wenn wir von einem Win32 API ausgelösten Popup sprechen, wie Du es hier wohl meinst). Das System Popup wirst Du also niemals in Deiner Anwendung so auswerten können. Das würde nur gehen, wenn Du das Popup komplett selbst implementierst / steuerst.
Auch hilft Dir Foreground nicht, weil Foreground im Gegensatz zu Active das ganze System betrifft.
Daher würde ich anhand Deiner Beschreibung antworten: nein, Dein Wunsch ist mit Deinen Mitteln nicht möglich, weil das Betriebssystem so nicht funktioniert.
Den Rest hast schon rausgefunden.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Ein Popup gehört technisch nicht _innerhalb _ Deiner Anwendung, sondern zum Betriebssystem (zumindest wenn wir von einem Win32 API ausgelösten Popup sprechen, wie Du es hier wohl meinst). Das System Popup wirst Du also niemals in Deiner Anwendung so auswerten können. Das würde nur gehen, wenn Du das Popup komplett selbst implementierst / steuerst.
Nicht ganz. Das Popup-Fenster wird vllt. in manchen Fällen mit System-Funktionen wie GetOpenFileName()
oder GetSaveFileName()
erstellt, aber das Fenster "gehört" trotzdem meiner Anwendung.
Wenn ich z.B. ein OpenFileDialog
erzeuge und beim Aufruf von ShowDialog()
mein Hauptfenster als "Owner" festlege, dann wird das "OpenFileDialog" Popup-Fenster in der Fenster-Hierarchie ganz eindeutig ein untergeordnetes (Child) Fenster von meinem Hauptfenster. So lange das "OpenFileDialog" Popup-Fenster noch aktiv ist, kann man das Hauptfenster nicht mehr aktivieren – beim Anklicken des Hauptfensters wird automatisch das offene "OpenFileDialog" Popup-Fenster aktiviert bzw. in den Vordergrund gebracht.
Man kann auch mit Spy++ sich die Details von dem "OpenFileDialog" Popup-Fenster anschauen. Da ist eindeutig die Prozess-ID diejenige von meiner Anwendung und das zugehörige "Parent Window" ist das Hauptfenster meiner Anwendung.
Irgendwie müsste meine Anwendung doch also feststellen können, dass bzw. ob an ihrem Hauptfenster aktuell noch so ein Popup-Fenster dran hängt... 😉
Auch hilft Dir Foreground nicht, weil Foreground im Gegensatz zu Active das ganze System betrifft.
Leider betreffen GetActiveWindow()
und GetFocus()
eben auch das "ganze" System.
...nur mit dem Unterschied, dass diese Funktionen einfach NULL zurück geben, wenn das Fenster, dass sich gerade (systemweit) im Vordergrund befindet, nicht zu meiner Anwendung gehört. Tatsächlich gibt es aber ja, zu jedem Zeitpunkt, auch innerhalb meiner Anwendung ein "aktives" (am weitesten vorne angeordnetes) Fenster. Das ist das Fenster, welches dann (wieder) im Vordergrund sein wird, sobald der User wieder zu meiner Anwendung zurück wechselt.
Irgendwie müsste meine Anwendung doch also feststellen können, dass bzw. ob an ihrem Hauptfenster aktuell noch so ein Popup-Fenster dran hängt... 😉
Das hat nichts mit "innerhalb" der Anwendung zutun, sondern ist nur eine Prozesszordnung.
So kann zB auch das Betriebssystem das Popup abschießen, wenn Du Du hart den Prozess beendest.
Kann sein, dass Du es über die Prozesszuordnung bekommst; aber zumindest funktioniert so nicht das Window Handle Prinzip.
PS: Deine hunderte Bearbeitungen nerven sehr, überschneiden sich mit Antworten und bringen quasi keinen Mehwert.
Muss man erstmal warten, bis Du mit den Edits fertig bist, bis man ne Antwort abschickt...
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Das hat nichts mit "innerhalb" der Anwendung zutun, sondern ist nur eine Prozesszordnung.
So kann zB auch das Betriebssystem das Popup abschießen, wenn Du Du hart den Prozess beendest.Kann sein, dass Du es über die Prozesszuordnung bekommst; aber zumindest funktioniert so nicht das Window Handle Prinzip.
Es geht nicht (nur) um die Process-ID. Wenn Du versuchst das Hauptfenster anzuklicken, während gerade ein Popup-Dialog aktiv ist, dann geht das nicht.
Standessen wird sofort der aktive Popup-Dialog in den Vordergrund geholt, sobald Du das Hauptfenster anklickst.
Also, es ist somit doch offensichtlich, dass der Popup-Dialog als ein (modales) Child-Window an meinem Hauptfenster "angedockt" ist, in der Fenster-Hierarchie.
Die Frage ist jetzt, wie kann man aus dem Programmcode den HWND des aktiven Popup-Dialog bekommen, bzw. feststellen ob überhaupt so ein Popup-Dialog aktiv ist ???
Wie schon gesagt, Application.Current.Windows
ist leider unvollständig. Das selbe gilt übrigens auch für this.OwnedWindows
😉
Man kann mit EnumWindows()
alle vorhandenen Fenster bekommen. Leider liefert es tatsächlich die Fenster von allen Anwendungen auf dem System!
Okay, kann man mit GetWindowThreadProcessId()
ausfiltern, um nur die Fenster zu bekommen, die zum eigenen Prozess gehören.
Es bleiben immer noch ziemlich viele Fenster übrig, selbst wenn nur das Hauptfenster da ist. Keine Ahnung wieso ?!
Okay, ich kann mit GetParent()
noch weiter ausfiltern, um nur die die Fenster zu bekommen, deren Parent-Window mit meinem Hauptfenster identisch ist...
Das klappt! Mehr oder weniger. Es bleiben noch zwei HWND's übrig, solange nur das Hauptfenster da ist. Keine Ahnung was die sind.
Aber: Wenn ich den OpenFileDialog
öffne, kommen etliche HWND's dazu, die alle wieder verschwinden, sobald der OpenFileDialog
geschlossen wird 👍
Trotzdem ist es noch unklar, welche HWND's jetzt für ein "aktives" Popup-Fenster stehen...
Nur Hauptfenster:
EnumWindows()
--> hwnd: 265076
--> hwnd: 3016478
OpenFileDialog geöffnet:
EnumWindows()
--> hwnd: 723696
--> hwnd: 920094
--> hwnd: 920308
--> hwnd: 789242
--> hwnd: 723808
--> hwnd: 854842
--> hwnd: 789190
--> hwnd: 854762
--> hwnd: 2230372
--> hwnd: 265076
--> hwnd: 3016478
OpenFileDialog wieder geschlossen:
EnumWindows()
--> hwnd: 265076
--> hwnd: 3016478
Wenn Du versuchst das Hauptfenster anzuklicken, während gerade ein Popup-Dialog aktiv ist, dann geht das nicht.
Is mir schon bewusst.
Liegt daran, dass die Windows API im Hintergrund SetWindowPos function (winuser.h) - Win32 apps verwendet.
Wenn Du mir nicht glaubst, was Dein gutes Recht ist; schau Dir doch einfach Open Source Win32 / C++ Applikationen an, wie die mit den Fenster umgehen.
Vielleicht verstehst dann das Verhalten unter Windows einfach besser. Mehr kann ich da nun auch nicht mehr sagen...
Wenn Du eine Lösung, zB über Process Enumerations oder was auch immer findest, kannst das ja gern posten.
Aber ich halt mich in dem Thread wieder raus. Viel Erfolg 🙂
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Wenn Du mir nicht glaubst, was Dein gutes Recht ist; schau Dir doch einfach Open Source Win32 / C++ Applikationen an, wie die mit den Fenster umgehen.
Vielleicht verstehst dann das Verhalten unter Windows einfach besser. Mehr kann ich da nun auch nicht mehr sagen...
Eigentlich ist es ja nicht so kompliziert: Jedes Fenster, ausgenommen das "Top-Level" Fenster (Hauptfenster), hat ein Parent-Window (Owner) wo es sozusagen "angedockt" ist.
Außerdem "blockiert" ein Popup-Fenster (modaler Dialog) sein Parent-Window so lange, bis es wieder geschlossen wird.
Diese Beziehung zwischen den Fenstern hat erstmal nichts damit zu tun, welches Fenster oder welche Anwendung gerade auf dem Bildschirm (systemweit) im Vordergrund ist.
Ich wüsste nur gerne, wie ich in einer WPF-Anwendung feststellen kann, ob mein Hauptfenster gerade so ein aktives Popup-Fenster als Child besitzt, oder eben nicht.
Zur Erklärung: Ich benötige diese Information, um in meinem Hauptfensters bestimmte Events zu ignorieren, so lange ein Popup-Fenster aktiv ist.
...denn auch wenn das Hauptfenster gerade durch ein Popup-Dialog für den Benutzer "blockiert" ist, werden die Events in diesem Fenster trotzdem weiter verarbeitet!
Wie schon erwähnt, eigentlich würde this.OwnedWindows
genau diese Information bereitstellen, aber das klappt anscheinend nur mit Fenstern, die tatsächlich von WPF verwaltet werden (nicht mit OpenFileDialog
u.s.w.).
GetActiveWindow()
funktioniert nicht, weil es NULL zurück liefert, wenn gerade eine andere Anwendung als meine im Vordergrund ist.
EnumChildWindows()
liefert bei meinem Test nur eine leere Ergebnismenge zurück 😠
EnumWindows()
funktioniert im Prinzip. Aber es ist, wie schon weiter oben beschrieben, schwierig die "richtigen" HWND's aus den unzähligen HWND's, die man bekommt, raus zu filtern.
Zur Info, hier die Lösung:
GetWindow()
mit Parameter GW_ENABLEDPOPUP
liefert genau des gesucht Ergebnis 😉
private static IntPtr GetPopupWindow(IntPtr hWndParent)
{
if (hWndParent != IntPtr.Zero)
{
IntPtr hWndPopup = GetWindow(hWndParent, GW_ENABLEDPOPUP);
return (hWndPopup != hWndParent) ? hWndPopup : IntPtr.Zero;
}
return IntPtr.Zero;
}
public const uint GW_ENABLEDPOPUP = 6;
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, uint command);
🥳🥳🥳
Hallo Weressated, Hallo "Forum" !
Systemnah (Windows-API) programmiere ich selten, deshalb war deine Lösung für mich sehr interessant, aber scheinbar mache ich noch etwas verkehrt oder ich habe deinen Ansatz nicht richtig verstanden.
Mit deiner Methode: GetPopupWindow erhalte ich das Handle eines PopUp-Fenster eines (Parent-) Fenster's. Richtig?
Ich habe mal eine kleines Demo erstellt (das ich mehrfach aufrufe). In diesem hole ich mir über die GetProcessesByName-Methode das Handle eines Fensters (= Parent-hWnd) und versuche über deine Methode das Handle eines PopUp-Fenster zu holen, was ich natürlich vorher aufgerufen habe:
Process[] prozesse = Process.GetProcessesByName("VorderstesFenster");
...
Info = prozesse[0].MainWindowTitle + " -> PID: " + prozesse[0].Id + " | Handle: 0x" + prozesse[0].Handle.ToString("X4") + " | Popup-Handle: " + GetPopupWindow(prozesse[0].Handle).ToString();
Leider erhalte ich als Handle immer 0, obwohl ich im 2. Fenster ein PopUp-Fenster aufgerufen habe.
Hier das Demo:
View:
<Window x:Class="VorderstesFenster.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VorderstesFenster"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
Title="{Binding FensterNr}" Height="350" Width="1200">
<Window.DataContext>
<local:VMVorderstesFenster/>
</Window.DataContext>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Command="{Binding FindVorderstesFensterCommand }" ToolTip="Vorderstes Fenster ermitteln."
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}">
<Path Data="M29.332 10.667H2.666V28c0 0.736 0.598 1.333 1.332 1.333c0.736 0 1.334 0.599 1.334 1.334S4.736 32 4 32
c-2.209 0-4-1.791-4-4V4c0-2.209 1.791-4 4-4h24c2.209 0 4 1.791 4 4v10.667C32 15.404 31.402 16 30.666 16
c-0.734 0-1.334-0.598-1.334-1.333V10.667L29.332 10.667z M29.332 8V4c0-0.736-0.596-1.333-1.332-1.333H4
C3.264 2.667 2.666 3.264 2.666 4v4H29.332z M22.666 4C23.402 4 24 4.598 24 5.333s-0.598 1.333-1.334 1.333
c-0.734 0-1.334-0.598-1.334-1.333S21.932 4 22.666 4z M26.666 4C27.402 4 28 4.598 28 5.333s-0.598 1.333-1.334 1.333
c-0.734 0-1.334-0.598-1.334-1.333S25.932 4 26.666 4z M18.666 32c-4.125 0-7.904-1.754-11.291-5.193
c-1.529-1.559-1.529-4.055 0-5.611c3.387-3.44 7.166-5.194 11.291-5.194s7.906 1.754 11.291 5.194c1.531 1.558 1.531 4.054 0 5.611
C26.572 30.246 22.791 32 18.666 32z M18.666 29.333c3.371 0 6.482-1.442 9.391-4.397c0.51-0.52 0.51-1.352 0-1.871
c-2.906-2.953-6.02-4.396-9.391-4.396c-3.369 0-6.482 1.443-9.389 4.396c-0.51 0.521-0.51 1.353 0 1.871
C12.184 27.891 15.297 29.333 18.666 29.333z M18.666 26.667C17.193 26.667 16 25.473 16 24s1.193-2.667 2.666-2.667
c1.475 0 2.666 1.194 2.666 2.667S20.141 26.667 18.666 26.667z" Fill="Black"/>
</Button>
<Button Command="{Binding DialogCommand }" ToolTip="Dateidialog öffnen." Margin="20,0,0,0"
Visibility="{Binding IsErstesFenster}">
<Path Data="M1.6 0h11.201v1.6h1.6v1.6h16V4.8H32V24h-1.6v1.6H1.6V24H0V1.6h1.6V0 M3.199 6.4v16h25.602v-16H3.199z" Fill="Black"/>
</Button>
</StackPanel>
<TextBlock Text="{Binding Info}" FontWeight="Bold" FontSize="36" Margin="0,20,0,0" />
</StackPanel>
</Window>
8000 Zeichen sind eindeutig zu wenig ...
Und hier das ViewModel
public class VMVorderstesFenster : MVVM_Base
{
#region Zentrale Eigenschaften
public const uint GWENABLEDPOPUP = 6;
[DllImport("user32.dll")] // User32 einbinden
private static extern IntPtr GetWindow(IntPtr hWnd, uint command); // Methode zur Ermittlung des obersten Fenster's
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string strclassName, string strWindowName = ""); // Methode zur Ermittlung des Fensters einer (definierten) Klasse
#endregion
#region View Eigenschaften
private string _Info;
public string Info { get => _Info; set { _Info = value; OnChanged(nameof(Info)); } }
private string _FensterNr;
public string FensterNr { get => _FensterNr; set { _FensterNr = value; OnChanged(nameof(FensterNr)); } }
private Visibility _IsErstesFenster;
public Visibility IsErstesFenster { get => _IsErstesFenster; set { _IsErstesFenster = value; OnChanged(nameof(IsErstesFenster)); } }
#endregion
#region Commands
public ICommand FindVorderstesFensterCommand { get; private set; } // Vorderstes Fenster bestimmen Command deklarieren
public ICommand DialogCommand { get; private set; } // File-Dialog aufrufen Command deklarieren
#endregion
#region Konstruktor
public VMVorderstesFenster()
{
FindVorderstesFensterCommand = new ActionCommand(FindVorderstesFensterExecuted, FindVorderstesFensterCanExecute); // Vorderstes Fenster bestimmen Command initalisieren
DialogCommand = new ActionCommand(DialogExecuted, DialogCanExecute); // File-Dialog aufrufen Command initalisieren
Process[] AplikationsProzesse = Process.GetProcessesByName("VorderstesFenster"); // Prozesse der untersuchten Applikation
FensterNr = "Fenster " + AplikationsProzesse.Length.ToString(); // Fensternummer abhängig von der Anzahl der Instanzen setzen
IsErstesFenster = AplikationsProzesse.Length == 1 ? Visibility.Collapsed : Visibility.Visible; // Sichtbarkeit abhängig von der Anzahl der Instanzen setzen
}
#endregion
#region Command-Routinen
private void DialogExecuted(object obj)
{
Microsoft.Win32.OpenFileDialog dlg = new(); // Datei-Dialog initalisieren
dlg.DefaultExt = ".txt"; // Standard Datei-Erweiterung
dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
dlg.ShowDialog();
}
private bool DialogCanExecute(object arg) => true;
private void FindVorderstesFensterExecuted(object obj)
{
// IntPtr windowHandle = GetPopupWindow(new System.Windows.Interop.WindowInteropHelper((MainWindow)obj).Handle);
Process[] prozesse = Process.GetProcessesByName("VorderstesFenster");
if (prozesse.Length > 0) Info = prozesse[0].MainWindowTitle + " -> PID: " + prozesse[0].Id +
" | Handle: 0x" + prozesse[0].Handle.ToString("X4") + " | Popup-Handle: " + GetPopupWindow(prozesse[0].Handle).ToString();
if (prozesse.Length > 1) Info += Environment.NewLine + prozesse[1].MainWindowTitle + " -> PID: " + prozesse[1].Id +
" | Handle: 0x" + prozesse[1].Handle.ToString("X4") + " | Popup-Handle: " + GetPopupWindow(prozesse[1].Handle).ToString();
if (prozesse.Length > 2) Info += Environment.NewLine + prozesse[2].MainWindowTitle + " -> PID: " + prozesse[2].Id +
" | Handle: 0x" + prozesse[2].Handle.ToString("X4") + " | Popup-Handle: " + GetPopupWindow(prozesse[2].Handle).ToString();
}
private bool FindVorderstesFensterCanExecute(object arg) => true;
#endregion
/// <summary>
/// Methode zum Ermitteln des obersten Fenster's
/// </summary>
/// <param name="hWndParent">hWnd des übergeordneten Fenster's</param>
/// <returns>hWnd des obersten Fenster's</returns>
private static IntPtr GetPopupWindow(IntPtr hWndParent)
{
if (hWndParent != IntPtr.Zero)
{
IntPtr hWndPopup = GetWindow(hWndParent, GWENABLEDPOPUP);
return (hWndPopup != hWndParent) ? hWndPopup : IntPtr.Zero;
}
return IntPtr.Zero;
}
}
Mit deiner Methode: GetPopupWindow erhalte ich das Handle eines PopUp-Fenster eines (Parent-) Fenster's. Richtig?
Ja, genau. Als hWndParent
übergebe ich den HWND meines Hauptfensters. Es funktioniert bei meinem Test wie folgt:
namespace WpfApp1
{
public partial class MainWindow : Window
{
private IntPtr m_hwnd = IntPtr.Zero;
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
if (source != null)
{
m_hwnd = source.Handle;
DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Background);
timer.Tick += OnTimerTick;
timer.Interval = TimeSpan.FromMilliseconds(250);
timer.Start();
}
}
private void OnTimerTick(object sender, EventArgs e)
{
try
{
Title = $"hWndPopup=0x{GetPopupWindow(m_hwnd).ToString("X")}";
}
catch { }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.ShowDialog(this);
}
private static IntPtr GetPopupWindow(IntPtr hWndParent)
{
if (hWndParent != IntPtr.Zero)
{
IntPtr hWndPopup = GetWindow(hWndParent, GW_ENABLEDPOPUP);
return (hWndPopup != hWndParent) ? hWndPopup : IntPtr.Zero;
}
return IntPtr.Zero;
}
public const uint GW_ENABLEDPOPUP = 6;
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, uint command);
}
}
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Margin="25">
<Button Content="Click!" Click="Button_Click"></Button>
</Grid>
</Window>
Achtung: Wenn man das Programm im Visual Studio-Debugger laufen lässt, dann hängt Visual Studio automatisch eine zusätzliche Symbolleiste an der Titlebar des Hauptfensters an. Und diese wird ebenfalls als Popup-Fenster erkannt. Ich vermute es ist so, weil diese Symbolleiste technisch gesehen ein eigenes Fenster ist. Wenn man das Programm ohne Debugger laufen lässt, dann funktioniert aber alles wie erwartet, d.h hWndPopup
ist 0
, solange kein Popup-Fenster offen ist.
Hallo Weressated!
Vielen Dank für dein Beispiel.
Die Ursache, warum deine Methode bei mir nicht funktionierte lag daran, dass das Windows-Handle was durch die GetProcessesByName-Methode zurückgegeben wird, nicht das Windows-Handle des Fensters dieses Processes ist.
Process[] prozesse = Process.GetProcessesByName("VorderstesFenster");
...
prozesse[1].Handle.ToString("X4") ... GetPopupWindow(prozesse[1].Handle) ...
Wenn ich das Windows-Handle, wie in deinem Beispiel demonstriert, von der PresentationSource ableite, wird mir auch das Fenster-Handle des PopUp-Fensters zurückgegeben!!!
#region Behavior's
public class WindowLoadedBehavior : Behavior<MainWindow>
{
protected override void OnAttached() => AssociatedObject.Loaded += AssociatedObject_Loaded;
protected override void OnDetaching() => AssociatedObject.Loaded -= AssociatedObject_Loaded;
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
VMVorderstesFenster myVM = ((MainWindow)sender).DataContext as VMVorderstesFenster; // ViewModel "holen"
if (PresentationSource.FromVisual((MainWindow)sender) is HwndSource source) myVM.FensterHandle = source.Handle; // Fenster-Handle "holen"
}
}
#endregion
(Behavior wegen MVVM)
In meinem Beispiel-Projekt kann ich nun das Fensterhandle (aus der Anzeige des jeweiligen Fenster's) eingeben und erhalte adäquat zum Zustand, PopUp-Fenster im Main-Fenster geöffnet oder nicht, das Fenster-Handle oder 0.
Vielen Dank für deine "Ermittlungen" nochmals!
Die Ursache, warum deine Methode bei mir nicht funktionierte lag daran, dass das Windows-Handle was durch die GetProcessesByName-Methode zurückgegeben wird, nicht das Windows-Handle des Fensters dieses Processes ist.
Process.GetProcessByName()
gibt ja ein Array vonProcess
Objekten.
Ich denke process.Handle
ist das Handle für den Prozess selbst, kein Fenster-Handle. Wenn Du das Handle für das Hauptfenster eines Prozesses haben willst, müsste process.MainWindowHandle
funktionieren.
Hallo Weressated!
Mit process.MainWindowHandle funktioniert es perfekt!
private void FindVorderstesFensterExecuted(object obj)
{
Process[] prozesse = Process.GetProcessesByName("VorderstesFenster");
Info = string.Empty;
for (int i = 0; i < prozesse.Length; i++)
{
Info += (i > 0 ? Environment.NewLine : "" ) + prozesse[i].MainWindowTitle + " -> PID: " + prozesse[i].Id +
" | Handle: [Process] 0x" + prozesse[i].Handle.ToString("X4") +
" | Handle: [View] 0x" + prozesse[i].MainWindowHandle.ToString("X4") +
" | Popup-Handle: " + GetPopupWindow(prozesse[i].MainWindowHandle).ToString();
}
}