Aushilfe gesucht
Aushilfe gesucht ExplorerDuo ist eine Konsolenanwendung, die sich mit der kostenlosen Express-Edition von Visual Basic .NET nachbauen und erweitern lässt. Obwohl sich die Programmbeschreibung simpel anhört, lässt es sich mit den Mitteln des .NET-Frameworks nicht realisieren. Der mächtigen a...
Aushilfe gesucht
ExplorerDuo ist eine Konsolenanwendung, die sich mit der kostenlosen Express-Edition von Visual Basic .NET nachbauen und erweitern lässt. Obwohl sich die Programmbeschreibung simpel anhört, lässt es sich mit den Mitteln des .NET-Frameworks nicht realisieren.
Der mächtigen aber keineswegs allmächtigen Klassenbibliothek von VB.NET fehlen Funktionen für den Umgang mit Fenstern. Die leiht sich ExplorerDuo daher direkt von Windows, das in Form seines Application Programming Interface - kurz: API - über eine alte, leistungsfähige Programmierschnittstelle verfügt.
Um API-Funktionen in einem VB.NET-Programm zu nutzen, melden Sie diese zunächst an. Dazu legen Sie wahlweise einen leeren Funktionsrumpf mit vorgestelltem DllImport-Attribut an oder nutzen die Declare-Anweisung wie in Visual-Basic-Programmen.
Aus technischer Sicht sind beide Methoden gleichwertig. VB-Umsteiger dürfen also beruhigt den Klassiker Declare verwenden, solange sie Funktionsparameter und Rückgabewerte, die in Visual Basic vom Datentyp Long waren, als Integer deklarieren. Während die Anmeldung für die API-Funktion GetWindow also in einem Visual-Basic-6-Programm noch so aussah
Declare Function GetWindow Lib "User32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
muss sie in einem VB.NET-Modul nun folgendermaßen lauten:
Declare Function GetWindow Lib "User32" (ByVal hWnd As Integer, ByVal wCmd As Integer) As Integer
Neben GetWindow greift ExplorerDuo auf sieben weitere API-Funktionen zurück, deren Deklarationen zusammen mit einigen zugehörigen Konstanten und einer Datenstruktur namens RECT in dem Projektmodul API.vb zu finden sind. Darüber hinaus enthält das Modul vier benutzerdefinierte VB.NET-Funktionen. Die kapseln eine Reihe von API-Funktionen, so dass sie sich aus dem Hauptprogramm von ExplorerDuo, der Prozedur Main im zweiten Projektmodul Main.vb, sehr komfortabel nutzen lassen.
Innenansichten

Nach dem Aufruf des Befehls In zweitem Explorer öffnen startet Windows den ExplorerDuo und übergibt dessen Main-Prozedur zwei Befehlszeilenargumente. Das erste enthält den Pfad des im Explorer gewählten Laufwerks oder Ordners, das zweite den Schalter /n, womit das Programm zwei Explorer-Fenster nebeneinander statt untereinander anzeigt.
Die Main-Prozedur wertet die im Args-Array übergebenen Argumente anfangs aus und speichert diese in internen Variablen. Da die parallele Anzeige von mehr als zwei Explorer-Fenstern wenig sinnvoll ist, muss die Prozedur sicherstellen, dass bislang nur ein Explorer-Fenster aktiv ist. Dazu ruft sie die Funktion HolFensterHandles im Modul API.vb auf und übergibt ihr den Klassennamen CabinetWClass, mit dem sich alle Fenster des Windows-Explorers identifizieren lassen.
Die Funktion arbeitet sich mit diversen API-Funktionen durch alle sichtbaren und unsichtbaren Fenster der aktuellen Windows-Sitzung und vergleicht deren Klassennamen mit dem übergebenen. Bei einer Übereinstimmung nimmt sie die eindeutige Zugriffsnummer des Fensters, das Handle, in eine ArrayList auf und gibt diese am Ende als Funktionswert an die Main-Prozedur zurück.
Die Main-Prozedur muss noch die Count-Eigenschaft der ArrayList abfragen, um die Anzahl der aktiven Explorer-Fenster zu kennen. Wenn diese 1 ist, speichert sie das von HolFensterHandles ermittelte Handle des ersten und einzigen Explorer-Fensters in der Variablen Explorer1Handle und sichert dessen aktuelle Größe und Position durch einen Aufruf der Funktion HolFensterRechteck.
Die ermittelt per API-Hilfe GetWindowRect die Abstände der vier Fensterseiten von den Rändern des Bildschirms und gibt diese in einer Struktur vom benutzerdefinierten Typ RECT zurück. Anschließend startet die Main-Prozedur eine zweite Instanz des Windows-Explorers als neuen Prozess. Dazu legt sie die StartInfo.FileName-Eigenschaft des Process-Objekts auf explorer.exe (die Angabe des Ordners ist hier verzichtbar) fest und die StartInfo.Arguments-Eigenschaft auf den Pfad des anzuzeigenden Ordners.
Die Do-Loop-Schleife ruft dann die bekannte Funktion HolFensterHandles auf, bis desie auf ein weiteres Handle stößt. Erst dann ist das Fenster des zweiten Explorer-Instanz sichtbar und der Startvorgang des Prozesses erfolgreich abgeschlossen.

Die For-Each-Next-Schleife durchläuft nun die von HolFensterHandles gelieferten Handles, isoliert daraus das Handle des zweiten Explorer-Fensters und speichert es in der Variablen Explorer2Handle. Dem Programm sind so beide Explorer-Handles bekannt, womit es in Folge auf beide Fenster des Dateimanagers zugreift.
Erfahrene VB.NET-Aktivisten fragen vielleicht, warum man das Handle des zweiten Explorer-Fensters umständlich über die HolFensterHandles-Routine und eine Schleife ermitteln muss, wo man es doch über die MainWindowHandle-Eigenschaft des neu gestarteten Explorer-Prozesses abfragen könnte. Das geht daher nicht, da besagte Eigenschaft beim Windows-Explorer (insbesondere, wenn mehrere Instanzen aktiv sind) kein korrektes Ergebnis liefert.
Warum das so ist, müsste man Microsoft fragen. Das Problem scheint grundlegend zu sein, da hier auch andere Tricks versagen. Es funktioniert auch nicht, einen zweiten Explorer per Shell zu starten und das Fenster-Handle über den von der Shell gegebenen Instanz-Handles zu ermitteln. Anregungen, wie sich das Problem eleganter lösen ließe, sind dem Autor jederzeit willkommen.