Mit Visual-Basic-Funktionen kaum zu lösen: die Auswahl eines Ordners mit dem von Windows dafür vorgesehenen Stadard-Dialog. Eine Win-API-Funktion löst das Problem. Ordner wir die Profis Mit dem Ordnerauswahldialog der Windows-Oberfläche (siehe Bild) haben Sie allen nur denkbaren Komfort: Sie können sowohl auf lokale Laufwerke als auch auf freigegebene Netzwerk-Ordner zugreifen. Leider gibt es in Visual Basic (VB) und dem in Programmen wie Microsoft Office eingebauten Visual Basic für Applikationen (VBA) leider immer noch keinen Befehl, um diesen eleganten Dialog aufzurufen.
Sie können aber trotzdem diese Ordnerauswahl auf den Bildschirm zaubern. Nötig dafür ist lediglich eine einfache API-Funktion. Wie Sie API-Funktionen in eigene VB-Projekte einbauen, zeigt Ihnen der Workshop WinAPI-Funktionen in VB nutzen. Das nötige Listing wird auf den nächsten Seiten Schritt für Schritt aufgebaut und erklärt. Den vollständigen Quellcode finden Sie auf der letzten Seite diese Beitrags. Dort können Sie ihn auch als Textdatei auf Ihren lokalen PC herunterladen. Den benötigten Datentyp definieren Um den abgebildeten Standarddialog zur Auswahl eines Verzeichnisses aufzurufen, müssen Sie zuerst einen Typ, Konstanten und API-Funktionen in Ihrem VB-Projekt deklarieren. Die zentrale API-Funktion ist "SHBrowseForFolder". Sie ruft die Dialogbox auf, die Sie auf der ersten Seite dieses Beitrags sehen. Ihr muss ein vom Anwender definierter Datentyp übergeben werden. Deklarieren Sie diesen Datentyp in einem Modul wie folgt: Type BrowseInfo hWndOwner As Long pIDLRoot As Long pszDisplayName As Long lpszTitle As Long ulFlags As Long lpfnCallback As Long lParam As Long iImage As Long End Type Mit diesem Datentyp können Sie die API-Funktion konfigurieren. Für die korrekte Arbeit der Funktion sind lediglich die drei Variablen hWndOwner, lpszTitle und ulFlags notwendig. Trotzdem müssen Sie den vollständigen Datentyp definieren, da die API-Funktion sonst nicht arbeiten kann. Die Bedeutungen der drei Variablen sind: Das Fenster-Handle hWndOwner wird mit einer weiteren API-Funktion ermittelt, die Sie ebenfalls im entsrechenden Modul deklarieren müssen: GetActiveWindow. Die Deklaration heißt: Private Declare Function GetActiveWindow Lib "user32" () As Long Dann deklarieren Sie noch die API-Funktion SHBrowseForFolder: Declare Function SHBrowseForFolder Lib "shell32" ( _ lpbi As BrowseInfo) As Long Diese API-Funktion erzeugt einen Zeiger auf eine Datenstruktur mit dem ausgewählten Pfad. Details hierzu folgen später. Die Variable "ulFlags" Zum Datentyp BrowseInfo gehört die Variable ulFlags. Ihr Wert beeinflusst das Verhalten des Verzeichnisdialogs. Je nach Wert zeigt der Dialog bestimmte objekte an und erlaubt nur die Auswahl bestimmter Objekte. Folgende Werte sind möglich:
Am besten deklarieren Sie diese Werte ebenfalls als Konstanten im entsprechenden Modul: Private Const BIF_BROWSEFORCOMPUTER = &H1000 Private Const BIF_BROWSEFORPRINTER = &H2000 Private Const BIF_BROWSEINCLUDEFILES = &H4000 Private Const BIF_RETURNONLYFSDIRS = &H1 Private Const BIF_DONTGOBELOWDOMAIN = &H2 Private Const BIF_STATUSTEXT = &H4 Private Const BIF_RETURNFSANCESTORS = &H8 Die "Item Identifier List" Die Ordnerstruktur der Windows-Oberfläche umfasst nicht nur Laufwerke und Verzeichnisse, sondern auch sogenannte Systemordner wie zum Beispiel die Systemsteuerung oder den Druckerordner. Außerdem gehören auch Netzwerk-Ressourcen wie Netzdrucker oder freigegebene Verzeichnisse auf anderen Rechnern dazu. Diese vielen Ordnertypen zeigt der Ordnerdialog als Baumansicht mit dem Desktop als Wurzel an. Die gesamte Struktur aus Systemordnern, Datenträgerordnern und Netzwerk-Ressourcen wird als Namensraum bezeichnet. Ähnlich wie bei einer Ordnerstruktur in einem Dateisystem gibt es auch für den gesamten Namensraum von Windows einen Namensstandard, der Systemordner und Dateisysteme umfasst. Er ähnelt der Pfadangaben einer Datei auf der lokalen Festplatte, Diskette oder einem sonstigen Datenträger. Der Namensraum enthält zu einem bestimmten Element – meist ein beliebiger Ordner – alle übergeordneten Elemente bis zurück zur Wurzel: dem Desktop: Dieser Darstellungsstandard heißt "Item Identifier List" ("Elementidentifikationsliste") oder kurz IID-Liste. Das Beispiel des folgenden Pfads soll das verdeutlichen: C:\Eigene Dateien\Konzepte\Buch.doc
Die dazugehörige IID-Liste besitzt eine andere Wurzel als den Laufwerksbuchstaben C, da auch alle weiteren Laufwerke von einer gemeinsamen Wurzel abzeigen – nämlich vom Arbeitsplatzsymbol. Die IID-Liste zu diesem Beispiel würde folgende Elemente enthalten: [Arbeitsplatz][C:][Eigene Dateien][Konzepte][Buch.doc] Diese Darstellung soll lediglich die Abfolge von Elementen dieser Datenstruktur verdeutlichen. Tatsächlich ist eine IID-Liste eine binäre Datenstruktur, die intern von Windows benutzt wird. Die Funktion SHBrowserForFolder gibt einen Zeiger auf eine solche IID-Liste zurück. Sie können mit Hilfe der API-Funktion SHGetPathFromIDList zu jeder IID-Liste die Pfadangabe des Dateisystems ermitteln. Setzen Sie also auch folgende Deklaration in das Modul ein: Declare Function SHGetPathFromIDList Lib "shell32" ( _ ByVal pidList As Long, _ ByVal lpBuffer As String) As Long Gehört die IID-Liste nicht zu einem Dateisystem, erzeugt diese Funktion eine leere Zeichenkette. Das heißt: Sie können damit nur lokale und Netzwerkpfade behandeln. Auf Systemordner können Sie nicht zugreifen, da der Darstellungsstandard für Pfadangaben keine Elemente außerhalb eines Dateisystem kennt. Mit der Funktion SHBrowseForFolder können Sie auch die Pfade zu Dateien und Ordnern im Netzwerk ermitteln. In diesem Fall erhalten Sie nach Umwandlung der IID-Liste mit SHGetPathFromIDList einen vollständigen Pfad nach der "Universal Naming Convention" (UNC). Auch dazu ein Beispiel: Sie haben im Dialog in der Netzwerkumgebung von dem Rechner "Computer5" das Verzeichnis "C:Eigene Dateien" markiert. Der entsprechende UNC-Pfad lautet dann: \\Computer5\C\Eigene Dateien Den Aufruf des Auswahldialogs in eine Funktion packen Damit Sie den Aufruf des Ordnerdialogs in Ihrem gesamten VB-Projekt nutzen können und nicht jedes Mal neu schreiben müssen, verpacken Sie in am besten in eine eigene Funktion. Im vorliegenden Beispiel heißt sie "BrowseForFolders". Diese Mantelfunktion benötigt lediglich ein Argument: Die Beschriftung des Dialogfeldes, die Variable Prompt: Function BrowseForFolder(Prompt As String) As String … End Function Der Aufruf des Ordnerdialogs geschieht in drei Schritten:
Dim n As Integer Dim IDList As Long Dim Result As Long Dim ThePath As String Dim BI As BrowseInfo Die Datenstruktur BrowseInfo wird als Variable BI deklariert. Sie wird dann sogleich mit den benötigten Werten gefüllt. Auf die einzelnen Bestandteile der Datenstruktur greifen Sie mit dem Punkt-Operator zu. Der Variablen hWndOwner weisen Sie beispielsweise den Wert des aktiven Fensters zu: BI.hWndOwner = GetActiveWindow() Entsprechend werden auch die anderen BI-Variablen mit Werten belegt. Wenn Sie nicht jedes Mal BI vor die Variable setzen wollen, nutzen Sie einfach die With-Konstruktion. Belegen Sie nun noch die Beschriftung des Dialogs und seine Flags. Im Beispiel wird als ulFlags der Wert BIF_RETURNONLYFSDIRS genutzt, so dass der Ordnerdialog nur die Auswahl von Dateisystemobjekten erlaubt: ' Erzeugen der Datenstruktur With BI ' Handle des aktiven Fensters ermitteln .hWndOwner = GetActiveWindow() ' Titel des Dialoges als nullterminierter String .lpszTitle = lstrcat(Prompt, "") ' Nur Dateisystemordner erlaubt .ulFlags = BIF_RETURNONLYFSDIRS End With Sie bemerken sicher die Funktion lstrcat. Sie konvertiert einen Visual-Basic-String in einen sogenannten nullterminierten String – denn Windows selbst versteht nur Strings, deren Ende mit einem Null-Zeichen beendet werden. lstrcat erledigt das für Sie. Andernfalls gäbe es einen Laufzeitfehler im Programm. Auch diese Funktion ist eine API-Funktion, die Sie zuvor im Modul deklarieren müssen: Private Declare Function lstrcat Lib "kernel32" _ Alias "lstrcatA" ( _ ByVal lpString1 As String, _ ByVal lpString2 As String) As Long Nachdem Sie BI mit Werten initialisiert haben, wird der Ordnerdialog mit SHBrowseForFolder aufgerufen: 'Anzeigen des Dialogs und Übergabe an eine IID-Liste IDList = SHBrowseForFolder(BI) Den Rückgabewert von SHBrowseForFolder auswerten Der Rückgabewert der API-Funktion SHBrwoserForFolder ist vom Typ Long. Er enthält einen Zeiger auf eine IID-Liste. Dafür ist am Beginn Ihrer BrowseForFolder-Funktion die Variable IDList entsprechend deklariert. Tritt beim Aufruf von SHBrowseForFolder(BI) ein Fehler auf oder klickt der Anwender im Ordnerdialog auf "Abbrechen", so hat IDList den Wert 0. Diesen können Sie in einer einfachen If-Abfrage auswerten. Der Rückgabewert wird nur bearbeitet, wenn IDList nicht 0 ist: ' Wenn IDList > 0, dann Auswahl bearbeiten If IDList Then Um die IID-Liste in eine Pfadangabe zu konvertieren, benötigen Sie als erstes eine Zeichenfolge, die Sie mit der VB-Funktion String$() Speicher zuweisen: ThePath. Anschließend genügt ein Aufruf der Funktion SHGetPathFromIDList, um den Pfad zu ermitteln: ' Speicher anfordern ThePath = String$(MAX_PATH, 0) ' IID-Liste in Pfadangabe konvertieren Result = SHGetPathFromIDList(IDList, ThePath) Der Wert MAX_PATH ist wiederum eine zuvor im Modul definierte Konstante. Sie enthält die maximale Länge der Zeichenfolge, nämlich 260 Zeichen: Private Const MAX_PATH = 260 Der nächste Schritt ist sehr wichtig. Windows hat für die IID-Liste Speicher reserviert, den Sie mit einem Aufruf von CoTaskMemFree wieder freigeben müssen. Wenn Sie dies nicht tun, kann Windows den angeforderten Speicher nicht wieder nutzen. Deshalb nun folgende Programmzeile: ' Speicher für IID-Liste verwerfen Call CoTaskMemFree(IDList) Zum Schluss müssen Sie die Zeichenfolge noch nachbearbeiten. Windows behandelt sie als Puffer. Das heißt: Die Pfadangabe wird beginnend mit dem ersten Byte in den String kopiert. Der "Rest" bleibt erhalten und besteht aus mehr oder weniger vielen Null-Zeichen. Diese müssen von dem String entfernt werden, damit er innerhalb von Visual Basic korrekt weiterverwendet werden kann: ' Alle Bytes hinter Nullbyte verwerfen n = InStr(ThePath, vbNullChar) If n Then ThePath = Left$(ThePath, n - 1) End If Der Wert vbNullChar ist dabei eine in VB eingebaute Konstante. Sie enthält einfach ein Zeichen mit dem Wert 0. Zum Schluss gibt die Funktion den ermittelten Pfad als Ergebnis zurück: ' Rückgabewert der Funktion definieren BrowseForFolder = ThePath End Function Die BrowseForFolder-Funktion in eigene Projekte einbauen Sie sollten den Quelltext des Listings in einem eigenen Modul in Ihr VB- oder VBA-Projekt einfügen. Er ist so geschrieben, dass alle internen Konstanten und Deklarationen als "Private" definiert sind. Dadurch werden Konflikte mit anderen Modulen vermieden. Die Funktion selbst ist als "Public" gekennzeichnet und wird beispielsweise wie folgt aufgerufen: TheFolder$ = BrowseForFolder("Wählen Sie einen Ordner aus.") Das vollständige Listing finden Sie im folgenden auf dieser Seite. ' ########################################### ' ' MODUL "FolderBrowse" ' ' (c) Ingo Steinhaus 2000 ' ingo.steinhaus@gmx.de ' ' Funktionen zur Anzeige des Windows-Standardialogs zur Auswahl ' eines Ordners auf dem aktiven Rechner oder im Netzwerk. ' ' Dieses Modul ist urheberrechtlich geschützte Freeware. ' Die originale Copyright-Meldung darf nicht entfernt oder ver- ' ändert werden. Der Quelltext darf nicht verändert werden. ' '########################################### Private Const MAX_PATH = 260 ' ********************************************************* ' Die Datenstruktur "BrowseInfo" dient der Konfiguration ' des Folder-Browse-Dialogs. Private Type BrowseInfo hWndOwner As Long ' Handle des Besitzers (mit GetActiveWindow() abfragen) pIDLRoot As Long ' Adresse der IID-Liste. 'Sie gibt die Position des Wurzelordners an, der als 'Baumwurzel im Browse-Dialog erscheint. Nur dieser 'Ordner und die davon abzweigenden Ordner erscheinen 'im Browse-Dialog. 'Sie können hier NULL eintragen; in diesem Fall wird 'der Desktop als Baumwurzel benutzt. Dadurch haben Sie 'Zugriff auf alle Laufwerke sowie die Netzwerkumgebung. pszDisplayName As Long ' Adresse eines Puffers, der den Namen des vom Anwender 'ausgewählten Ordners (ohne Pfad) enthält. Der Puffer 'kann maximal 260 Zeichen enthalten (MAX_PATH Konstante) lpszTitle As Long ' Adresse eines nullterminierten Strings, der über der 'Baumansicht gezeigt werden. Sie können diesen String 'für Informationen oder Anweisungen benutzen. ulFlags As Long ' Flags, die die Anzeigeoptionen des Dialogfeldes bestimmen lpfnCallback As Long ' Adresse einer Rückruffunktion, die in der Anwendung 'definiert wird. 'Sie können hier NULL eintragen. lParam As Long ' Ein anwendungsdefinierter Wert, den das Dialogfeld an 'eine Rückruffunktion übergibt. iImage As Long ' Eine Variable für das Bild, mit dem der ausgewählte Ordner 'in der Baumansicht gekennzeichnet ist. Die Variable enthält 'einen Index auf die Systembilderliste von Windows 95/98. End Type ' ********************************************************* ' Die folgenden Konstanten sind die erlaubten Werte für ' BrowseInfo->ulFlags. Private Const BIF_BROWSEFORCOMPUTER = &H1000 ' Nur Computer als Auswahl erlaubt. Wenn der Anwender andere 'Ordner markiert, kann der OK-Schalter nicht ausgewählt 'werden. Private Const BIF_BROWSEFORPRINTER = &H2000 ' Nur Drucker als Auswahl erlaubt. Wenn der Anwender andere 'Ordner markiert, kann der OK-Schalter nicht ausgewählt 'werden. Private Const BIF_BROWSEINCLUDEFILES = &H4000 ' Der Dialog zeigt neben den Ordnern auch Dateien. Private Const BIF_DONTGOBELOWDOMAIN = &H2 ' Der Dialog zeigt keine Netzwerkordner unterhalb der 'aktuellen Domain. Private Const BIF_RETURNFSANCESTORS = &H8 ' Nur Dateisystemobjekte als Auswahl erlaubt. Wenn der 'Anwender andere Ordner markiert, kann der OK-Schalter 'nicht ausgewählt werden. Private Const BIF_RETURNONLYFSDIRS = &H1 ' Nur Dateisystemordner als Auswahl erlaubt. Wenn der 'Anwender andere Ordner markiert, kann der OK-Schalter 'nicht ausgewählt werden. Private Const BIF_STATUSTEXT = &H4 ' Der Dialog enthält eine Statuszeile. Die Rückruffunktion 'kann die Statuszeile ausfüllen. ' ********************************************************* '*** CoTaskMemFree ' Eine Funktion zum Verwerfen von angefordertem globalen ' Speicher. Private Declare Sub CoTaskMemFree Lib "ole32.dll" ( _ ByVal hMem As Long) ' ********************************************************* '*** lstrcat ' Eine Funktion zum Verknüpfen von nullterminierten Strings. Private Declare Function lstrcat Lib "kernel32" _ Alias "lstrcatA" ( _ ByVal lpString1 As String, _ ByVal lpString2 As String) As Long ' ********************************************************* ' *** GetActiveWindow ' Eine Funktion zum Ermitteln des Fenster-Handles. Private Declare Function GetActiveWindow Lib "user32" () As Long ' ********************************************************* ' *** SHGetPathFromIDList ' Diese Funktion konvertiert eine IID-Liste in einen Pfad des ' Dateisystems. Private Declare Function SHGetPathFromIDList Lib "shell32" ( _ ByVal pidList As Long, _ ByVal lpBuffer As String) As Long ' ******************************************************** Rem *** SHBrowseForFolder Rem Diese Funktion ruft den Folder-Browse-Dialog auf. Rem Der Aufrufer muß den Speicher der IID-Liste verwerfen. Private Declare Function SHBrowseForFolder Lib "shell32" ( _ lpbi As BrowseInfo) As Long ' ********************************************************* ' *** BrowseForFolder ' Eine VB/VBA-Funktion als einfach zu nutzender Mantel für den ' Aufruf des Folder-Browse-Dialogs. Public Function BrowseForFolder(Prompt As String) As String Dim n As Integer Dim IDList As Long Dim Result As Long Dim ThePath As String Dim BI As BrowseInfo ' Erzeugen der Datenstruktur With BI ' Handle des aktiven Fensters ermitteln .hWndOwner = GetActiveWindow() ' Titel des Dialoges .lpszTitle = lstrcat(Prompt, "") ' Nur Dateisystemordner erlaubt .ulFlags = BIF_RETURNONLYFSDIRS End With ' Anzeigen des Dialogs und Übergabe an eine IID-Liste IDList = SHBrowseForFolder(BI) ' Wenn IDList > 0, dann Auswahl bearbeiten If IDList Then ' Speicher anfordern ThePath = String$(MAX_PATH, 0) ' IID-Liste in Pfadangabe konvertieren Result = SHGetPathFromIDList(IDList, ThePath) ' Speicher für IID-Liste verwerfen Call CoTaskMemFree(IDList) ' Alle Bytes hinter Nullbyte verwerfen n = InStr(ThePath, vbNullChar) If n Then ThePath = Left$(ThePath, n - 1) End If ' Rückgabewert der Funktion definieren BrowseForFolder = ThePath End Function Dieser Workshop wurde bereits 34.523 mal aufgerufen.
Anzeige
Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
Neu! sevCommand 4.0 Professionelle Schaltflächen im modernen Design! Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Tipp des Monats Dezemeber 2024 Roland Wutzke MultiSort im ListView-Control Dieses Beispiel zeigt, wie sich verschiedene Sortierfunktionen für ein ListView Control realisieren lassen. Access-Tools Vol.1 Über 400 MByte Inhalt Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB |
|||||||||||||||||||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |