Verwenden von Dialogressourcen
Einleitung
In Visual Basic lassen sich mit geringem Aufwand Formulare, d. h., Fenster, die Steuerelemente enthalten, entwerfen. Dennoch sollte man wissen, daß unter Windows Formulare auch in Ressourcendateien abgelegt werden können. Das Windows-API stellt die Möglichkeit bereit, in Ressourcendateien definierte Formulare während der Laufzeit zu laden und in der Anwendung zu benutzen. Dieser Artikel zeigt, wie Formulare in Ressourcendateien definiert werden und sie in Visual-Basic-Anwendungen geladen, manipuliert und angezeigt werden können.
Grundlagen
Was sind Dialoge?
Unter einem Dialog versteht man im Allgemeinen ein Fenster, über das der Benutzer mit der Anwendung „kommuniziert“. Heutzutage enthält fast jede Anwendung mehrere Dialoge. Einfachstes Beispiel ist ein Anmeldungsdialog oder der legendäre Versionsinformationsdialog, der bei fast keiner Anwendung fehlt. Allerdings sind nicht alle Fenster unter Windows Dialoge im Sinne von Dialogressourcen. Ein Großteil der Anwendungen besteht aus einem Hauptfenster, bei dem es sich nicht um eine Dialogressource handelt. Dieses Hauptfenster enthält meist eine Werkzeugleiste, eine Menüleiste und eine Statusleiste. Dabei ist zu bemerken, daß auch Menüs und Werkzeugleisten aus Ressourcendateien geladen werden können.
Motivation für die Verwendung von Dialogressourcen
Wie bereits angesprochen, werden Hauptfenster nicht aus Ressourcendateien geladen. Natürlich kann man bei allen Dialogen einer Anwendung so verfahren, jedoch muß man dann dem Code die entsprechenden Anweisungen zum Erstellen des Fensters, der darauf enthaltenen Steuerelemente und der notwendigen Ereignisverarbeitungsroutinen hinzufügen, was den Codeumfang vergrößern würde. Dies war einer der Gründe, warum der Ressourcentyp DIALOG
eingeführt wurde; weitere Ursachen sind die Folgenden:
Vereinfachung der Programmierung von Anwendungen und Erleichterung der Wartung des Quellcodes.
Erleichtertes GUI-Design durch Drag-and-Drop-Editoren, die das Erstellen und Testen von Dialogen vereinfachen. Dies ist besonders wichtig, da das reine Erstellen durch Code mittels
RegisterClass
,CreateWindowEx
usw. viel zu umständlich ist. Man bedenke dabei nur, daß nach jeder Änderung des Codes das neuerliche Kompilieren der gesamten Anwendung notwendig ist, was besonders bei größeren Projekten ziemlich zeitaufwendig ist. Außerdem ist dadurch der Code schwer verständlich und erfordert eine sehr detaillierte Kommentierung. Denn wie soll man schnell erkennen, welcher Code dann exekutiert welches Fenster erstellt?Abstrahierung der Projektstruktur auf Seite der Entwicklung. Gliederung des Codes in Module, Klassen und Ressourcen.
Durch den vorigen Punkt implizierte Förderung der Programmierung durch Teams mit Aufgabentrennung. So kann beispielsweise ein eigener Bildschirmdesigner mit dem Erstellen der Dialoge beauftragt werden, ohne dabei den anderen Programmierern im Weg zu sein.
Leichter durchschaubare Speicherverwaltung. Es ist einfacher nachvollziehbar, wie lange welches Fenster geladen ist, da nicht mehr so viel Code zum Erstellen und Entladen von Fenstern und Steuerelementen notwendig ist.
Dialogressourcen versus Visual-Basic-Dialogfenster
Das Formularsystem von Visual Basic
Natürlich werden Sie sich die Frage stellen, warum man eigentlich Dialoge aus Ressourcen verwenden soll, bietet doch Visual Basic bereits eine so einfache Möglichkeit, Dialoge zu erstellen und zu verwalten. Sieht man sich aber Formulare und Steuerelemente unter Visual Basic genauer an, so erkennt man schnell die etwas starre Struktur und die mangelnde Flexibilität. Bestes Beispiel hierfür sind die schreibgeschützten und fehlenden Eigenschaften. Wer unter Visual Basic eine wirklich professionelle Anwendungsoberfläche erstellen will, findet sowieso keinen Umweg um die Verwendung von Plattformfunktionen; warum sollte man nicht gleich auch die Dialoge per API-Aufrufen erstellen und organisieren?
Bei näherer Betrachtung des Visual-Basic-eigenen Steuerelementsystems wird man feststellen, daß die Steuerelemente keine „echten“ Windows-Steuerelemente sind. Unter Windows gibt es mehrere Standardsteuerelemente, die jeweils Instanzen einer bestimmten Fensterklasse sind. Der Klassennname einer Schaltfläche beispielsweise ist BUTTON
, der eines TextBox-Steuerelements wäre EDIT
. Wenn man nun die Klassennamen der Steuerelemente in einer mit Visual Basic erstellten Anwendung ansieht (beispielsweise mit dem Werkzeug Spy++), wird man feststellen, daß es sich hier um andere Klassennamen handelt, die nur die Windows-Steuerelementtypen kapseln.
Probleme und Einschränkungen des Visual-Basic-Formularsystems
Normalerweise hat man damit auch kein Problem, spätestens seit Windows 2000 gibt einem diese Architektur aber zu denken: Windows 2000 bietet nämlich einen eigenen Darstellungsmodus an, in dem die Zugriffstasten nicht unterstrichen werden und auch keine Fokusrechtecke angezeigt werden. Dies verleiht Anwendungen ein moderneres und aufgelockerteres Design, wenngleich auch die Benutzerfreundlichkeit etwas darunter leidet. Während bei normalen Anwendungen Fenster in diesem Modus gestartet werden, werden bei Visual-Basic-Anwendungen immer die Zugriffstasten unterstrichen und Fokusrechtecke angezeigt; dies kann allerdings über Windows-API-Funktionen ausgeschaltet werden.
Ein weiterer Vorteil ist, daß Steuerelemente wie ListView oder StatusBar ohne Verwendung der Komponente Microsoft Windows Common Controls eingebunden werden können. Leider können diese Steuerelemente anschließend nur über Plattformfunktionen modifiziert werden, was aber auch als Vorteil betrachtet werden kann. Wenn man schon auf API-Funktionen zurückgreifen muß, um verschiedene Merkmale und Verhaltensweisen zu erzielen, dann kann man die Steuerelemente auch gleich per API-Aufrufen erstellen und in weiterer Folge auch verwalten. Das selbe gilt auch für Formulare.
Weiters sind Dialogressourcen vorteilhaft, da bestimmte Aussehenseigenschaften wie z. B. seitenverkehrte Fenster komfortabel eingestellt werden können. Das Formularsystem von Visual Basic stellt zwar die wichtigsten Eigenschaften bei der Formularklasse zur Verfügung, jedoch ist nur eine Teilmenge der Möglichkeiten direkt verfügbar.
Nachteil der Verwendung von Dialogressourcen unter Visual Basic ist, daß die Tabulatorreihenfolge der Steuerelemente in den daraus geladenen Dialogen nicht korrekt funktioniert. Außerdem ist zu beachten, daß die Verwendung von Dialogressourcen unter Visual Basic nicht vorgesehen ist und daher auch von der Entwicklungsumgebung nicht vollständig unterstützt wird. Damit eine Dialogressource geladen werden kann, muß die Anwendung als kompilierte Anwendung vorliegen, beim Ausführen aus der Entwicklungsumgebung heraus funktioniert das Laden der Ressourcen nicht, da App.hInstance
auf die Instanz der Entwicklungsumgebung, nicht aber auf die Anwendung selbst verweist.
Der Ressourcentyp DIALOG
Hier wird auf eine genauere Beschreibung des Aufbaus von DIALOG
-Ressourcen verzichtet, da diese nur selten als Code bearbeitet werden müssen. Für nähere Informationen sei auf die Dokumentation verweisen. Zum Erstellen von Ressourcendateien kann beispielsweise Microsoft Visual C++ verwendet werden. Diese Entwicklungsumgebung bietet die Möglichkeit, in einem WYSIWYG-Editor mittels Drag and Drop Dialogfelder zu erstellen. Dabei können Steuerelemente, wie dies aus Visual Basic bekannt ist, mit der Maus in einer grafischen Entwurfsansicht positioniert und formatiert werden. Anschließend wird das Ressourcenskript zu einer Ressourcendatei kompiliert. Die fertige Ressourcendatei kann dann dem Visual-Basic-Projekt hinzufügt werden.
Relevante Win32-API-Funktionen
Aus Gründen der leichteren Nachvollziehbarkeit wird hier ein einfach gehaltenes Beispiel zur Nutzung von Dialogressourcen vorgestellt, das nicht die gesamte Palette an Möglichkeiten, die Dialogressourcen bieten, darstellt.
Die Funktion CreateDialogParam
Die Funktion CreateDialogParam
wird benutzt, um einen Dialog zu erstellen. Sie wird wie folgt deklariert:
Im Parameter hInstace
wird die Zugriffsnummer der Instanz der Anwendung angegeben, also App.hInstance
, lpName
ist der Name der Dialogressource in der Ressourcendatei in Form einer Zeichenfolge, hWndParent
gibt das Fenster an, das als Elternfenster verwendet werden soll, lpDialogFunc
ist ein Zeiger auf die Rückrufprozedur für die Dialognachrichten und der Parameter lParamInit
ist nicht relevant, wir übergeben im Beispiel den Wert 0&
. Als Rückgabewert wird die Zugriffsnummer des Dialogs geliefert. Tritt ein Fehler auf, dann ist der Rückgabewert 0.
Die Funktion EndDialog
EndDialog
wird verwendet, um den Dialog wieder zu entladen. Die Deklaration sieht folgendermaßen aus:
Der Parameter nResult
ist hier nicht relevant, hDlg
ist die Zugriffsnummer des Dialogs (der Rückgabewert von CreateDialogParam
).
Die Rückrufprozedur DialogProc
Wie bereits in der Beschreibung zur Funktion CreateDialogParam
angeführt, muß im Parameter lpDialogFunc
ein Zeiger auf eine benutzerdefinierte Rückruffunktion übergeben werden. Dies ist seit Visual Basic 5.0 über den Operator AddressOf
möglich. Gemäß der Dokumentation hat diese Rückruffunktion folgendes Aussehen:
Übersetzt man dies in Visual-Basic-Syntax, sieht der Kopf der Funktion wie folgt aus:
Die Funktionsdeklaration gleicht jener von Fensterprozeduren.
Behandeln von Ereignissen
Folgendes Beispiel zeigt, wie im Programmcode auf Ereignisse der Steuerelemente des Dialogs reagiert werden kann. Im Beispiel wird beim Klick auf die Schaltfläche IDC_SHOWMSG
des Dialogs der Inhalt des ebenfalls am Fenster enthaltenen TextBox-Steuerelements IDC_MSGTEXT
in einem Meldungsfenster angezeigt. Die Ereignisbehandlung aller Steuerelemente im Fenster erfolgt in der Funktionsprozedur DialogProc
. Folgendes Listing zeigt eine stark vereinfachte Version des Codes aus dem Beispielprojekt:
Schlußwort
Auch wenn die vorgestellte Methode ihre Einschränkungen hat und in der Praxis wohl kaum einsetzbar ist, sollte man als Programmierer darüber bescheid wissen. Es ist nämlich auch möglich, Dialogressourcen aus anderen Anwendungsdateien und Bibliotheken zu laden und mit eigenen Ereignisbehandlungsroutinen auszustatten. Ein Beispiel dazu ist im nachfolgenden Abschnitt zu finden.
Downloads
- Beispielprojekt (
DialogResource.zip
) Projekt im Visual-Basic-6.0-Format.
- Beispielprojekt (
DialogExplorer.zip
) Visual-Basic-6.0-Code eines Werkzeugs zum Ansehen der Dialogressourcen anderer Anwendungen.