Visual BASIC

Inhaltsverzeichnis:

Einleitung
Windows ist das Zauberwort der neunziger Jahre. Visual Basic ist der Schlüssel zu Windows, denn Visual Basic ermöglicht das Erstellen von richtigen Programmen ohne spezielle Vorkenntnisse. Kann man Basic, so beherrscht man Windows. Auf diese Kurzformel lässt sich das Geheimnis von Visual Basic bringen. Visual Basic ist die erste speziell für die Windows - Programmierung konzipierte Programmier - bzw. Hochsprache. Visual Basic ist in mehreren Beziehungen revolutionär. Früher musste man nicht nur gute Kenntnisse in C und Windows selbst haben, reichen heute Grundkenntnisse in Basic, um in kürzester Zeit funktionsfähige Windows - Programme herzustellen. Visual Basic kombiniert die Einfachheit der Programmiersprache mit einem sehr leistungsfähigen und komfortablen Entwicklungssystem. Visual Basic ist sehr erweiterbar. Über den Aufruf von sogenannten Bibliotheksfunktionen (siehe Kapitel: API - Routinen) bzw. über Steuerelemente können die Möglichkeiten der Sprache sehr erweitert werden.

Visual Basic erlaubt das Erstellen von komplexen Benutzeroberflächen in kürzester Zeit. Visual Basic Programme unterscheiden sich äußerlich nicht von kommerziellen Programmen. Visual Basic ist allerdings nicht die universelle Programmiersprache für Windows. Es ist vielmehr eine Sprache, die viele Vorteile, aber auch einige Mängel aufweist. Der wohl wichtigste Vorteil von Visual Basic ist, dass grundlegende Basic - Kenntnisse ausreichen, um voll funktionsfähige Programme entwickeln zu können.

Auch das zur Zeit recht populäre Schlagwort "objektorientiert" wir des öfteren in Verbindung mit Visual Basic gebracht. Visual Basic behandelt jedes Kontrollelement in einem Applikationsfenster als ein Objekt, das eine bestimmte Anzahl von Eigenschaften besitzt. Dazu gehören die Eigenschaften, die das Aussehen bestimmten genauso wie die Möglichkeiten, auf verschiedene Situationen (Mausklick, Tastendruck, ...) reagieren zu können.

Manch einer kann dem Ganzen nicht so recht trauen. Die Einfachheit, die Effizienz usw. Allerdings legt Visual Basic dem Programmierer etliche Beschränkungen auf. Als Beispiel möchte ich hier große Datenmengen nehmen. Visual Basic richtet sich aber nicht nach der professionellen Programmierung (sie ist zwar mit etwas Beihilfe von C/C++ o.ä. möglich), sondern eher nach einfacheren Programmen, in denen weder sehr komplexe Datenstrukturen vorkommen, noch die Ausführungsgeschwindigkeit ein Problem darstellt).

Visual Basic kann durchaus mit "Hypercard" (Apple Macintosh) oder mit dem "Interface - Builder" (NeXT - Computer) verglichen werden. So wie diese Programme das Programmierkonzept von den genannten Rechnern verändert haben, wird auch Visual Basic die Programmierart verändern: Einfach und trotzdem leistungsfähig. Man wird nie C/C++ innerhalb von Visual Basic überbieten können, da dieses mehr auf Systemebene arbeitet. Trotzdem ist Visual Basic gerade für den Gelegenheits - Programmierer wie z.B.: mich ideal, da es doch viele Möglichkeiten besitzt und (im Verglich zu "stärkeren" Programmiersprachen wesentlich billiger ist. Dies sind wohl auch die Möglichkeiten, warum Visual Basic zum Thema meiner Fachbereichsarbeit geworden ist.

Unterteilung:
Im ersten Teil befindet sich der theoretische Teil, der die Voraussetzungen zur API Programmierung darstellt.
Der zweite Teil ist ein Programm zur API - Programmierung.
Im Anhang befindet sich ein Glossar

Auf der beiliegenden CD befindet sich sowohl das Programm als auch die gesamte Fachbereichsarbeit inkl. aller Bilder und Vorgaben

Bedanken möchte ich mich noch bei Herr Prof. Walter Rigger für die Betreuung meiner Fachbereichsarbeit.
Grundlegendes
Was heißt Programmieren:
Programmieren bedeutet, dem Computer Anweisungen zu geben, die dieser auszuführen hat. Da es sich bei einem Computer, genauer gesagt bei einem Prozessor, der die eigentliche Programmausführung übernimmt, um einen elektronischen Baustein handelt, gilt es ein grundsätzliches Kommunikationsproblem zu überwinden. Dieses Kommunikationsproblem besteht darin, dass der Prozessor nur Befehle und Daten in binärer Form, das heißt in Form von Dualzahlen versteht. Ein typische Befehl an den Prozessor könnte daher folgendes Aussehen haben:
1 0 1 1 0 1 0 1 1 1 0 0 1 0 1 0
Da dieser Befehl direkt vom Prozessor ausgeführt werden kann, wird er als Maschinenbefehl bezeichnet. Alle Maschinenbefehle eines Prozessors werden unter dem Begriff Befehlssatz zusammengefaßt. Die Gesamtheit aller Befehle heißt: Maschinensprache. Eine einzelne Ziffer einer Dualzahl wird übrigens als Bit bezeichnet. Ein Bit kann nur zwei Zustände annehmen (0 ↔ 1, falsch ↔ wahr, aus ↔ ein) und ist damit die denkbar kleinste Informationseinheit. Die Tatsache, dass jede der beiden abgebildeten Dualzahlen genau 8 Bits umfaßt, ist kein Zufall, denn in der Informationsverarbeitung werden 8 Bits aus praktischen Erwägungen zu einem Byte zusammengefaßt. Auch ein Byte ist eine sehr kleine Einheit, man findet daher in der Praxis die Einheiten Kbyte (1 Kbyte = 1024 Bytes), Mbyte (1Mbyte = 1024 * 1024 Byte = 1024 Kbyte) oder auch Gbyte (1 Gbyte = 1024 * 1024 * 1024 Byte = 1024 Mbyte).

Verständlicherweise ist die Eingabe von Befehlen und Daten in Form von Dualzahlen sehr umständlich. Schon sehr bald nach Einführung der ersten Rechenmaschine in den Vierziger Jahren, musste ein Kompromiß gefunden werden. Dieser Kompromiß heißt Programmiersprache. Obwohl die erste Programmiersprache, es war FORTRAN, bereits Anfang der Fünfziger Jahre entwickelt wurde, hat sich an diesem Prinzip grundsätzlich nichts geändert. Inzwischen gibt es für den PC mehrere Dutzend Programmiersprachen. Sie werden auch als Hochsprachen bezeichnet, um sie von der Maschinensprache abzugrenzen. Alle Hochsprachen haben eines gemeinsam: sie übersetzen die Befehle eines Programms in die "Muttersprache" des Prozessors, die Maschinensprache. Auch für die Windows - Programmierung hat dieser Ablauf Gültigkeit. Allerdings sind Windows - Programme teilweise so komplex, dass der Zusammenhang zwischen den Befehlen der Programmiersprache und den übersetzten Maschinenbefehlen in der Praxis keine Bedeutung hat. Die meisten Windows - Programme werden in der Sprache C erstellt. Doch auch in Visual Basic lassen sich sehr leistungsfähige Programme entwickeln.
Was ist Visual Basic:
Visual Basic ist eine einfach zu erlernende Programmiersprache, die es dem Anwender bzw. dem Programmierer ermöglicht, eigene Programme für Microsoft Windows™ zu erstellen. Visual Basic benutzt hierzu eine grafische Oberfläche, die aus verschiedenen Teilbereichen zusammengesetzt ist. Mehr dazu später. Sie wurde von Microsoft entwickelt und mittlerweile gibt es schon die Versionsnummer 5.0. In meinen Beispielen arbeite ich mit Version 4.0, da Version 5.0 noch sehr neu ist und noch ein paar Mängel aufweist. Außerdem ist es günstig, die Version 4.0 zu verwenden, da es von dieser Version sowohl eine 16bit (Windows 3.x) als auch eine 32bit (Windows ´95/NT) Version gibt. Da Visual Basic einfach zu erlernen ist, hat es auch seine Grenzen, die allerdings für den normalen Programmierer, wie zum Beispiel für mich in weiter Ferne liegen. Die Befehle von Visual Basic sind nicht Case - Sensitive, d.h. es ist egal, ob bestimmte Befehle groß oder klein geschrieben werden. Außerdem werden Befehle, die Visual Basic erkennt, immer mit blau geschrieben, um eine bessere Ãœbersicht zu gewinnen. Ein weiterer Vorteil von Visual Basic ist, dass es den Zugriff auf die API’s erlaubt. Diese werden weiter hinten noch erläutert. Ein weiterer Nachteil von Visual Basic ist, dass die kompilierte (fertige) Anwendung im Gegensatz zu komplexeren Programmiersprachen wie z.B.: C/C++ oder Delphi (siehe Vergleiche) relativ langsam ist. Da sich dies allerdings erst bei komplexeren Programmen bemerkbar macht und da bisher erst wenige meiner Programme über die Größe eines Megabytes gingen, ist dieser Aspekt für mich uninteressant.

Ein Grund dafür, warum Visual Basic so bekannt geworden ist, liegt sicher im Preis. Im Gegensatz zu Visual Basic kosten "richtige" Programmiersprache wie z.B.: C/C++ oder Java ein Vielfaches von Visual Basic. Vielleicht ist Visual Basic nicht gerade die komplexeste Programmiersprache, dafür ist sie aber ebenso einfach zu erlernen.

Diese FBA soll einen kleinen Überblick über die Möglichkeiten von Visual Basic geben und zeigen, was mit einfachsten Mitteln alles möglich ist.
Innerhalb von Fenstern[1]
Zu Beginn muss gesagt werden, dass sich Visual Basic und Windows sehr gleichen. Visual Basic bietet ein sehr einfach zu benutzendes Interface (eine einfach zu benutzende Oberfläche). Ein Fenster hat eine große Menge an Eigenschaften, die über das Eigenschaftsfenster einfach verändert werden können. Das API - Interface ist um einiges komplexer.
Was ist ein Fenster:
Fenster können sowohl Formen, einzelne graphische Teile der Windows - Oberfläche, Bildlaufleisten als auch Icons sein. Sogar der Windows - Hintergrund ist ein Fenster.
Wann ist ein Fenster kein Fenster
Mit der Version 2.0 von Visual Basic kamen neue Arten von Steuerelementen, die Graphische Steuerelemente genannt wurden. Diese haben etwas gemeinsam: Sie sind keine Fenster, obwohl sie vielleicht so aussehen oder sich so verhalten. Ein graphisches Steuerelement ist ein innerhalb von Visual Basic definiertes Element. Graphische Steuerelemente unterstützen nicht viele der Möglichkeiten eines Fensters. Als Beispiel möchte ich das Label - Steuerelement (ein einzelnes Feld, in dem Text angezeigt werden kann) aufführen. Es beschreibt nur einen einfachen Textblock und, wie viele andere dieser Steuerelemente auch, kann es zum Beispiel den Fokus nicht erhalten (d.h. es kann nicht aktiviert werden, es hat immer den gleichen Status; besitzt ein Textfeld den Fokus, so können in dieses Daten eingegeben werden) und somit auch keine Tastatureingabe erkennen und auswerten (im Gegensatz zum Text - Control). Der eigentliche Schwachpunkt aber ist, dass sie keinen Window - Handle (eine Zahl, die ein Fenster eindeutig identifiziert) besitzen. Sie können daher auch nicht von API - Funktionen angesprochen werden, die einen solchen Handle benötigen.
System - Objekte:
Die Systemobjekte in Visual Basic (Zwischenablage - , Screen - , und Drucker - Objekte) haben ebenfalls keine Ansprechmöglichkeit betrachtet man sie von der Fenster - Seite (sie sind ebenfalls keine Fenster). Diese Systemressourcen werden direkt von Windows - APIs angesprochen.



Programmerstellung mit Visual Basic
Interpreter und Compiler:
Jeder Computer bzw. Prozessor besitzt einen Sprach - bzw. Befehlsvorrat, der ihn befähigt bestimmte Aufgaben wie etwa die Addition zweier Zahlen auszuführen. Um die Befehle der Hochsprache (ab hier wird sie nur noch Programmiersprache) genannt in Befehle des Prozessors zu verwandeln, bedarf es eines Dolmetschers, der die Befehle "übersetzt". Der Übersetzungsvorgang kann vor der eigentlichen Programmausführung geschehen und wird in der Informatik als kompilieren (engl. To compile) bezeichnet. Das Programm, das diese Arbeit erledigt, heißt Compiler. Im Gegensatz dazu kann das Programm natürlich auch erst während der Programmlaufzeit in die dem Computer verständliche Sprache übersetzt werden. In diesem Fall spricht man von einem Interpreter. Während Sprachen wie PASCAL oder auch C reine Compiler - Sprachen darstellen, also vor dem eigentlichem Programmstart erst einmal kompiliert werden müssen, ist Visual Basic eine Interpreter - Sprache, d.h. das Programm wird - ähnlich einem Simultan - Dolmetscher im Fernsehen - Stück für Stück unmittelbar zur Laufzeit übersetzt. Dieses Verfahren erspart zwar dem Programmierer die Wartezeit, bis sein Quell - Code (Programm) in die Maschinensprache des Computers umgesetzt wurde, hat dafür aber einen gewaltigen Nachteil: das Umsetzen des Programms in Maschinensprache beansprucht Rechnerleistung und somit Zeit, die zur Verlangsamung der Programmausführung führt (oft bis zu einem Faktor 10). Aus diesen Gründen hat Microsoft seinem Schützling Visual Basic auch einen Compiler mit auf den Weg gegeben, der dafür sorgt, dass die mit dieser Sprache erstellten Windows - Applikationen auch mit maximaler Geschwindigkeit ausgeführt werden können. Der Compiler setzt dabei alle innerhalb der Projektverwaltung aufgelisteten Formulare und Module zu einem direkt ausführbaren Programm um. Nur die Dateiendung wird von *.vbp in *.exe umbenannt, die ja bekanntlich ein direkt ausführbares Programm kennzeichnet. Von nun an kann das Programm direkt von der Windows - Oberfläche heraus gestartet werden. Visual Basic selbst (hier in Funktion des Interpreter - Programmes) wird nicht mehr zur Programmausführung benötigt. Lediglich eine Datei namens VB40016.DLL für 16 - bit Programme bzw. VB40032.DLL für 32 - bit Programme, die man übrigens - ohne dass Lizenzgebühren anfallen - mit eigenen Programmen weitergeben darf, muss während der Programmausführung vorhanden sein.

Diese Datei, eine dynamische Link - Library (.DLL), enthält wichtige Programmfunktionen, die zwar zur Programmlaufzeit benötigt werden, jedoch nicht direkt in die ausführbare EXE - Datei aufgenommen wurden. Der Vorteil einer solchen DLL besteht darin, dass mehrere (mit Visual Basic kompilierten) Programme auf eine DLL zurückgreifen können. Sie muss also nur einmal auf der Festplatte (im Speicher des Computers) vorhanden sein. Würde man die in der DLL enthaltenen Funktionen in jede mit Visual Basic erstellte Applikation direkt aufnehmen, würden sich deren Umfänge erheblich vergrößern.
DDE und OLE[2]
Der Dynamische Datenaustausch:
Man versteht unter dynamischem Datenaustausch das Kommunizieren zweier Windows - Anwendungen, die gegenseitig Windows - Daten austauschen. Diese Möglichkeit wird ebenfalls von Visual Basic - Anwendungen unterstützt.

Es gibt zwei Möglichkeiten, den dynamischen Datenaustausch zu realisieren: Eine starre Verbindung, die während der Entwicklungszeit hergestellt wird und eine flexible, die erst während der Laufzeit entsteht. Auch über die Zwischenablage lassen sich Daten zwischen einzelnen Anwendungen austauschen, jedoch nicht in dem Umfang und der Flexibilität, wie dies mit dem dynamischen Datenaustausch möglich ist.
Wieso benötigt man den dynamischen Datenaustausch:
Zu Beginn muss gesagt werden, dass auch die Möglichkeiten des dynamischen Datenaustausches begrenzt sind. Allerdings könnte man ohne ihn auch keine Bilder in Schriftdokumente einbinden, keine Daten in einer Excel - Tabelle darstellen und keine Töne in verschiedene Dokumente einbauen. Der dynamische Datenaustausch stellt eine Art Verbindung zwischen den einzelnen DDE - unterstützenden Programmen dar. Jeder hat wohl schon einmal ein Bild in ein Textdokument eingebaut und hat dadurch seine Arbeit "verschönert". Genau diese Verbindung zwischen dem Programm, das das Bild erzeugt hat und dem Programm, mit dem das Textdokument verwaltet wird ist das Ergebnis eines Datenaustausches.
Begriffserläuterungen:
Client und Server: Das Anwendungsprogramm, welches die Kommunikation beginnt und Daten anfordert, heißt Server. In Visual Basic umgesetzt, bedeutet dies, dass Textfelder, Bilder und Bezeichnungsfelder als Client dienen, während Formen (also Fenster) die Aufgabe des Servers übernehmen.
Name des Anwendungsprogramms: Jede Anwendung, die als Server dienen soll, benötigt einen speziellen DDE - Namen - mit diesem wird die Anwendung angesprochen - der aber meist der eigentlichen Anwendungsbezeichnung sehr ähnlich ist (Word für Windows: WinWord, Excel: Excel).
In Visual Basic ist der DDE - Name der Name, der ausführbaren EXE - Datei, falls bereits eine erstellt wurde, ansonsten der Hauptname der Projektdatei.
Aktive und passive Verbindung: Eine aktive Verbindung besteht dann, wenn Client und Server in ständiger Verbindung stehen, d.h. die Daten werden ständig aktualisiert. Im Gegensatz dazu tauscht eine passive Verbindung Daten nur dann aus, wenn der Client diese anfordert.
Hierzu ein Beispiel:
Passive Verbindung: Microsoft WinWord fordert ein Bild von Microsoft Paint an, d.h. die beiden Anwendungen werden verknüpft. Dieses Bild wird nun ein einziges Mal an WinWord übergeben. Ändert sich das Bild in Paint, so hat dies keinen Einfluß auf WinWord und umgekehrt. Die Verbindung wird hiermit gelöscht.
Aktive Verbindung: Auch hier übergibt Paint WinWord ein Bild. Wird dieses nun allerdings in Paint verändert, so erhält auch WinWord das veränderte Bild, d.h. ein neues Bild wird im Dokument dargestellt. Allerdings funktioniert dieser Vorgang nur bei wenigen Programmen, da viele nur ein passive Verbindung zulassen.
Object Linking (Objekt einbinden): Das Objekt einer anderen Anwendung wird in der Rahmenanwendung nur eingebunden, d.h. angezeigt. Eine Bearbeitung ist hier nicht möglich.
Object Embedding (Objekt verknüpfen): Eine Objekt - Verknüpfung geht über die Einbindung hinaus. Das Objekt wird hier nicht nur angezeigt, sondern es kann auch bearbeitet werden. Dazu wird das OLE - Programm (Server) aufgerufen.
OLE - Programm: Eine OLE - Programm ist dasjenige Programm, welches die Daten liefert (Server). Beispielsweise liefert Word für Windows ein Textdokument oder Excel eine Kalkulationstabelle als Daten bzw. Objekt, die dann von der Rahmenanwendung (Client) übernommen werden.
Rahmenanwendung: Eine Rahmenanwendung ist das Programm, welches Objekte von einem OLE - Programm (Server) übernimmt, damit diese angezeigt oder bearbeitet werden können.
OLE - Objekt: OLE - Objekte sind die Daten, die in die Rahmenanwendung zur Anzeige bzw. Bearbeitung übergeben werden.
OLE - Server / OLE - Client: Ein OLE - Server ist die Anwendung, die Daten bzw. Objekte zur Verfügung stellt, welche im OLE - Client eingebettet bzw. mit ihm verknüpft werden. Wird z.B.: in einer Visual Basic - Anwendung eine Excel Tabelle eingebunden bzw. bearbeitet, so ist Excel der OLE - Server und Visual Basic der OLE - Client.
Klasse: Die Klasse eines Objekts legt die Anwendung fest, welche das Objekt erzeugt. Klassen sind z.B.: MsGraph, MsDraw, Word - Dokument oder Excel - Worksheet. Die Klasse ist die formale Definition eines Objekts. Sie ist die Vorlage, nach der zur Laufzeit eine Instanz eines Objekts erzeugt wird. Die Klasse definiert die Eigenschaften des Objekts und die Methoden, die zur Steuerung des Objektverhaltens verwendet werden.
Klassenmodul: Das Klassenmodul ist ein Modul, das die Definition einer Klasse (ihre Eigenschaften - und Methoden - Definitionen) enthält.
Klassenbibliothek: Die Klassenbibliothek ist eine Datei oder ein Teil einer Datei die Standardbeschreibungen von offengelegten Objekten, Eigenschaften und Methoden im Rahmen der OLE - Automatisierung enthält. Objektbibliotheksdateien (.OLB) enthalten Klassenbibliotheken.
Objekt: Objekt ist ein allgemeiner Begriff für Formen und Steuerelemente. Aber auch die Zwischenablage (Clipboard), der Drucker (Printer), der Bildschirm (Screen) sowie die Fehlersucheinrichtung (Debug) zählen zu den Objekten von Visual Basic. Jedem Objekt werden zur Entwicklungs - oder zur Laufzeit bestimmte Eigenschaften (Properties) zugewiesen, die z.B.: die Abmessungen oder die Farben des Objekts festlegen.
Objektbibliothek: Die Objektbibliothek ist eine Datei mit der Erweiterung .OLB, die Informationen zu OLE - Automatisierungs - Controllern (wie Visual Basic) über verfügbare OLE - Automatisierungsobjekte bereitstellt. Der Objektkatalog ist ein Dialogfeld und kann verwendet werden, um den Inhalt einer Objektbibliothek zu untersuchen und Informationen zu den verfügbaren Objekten zu erhalten.

Der dynamische Datenaustausch zur Entwicklungszeit:
Die erste Möglichkeit einen dynamischen Datenaustausch herzustellen, ist die nachstehend beschriebene starre Methode. Hierbei wird bereits während der Entwicklungszeit eines Visual Basic - Projektes eine aktive Verbindung zum anderen Anwenderprogramm hergestellt, die später während der Ausführung in der gleichen Weise wiederaufgenommen wird. Da diese Art der Kommunikation ausschließlich über Visual Basic - Menübefehle abgewickelt wird, ist die zwar einfach zu handhaben aber wenig flexibel und benötigt auch keinen Programmcode. Die Verbindung kann außerdem nur bei Programmbeendigung abgebrochen werden. Darüber hinaus ist diese Methode auch nur für solche Anwenderprogramme geeignet, die über ein Menü Bearbeiten/Verknüpfen und Einfügen (oder ähnliches) verfügen.
Der dynamische Datenaustausch zur Laufzeit:
Nachfolgend ist die zweite flexible Methode beschrieben, einen dynamischen Datenaustausch herzustellen. Diese ist wesentlich flexibler als die oben beschriebene und eignet sich auch für Anwendungen, die nicht über den vorher genannten Menüpunkt verfügen. Der Datenaustausch wird hier während der Programmausführung über Visual Basic - Eigenschaften, - Ereignisse und - Methoden gesteuert, für die der Anwender wiederum Code schreiben kann.
Handles[3]
Fenster, Geräte, Programminstanzen, Bitmaps und Mauszeiger stellen wohl die wichtigsten Objekte in einer Windows - Umgebung dar. Sie können auf verschiedene Arten angesprochen werden. Das bedeutet auch, dass es einen Weg geben muss, diese identifizieren zu können, um sie dann als Parameter an Funktionen weitergeben zu können. Windows identifiziert jedes dieser Objekte mit einer 32bit langen geraden Zahl (Integer), die auch als Handle bekannt ist. Jedes Handle hat als Typenidentifzierer (Identifier) ein kleines h am Anfang. Als Beispiel möchte ich einen einfachen Fall aufzeigen, die API - Funktion SetFocus.

An die SetFocus - Funktion wird ein Parameter übergeben, der das Fenster eindeutig identifiziert. Diese Funktion lautet vollständig also SetFocus(hWnd).

Menu
hMenu
Menüleiste oder Pop - Up Menü
Module
hModule
Zeigt auf ein Codemodul wie z.B. eine DLL oder ein Anwendungsmodul
Palette
hPalette
Farbtabelle
Region
hRgn
Ein Gebiet eines Fensters
Windows
HWnd
Ein Fenster

Neben diesen gibt es auch noch weitere, die allerdings weniger häufig gebraucht werden. Objekte, die von der Windows API benutzt werden, sollten nicht mit Visual Basic Objekten vermischt werden, da diese mit dem Visual Basic Befehl GetObject herausgefunden werden. Diese Objekte werden von OLE (Object Linking and Embedding) oder Visual Basic selbst verändert und sind nicht im Kern der Windows - API vorhanden.
Die Windows - API - Routinen[4]
Was bedeutet API:
API bedeutet Advanced Programmer’s Interface (engl.: die Oberfläche des fortgeschrittenen Programmierers), also eine erweiterte Programmierschnittstelle zu anderen Anwendungen bzw. Dateien.
Wozu benötigt man API - Funktionen:
API - Funktionen stellen einen wichtigen Bereich in der (Visual - Basic) Programmierung dar. Sie sind sozusagen die Schnittstelle zu wichtigen System - Funktionen. Mit ihrer Hilfe können die Möglichkeiten von Visual Basic erheblich gesteigert werden. Visual Basic zielt hauptsächlich darauf ab, die Systemstabilität zu gewährleisten. Dazu muss allerdings auch die Zahl der verfügbaren Funktionen erheblich eingeschränkt werden. Allerdings sind ein Großteil der wichtigen Funktionen nun über die API - Schnittstelle bzw. die API - Funktionen erreichbar. Man kann demzufolge sagen, dass die API - Routinen eine Schnittstelle zwischen den wirklich abgesicherten Visual Basic Funktionen und den absturzgefährdeten Windows - Routinen sind. Diese API - Routinen können von Visual Basic zwar nicht direkt angesprochen werden - sie müssen zuvor deklariert werden - sind später aber voll funktionsfähig. Der einzige Nachteil dieser Funktionen gegenüber den Visual Basic - Funktionen ist der, dass alle Sicherheitsmechanismen bei dem Aufruf einer API von Visual Basic außer Kraft gesetzt sind, da diese bekanntlich nicht zu Visual Basic sondern zu Windows selbst gehören.
Allgemeine Informationen:
Eine besondere Variante, die Leistungsfähigkeit von Visual Basic erheblich zu steigern, liegt im Einsatz von dynamischen Verbindungsbibliotheken, den sogenannten DLLs (Dynamic Link Library).
Auch die Windows API Funktionen sind in diesen Dateien enthalten. Visual Basic selbst kann keine DLLs mit exportierten Funktionen erzeugen. Höhere Programmiersprachen wie z.B.: Delphi oder C/C++ können Funktionen aus DLLs direkt exportieren.
Sicherheitsaspekte beim Gebrauch von API - Routinen:
Die Sicherheits - und Überprüfungsmöglichkeiten von Visual Basic sind beim Aufruf von DLL - Routinen außer Kraft gesetzt. Deshalb ist es notwendig, dass vor jedem Aufruf eines DLL beinhaltenden Programmes die Quelldatei gespeichert wird, um etwaigem Datenverlust vorzubeugen.
Die Deklaration von DLL - Routinen:[5]
An dieser Stelle soll zuerst die Schnittstelle von Visual Basic erklärt werden, die den Zugriff auf DLL - Routinen ermöglicht. Jede DLL - Routine muss vor Ihrem Einsatz zunächst deklariert werden. Neben dem Prozedurnamen muss sowohl die dynamische Verbindungsbibliothek (DLL) als auch die Parameterliste genannt werden. Mit der Anweisung Declare kennzeichnen Sie eine Prozedur als extern (außenständig, nicht direkt in Visual Basic implementiert). Der DLL - Name muss angegeben werden, da die DLL dynamisch zur Laufzeit an ein Programm gebunden ist (sie wird erst während der Ausführung des Programms benötigt, nicht gleich beim Aufruf). Die DLL muss sich entweder im Programm - oder Windows - Systemverzeichnis befinden. Ist dies nicht der Fall, muss explizit der Suchpfad mit angegeben werden. Es sollten jeweils nur Deklarationen in ein Programm aufgenommen werden, die unbedingt benötigt werden.

Die allgemeine Syntax lautet:

DECLARE FUNCTION LIB "BIBLIOTHEK.DLL" [ALIAS "ORIGINALNAME"] ([[BYVAL|BYREF] VARIABLENNAME [AS VARIABLENTYP] [,[BYVAL|BYREF] VARIABLENNAME ...][....]])
BZW.
DECLARE SUB LIB "BIBLIOTHEK.DLL" [ALIAS "ORIGINALNAME"] ([[BYVAL|BYREF] VARIABLENNAME [AS VARIABLENTYP] [,[BYVAL|BYREF] VARIABLENNAME ...][....]])

Der Abschnitt Lib LibName in der Declare - Anweisung teilt Visual Basic mit, wo die Dynamic - Link Library gespeichert ist. Betriebssystem - DLLs sind entweder "User", "GDI" oder "Kernel" oder eine der anderen System - DLLs wie "MMSystem". Bei anderen DLLs ist LibName ein Dateiname, der auch eine Pfadangabe enthalten kann.

Mit der Alias - Klausel kann eine Prozedur deklariert und damit einhergehend umbenannt werden. Diese Umbenennung ist dann sinnvoll, wenn ein Name einer DLL - Prozedur in Visual Basic nicht gültig ist oder aber bereits definiert ist. Wird eine Routine innerhalb DLL lediglich unter einer Ordnungszahl verwaltet, muss die Prozedur wie unten beschrieben deklariert werden.

DECLARE PROZEDURNAME LIB "BIBLIOTHEK.DLL" ALIAS "#ZAHL" .......

Die Ordnungsnummer wird im Zeichenkettenformat angegeben und mit einem Doppelkreuz eingeleitet. Die Parameterliste ist optional, lediglich die runden Klammern sind in jedem Fall mit anzuführen. Die Parameterliste kann einen oder mehrere Parameter enthalten. Jeder Parameter muss mit einem Datentyp versehen werden. Folgende Besonderheiten sind bei der Übergabe von Werten an DLL - Routinen zu berücksichtigen.
Wert oder Referenzübergabe von Argumenten:
Standardmäßig übergibt Visual Basic alle Argumente als Referenz. d.h. Visual Basic übergibt die 32 - Bit - Adresse, an der der Wert gespeichert ist, und nicht den eigentlichen Wert des Arguments. Das Schlüsselwort ByRef muss zwar nicht angegeben werden, man kann es aber zur Dokumentation im Code verwenden, damit offensichtlich ist, wie Daten übergeben werden.

Viele DLL - Prozeduren erwarten, dass ein Argument als Wert übergeben wird, d.h. sie erwarten den eigentlichen Wert und nicht die Speicheradresse des Wertes. Wenn ein Argument als Referenz an eine Prozedur übergeben wird, die eine Übergabe des Wertes erwartet, erhält die Prozedur falsche Daten und kann nicht korrekt ausgeführt werden.

Ein Argument kann als Wert übergeben werden, indem vor der Argumentdeklaration in der Declare - Anweisung das Schlüsselwort ByVal eingefügt wird. Dies gewährleistet, dass das Argument bei jedem Prozeduraufruf als Wert übergeben wird.
Konvertieren von C - Deklarationen nach Visual Basic:
Die Prozeduren in DLLs werden meistens in der Syntax der Programmiersprache C dokumentiert. Um sie von Visual Basic aus aufzurufen, müssen sie in gültige Declare - Anweisungen übersetzt und ordnungsgemäß aufgerufen werden. Die folgende Tabelle enthält eine Liste der wichtigsten C - Deklarationen und der jeweiligen Entsprechung in Visual Basic.
Zeichenkettenübergabe:
Zeichenketten, die an DLL - Routinen übergeben werden, enden im Regelfall mit Chr$(0) (ASCII - String). Das Nullzeichen wird automatisch an eine Zeichenkette, die an eine DLL Routine übergeben wird, angehängt, wenn sie innerhalb der Parameterliste mit dem Schlüssel ByVal deklariert ist. Zeichenketten werden an DLL - Routinen immer als Referenz übergeben. DLL - Routinen liefern in der Regel nur Zeichenketten mit maximal 255 Zeichen zurück. Die Länge einer Zeichenkette kann in der DLL nicht geändert werden, sofern die Routine nicht speziell für Visual Basic geschrieben wurde. Eine Zeichenkette, die ein Ergebnis zurückliefert, muss daher in der Regel zunächst auf 255 Zeichen initialisiert werden. Dies kann mit dem Befehl Variable1$ = Space$(255). Funktionen, die in einem Parameter eine Zeichenkette mit dem Wert Null erwarten, können die Visual Basic Konstante VbNullString erhalten. Zeichenketten fester Länge können an DLL - Funktionen nicht übergeben werden. Gibt eine DLL - Funktion eine Zeichenkette zurück, so ist diese ebenfalls mit Chr$(0) abgeschlossen. Left$(Rückgabewert$, InStr(Rückgabewert$, Chr$(0)) - 1) liefert dann einen String in der richtigen Länge.

Hierzu ein Beispiel: Mit Hilfe einer API - Routine wird versucht, das Systemverzeichnis des Betriebsystemes Windows95 zu eruieren. Angenommen es lautet "C:\WINDOWS\SYSTEM". Diese Variable benötigt mindestens eine Länge von 17 Zeichen. Wird das Feld, also die Variable, in die der Wert geschrieben wird nur mit 15 Zeichen initialisiert, so werden die letzten zwei Zeichen in den Speicher geschrieben. Anstelle der ansonsten reservierten 255 Zeichen (Visual Basic liefert keinen String zurück, der länger ist als 255 Zeichen) sind nun nur 15 Zeichen im Speicher frei. Angenommen, im Speicher würde hinter unserer Variable gleich anschließend eine wichtige Windows - Systemdatei stehen, so würde es zu einem Datenverlust kommen, da die ersten beiden Zeichen der Variable die ersten Zeichen der Systemdatei überschreiben würden. Unter Umständen könnte es auch zu einem Systemabsturz kommen, wenn auf die wichtige Datei unmittelbar danach zugegriffen wird, da sie 2 Byte an Fehlinformationen enthält. Um dies zu verdeutlichen habe ich eine Zeichnung angefertigt.

Hier wurde die Systemdatei Kernel.dll mit der Variable, die die gewünschten Informationen enthält überschrieben. Es wäre aber ebenso möglich, dass unsere Variable von einer anderen Datei überschrieben werden würde, was wiederum einen Datenverlust, nur diesmal bei unserem Programm, zur Folge hätte.
Normalerweise nimmt eine Variable, die mit 255 Zeichen initialisiert wurde, immer 255 Zeichen Platz ein. Es wären also im Normalfall 17 Zeichen und 208 Leerzeichen (208 + 17 = 255).
Ungültige Namen:
Mitunter hat eine DLL - Prozedur einen Namen, der kein gültiger Bezeichner ist. Der Name kann ein ungültiges Zeichen (beispielsweise einen Bindestrich) enthalten oder mit einem reservierten Wort von Visual Basic (beispielsweise GetObject) übereinstimmen. In diesem Fall muss das Schlüsselwort Alias verwendet werden.

Einige Prozeduren in den DLLs der Betriebsumgebung beginnen beispielsweise mit einem Unterstrich. Zwar können Sie Unterstriche in Visual Basic - Bezeichnern verwenden, doch darf der Unterstrich nicht das erste Zeichen sein. Um solche Prozeduren verwenden zu können, muss die Prozedur mit Alias deklariert werden:

DECLARE FUNCTION LOPEN LIB "KERNEL" ALIAS "_LOPEN" (BYVAL FN AS STRING, BYVAL F AS INTEGER) AS INTEGER

In diesem Beispiel ist LOpen der Name der Prozedur, wie er in der Visual Basic - Prozedur verwendet wird. Der Name _lopen ist der Name, der in der DLL erkannt wird.
Der Alias - Abschnitt, kann verwendet werden, wenn immer es angebracht ist. Die folgende Declare - Anweisung ersetzt beispielsweise einen langen Namen (GetWindowsDirectory) durch einen kürzeren Namen (WinDir):

DECLARE FUNCTION WINDIR LIB "KERNEL" ALIAS "GETWINDOWSDIRECTORY" (BYVAL LPBUFFER AS STRING, BYVAL NSIZE AS INTEGER) AS INTEGER

Nun kann die Funktion mit einem kürzeren Namen aufgerufen werden:

DIM WINPATH AS STRING
WINPATH = STRING(145, CHR(0))
WINPATH = LEFT(WINPATH, WINDIR(WINPATH, LEN(WINPATH))) 
Ãœbergeben von Zeichenfolgen:
Visual Basic verwendet einen String - Datentyp, der als BSTR bezeichnet wird und einen Datentyp darstellt, der durch die OLE - Automatisierung definiert wird. Ein BSTR - Wert verhält sich wie ein Zeiger auf das erste Datenbyte. BSTR - Werte verweisen auf Zeichenfolgen, die durch ein Null - Zeichen (ANSI - Wert Null) begrenzt sind. Den Daten ist ein Header vorangestellt, der von Visual Basic verwendete Informationen enthält. Der BSTR - Wert ignoriert diesen Header und verweist auf das erste Datenbyte in der Zeichenfolge.

Die folgende Funktion würde Daten in eine Variable schreiben. Ist diese Variable aber nicht lange genug (z.B.: weniger als zehn Zeichen, obwohl 17 benötigt würden), so würde die API - Funktion über den reservierten Speicher hinausschreiben, ein anderer Inhalt würde überschrieben werden und ein Datenverlust wäre die Folge.

DECLARE FUNCTION GETWINDOWSDIRECTORY LIB "KERNEL" (BYVAL LPBUFFER AS STRING, BYVAL NSIZE AS INTEGER) AS INTEGER

Eine sichere Lösung zum Aufrufen der Prozedur ist das Erstellen eines Rückgabearguments, das mindestens 255 Zeichen lang ist, durch Auffüllen des Arguments mit Zeichen — in diesem Fall mit Null - Zeichen (Binärwert Null):
PATH = STRING(255, 0)
RETURNLENGTH = GETWINDOWSDIRECTORY(PATH, LEN(PATH))
PATH = LEFT(PATH, RETURNLENGTH)
16/32 bit - Anwendungen:
Sehr wichtig bei der Betrachtung von 16 - Bit - und 32 - Bit - Versionen von Visual Basic 4.0 sind Fragen im Zusammenhang mit ANSI und UNICODE. Wenn DLLs geschrieben werden, verwenden ANSI - Zeichenfolgen ein Byte pro Zeichen und UNICODE - Zeichenfolgen zwei Byte pro Zeichen.

Die 16 - Bit - Version von Visual Basic verwendet entweder ANSI - oder DBCS - Zeichenfolgen. Die 32 - Bit - Version von Visual Basic verwendet UNICODE - Zeichenfolgen. Deshalb sollte eine Reihe von Dingen berücksichtigt werden, wenn DLLs für die Verwendung mit Visual Basic 4.0 geschrieben werden.

    Wenn eine 1 - Byte - Variable benötigt wird, kann 'String * 1' in der 16 - Bit - Version von Visual Basic verwendet werden. In der 32 - Bit - Version von Visual Basic nimmt 'String * 1' jedoch tatsächlich zwei Bytes im Speicher ein. Darum wurde der Datentyp Byte eingeführt. Dieser Datentyp nimmt 1 - Byte im Speicher ein, unabhängig davon, ob er in der 16 - Bit - oder in der 32 - Bit - Version von Visual Basic verwendet wird. In Win32 (32bit Bsp.: Win95, WINNT) wird bei Namen von DLL - Prozeduren zwischen Groß - und Kleinschreibung unterschieden. In Win16 (16bit Bsp.: Windows 3.11) ist dies nicht der Fall. GetSystemMetrics und GETSYSTEMMETRICS sind daher unterschiedliche Funktionen. Dennoch ist in diesem Fall nur der erste Name korrekt, so wie er in USER32.DLL existiert. Wenn also die normale DECLARE - Anweisung für diese Funktion:

DECLARE FUNCTION GETSYSTEMMETRICS LIB "USER32" (BYVAL N AS INTEGER) AS INTEGER
auch an anderer Stelle im Projekt existiert (z.B. wenn die FESTSTELL - TASTE bei der Eingabe des Funktionsnamens zufällig gedrückt wird), z.B. als

DECLARE FUNCTION GETSYSTEMMETRICS LIB "USER32" (BYVAL N AS INTEGER) AS INTEGER
wird auch die vorherige Definition dementsprechend geändert.

In Win16 gibt es diesen Unterschied nicht, da bei Funktionsnamen nicht zwischen Groß - und Kleinschreibung unterschieden wird. In Win32 würde jedoch ein Laufzeitfehler auftreten, da GETSYSTEMMETRICS nicht in der DLL existiert. Dieses Problem kann dadurch umgangen werden, indem der Alias - Abschnitt wie folgt verwendet wird:
DECLARE FUNCTION GETSYSTEMMETRICS LIB "USER32" ALIAS GETSYSTEMMETRICS (BYVAL N AS INTEGER) AS INTEGER
So wird sichergestellt, dass der im Alias verwendete Name nicht von einer Umwandlung (falls sie vorkommt) betroffen ist. Unabhängig davon, wie der Name in anderen Teilen des Codes verwendet wird, bezieht sich die Deklaration somit weiterhin auf den korrekten Prozedurnamen in der DLL.
Bedingte Kompilierung:
Die Befehle, die zur bedingten Kompilierung notwendig sind, gleichen den normalen Visual Basic Befehlen (If, ElseIf, Else, End If). Der einzig große Unterschied besteht darin, dass diese Befehle nur einmal ausgeführt werden, und zwar dann, wenn das Programm kompiliert wird. Um dies zu verdeutlichen muss ich an dieser Stelle ein Beispiel aufzeigen: Es ist möglich, dass ein Programm sowohl unter Windows 3.11 (o.ä.) als auch unter Windows95 ausgeführt werden soll. Nun lauten aber die Aufrufe für die Win16 API anders als für die Win32 API. Hier schaltet sich nun die bedingte Kompilierung ein. Falls die Win32 API benötigt wird, werden die Anweisungen für diese geladen und die Anweisungen für die Win16 API übersprungen und umgekehrt.
Geschwindigkeit vs. Sicherheit bei der Nutzung von API - Routinen - Zusammenfassung[6]
Es gibt eigentlich zwei überzeugende Gründe, um die Windows - API mit Visual Basic zu benutzen: gesteigerte Möglichkeiten und verbesserte Performance. Die gesteigerten Möglichkeiten kommen daher, da Visual Basic nur ein stark gekürztes Set der Windows - Möglichkeiten unterstützt. Eben dieses Subset, also eine kleinere Einteilung bewirkt, dass die Programmierung mit Visual Basic sehr sicher ist - mindestens um vieles sicherer als eine andere Programmierumgebung. Kurz gesagt: Visual Basic verbessert die Sicherheit, indem es die verfügbaren Funktionen limitiert.

Sobald man nun beginnt, mit der Windows32 API zu arbeiten, ändert sich dies wieder: Die Sicherheit wird außer Acht gelassen, die Kapazität kommt voll zum Vorschein. Mit verschiedenen Tools wie z.B. denen der Firma Desaware (als Beispiel möchte ich an dieser Stelle die Desaware SpyWorks vermerken) kann ein Visual Basic Programmierer fast an die Möglichkeiten eines C/C++ Programmierers hinkommen. Zusätzlich zu dem Umfang der API - Routinen kommt auch noch eine verbesserte Geschwindigkeit, da die meisten API - Routinen auf Geschwindigkeit hin optimiert wurden. Außerdem kann eine API - Funktion die Arbeit verschiedener Visual Basic Kommandos übernehmen, was sich wiederum positiv auf die Geschwindigkeit auswirkt. Als Beispiel hierfür möchte ich nur die Graphikfunktionen nennen. Zusammenfassend kann gesagt werden, dass es möglich ist, den Kampf Geschwindigkeit gegen Sicherheit zu kontrollieren. Man muss nur aufpassen, welche Funktionen man für welche Aufgaben benötigt.
Vergleich:
Visual Basic Code:
Vorteile
Nachteile
Höchste Sicherheit
Niedrigere Performance (langsamer)
Einfach zu testen und Fehler sind leicht zu beheben
Benötigt oft mehr Programmieraufwand als die Nutzung von Custom Controls
Plattformunabhängig

Win32 API Code:
Vorteile
Nachteile
Höchste Flexibilität
Benötigt sowohl Win32 als auch Win16 Code
Getestet und dokumentiert
Benötigt gute Kenntnisse
Bietet höhere Performance


Custom - Controls (Benutzerdefinierte Steuerelemente) und OLE - Server:
Vorteile
Nachteile
Einfach zu benützen
Benötigt die Auslieferung von zusätzlichen Software - Komponenten
Möglicherweise hervorragende Performance


BeispielProgramm: Computer Informationen: Programmiert von Thomas Linder - 8c - 1998
Ãœber dieses Programm:
Die Idee dieses Programms hatte ich bereits vor langer Zeit. Ich wollte ein Programm entwerfen, das etwas leistet und das man herzeigen kann. Normalerweise habe ich als Schüler nicht soviel Zeit, um ein wirklich anspruchsvolles Programm zu entwerfen. Diese Fachbereichsarbeit gab mir die Gelegenheit dazu, ein Programm aus zwei Gründen zu entwerfen. Der erste Grund ist, wie bereits erwähnt, dass ich schon immer einmal ein leistungsfähiges Programm entwerfen wollte. Der zweite Grund ist, dass ich dies dann machen kann, wenn es mir wirklich etwas nützt.
Aufgrund dieser Fachbereichsarbeit kann ich nun diese beiden Faktoren verknüpfen.
Natürlich kann sich dieses Programm nicht mit den Programmen von professionellen Programmierern messen. Es ist auch erst das zweite Projekt in dieser Größenordnung. Das Ziel dieses Programmes ist es, ein gutes Beispiel dafür zu sein, was mit einfachen Mitteln alles möglich ist. Zu Beginn sollte dieses Programm einfach die Möglichkeiten darstellen, was alles möglich ist. Ich dachte zuerst nicht daran, ein vollständiges Programm zu entwickeln. Im Laufe der Zeit allerdings, kam immer mehr der Wunsch nach einer "richtigen" Oberfläche. Da zuerst die Laufwerksinformationen entwickelt wurden, war zunächst dies mein Hauptfenster. Als ich dann allerdings nicht mehr wußte, wie ich die verschiedenen Schaltflächen anordnen sollte, wurde mir klar, dass eine größere Oberfläche her musste. Ein einfaches Fenster, das sich zu Beginn öffnet und mir zehn verschiedene Schaltflächen zeigte, war mir zu primitiv und unschön. Also beschloß ich, einen Explorer bzw. Dateimanager - Ersatz zu machen. Obwohl auch meine Version viele Funktionen für verschiedene Dateitypen beinhaltet, ist es kein vollwertiger Ersatz. Die Programmierung schritt fort, und kurze Zeit später hatte ich die Systemspeicherinformationen, die Prozessorinformationen und Betriebssysteminformationen. Als Schlußpunkt suchte ich noch einige spielerische aber dennoch nützliche API - Funktionen, die mir ich unter die Rubrik "Verschiedene API - Funktionen" steckte. Vielleicht sind diese im Augenblick nicht nützlich, aber es ist einfacher an sie zu gelangen als sich in der Systemsteuerung von Windows95 herumzuquälen.
Information bezüglich Sourcecode:
Da ich nicht den ganzen Sourcecode abdrucken kann, der gute 34 Seiten umfaßt (+20 Seiten Programmformatierung), habe ich eine CD beigelegt, die sowohl diese Arbeit als auch den vollständigen Code des Programmes enthält. Ich habe mich dazu entschlossen, nur die wichtigsten Stellen abzudrucken. Damit sind die Stellen gemeint, die für die API - Routinen wirklich wichtig sind. Da ich nur wenige, dafür teilweise recht komplizierte API - Routinen verwende, habe ich mich ebenfalls entschlossen alle davon mit dem richtigen Aufruf darzustellen. Diese stellvertretend für die gewaltige Menge an API - Aufrufen. Alle Aufrufe der restlichen Routinen, funktionieren mehr oder weniger nach demselben Prinzip.

Vor dem Programmcode befindet sich eine kurze Beschreibung der Form, die klarmachen soll, was diese Form darstellen bzw. auswerten soll und um was es sich in dem jeweiligen Teilbereich des Programmes handelt.

Der eigentliche Programmcode wird in Blau dargestellt. Nach jedem Programmblock folgt eine kurze Erklärung, die die wichtigsten Schritte verdeutlicht.
Der Sourcecode:
Generelle Informationen:
In diesem Programm kommen sehr viele benutzerdefinierte Datentypen vor. Diese werden, zusammen mit den API - Aufrufen in dem Modul Modul1.bas definiert.
Die Hauptform:
Diese Form ist eigentlich nicht sehr wichtig, denn sie ist nur die Sprungform zu den wichtigen Teilen.

Allerdings enthält sie eine API - Routine. Bei Doppelklick auf eine Datei mit Endung "wav" innerhalb des Dateifensters, wird diese Sounddatei (wav = Sounddatei) automatisch abgespielt. Die der dazu gehörende Code:

Dim PathuDatei As String
If Len(Dir1.Path) > 3 Then 'markierte Datei an Variable PathuDatei übergeben
 PathuDatei = Dir1.Path + "\" + File1.filename
Else
 PathuDatei = Dir1.Path + File1.filename
End If
endung = Trim$(Right$(PathuDatei, 3))
Select Case endung
...
Case "wav"
 xxx& = sndPlaySound(PathuDatei, 1) 'API - Aufruf, um Sound Datei abzuspielen
...
Case Else
...
End Select

Hier wird zuerst der Variable "PathuDatei" der Datentyp String zugewiesen. Der Variable PathuDatei wird darauf der Name und der Ort der Datei, auf die doppelgeklickt wurde, übergeben (Bsp.: "C:\WINDOWS\MEDIA\Der Microsoft Sound.wav". Hierauf werden die letzten drei Zeichen genommen (sie sind die endung), welche dann in der Variable "endung" gespeichert werden. Nun folgt eine Select Case - Anweisung, die je nach "endung" eine bestimmte Prozedur vollzieht. In diesem Fall geschieht dies, wenn die Endung auf "wav" lautet. Ist dies der Fall, so wird eine API - Routine aufgerufen, die den Namen sndPlaySound trägt. Ihr werden zwei Parameter übergeben. Einer übergibt die Datei und wo diese gespeichert ist, der andere bezeichnet die Art, wie die Datei abgespielt wird. Dies ist die einzige API - Routine, die in dieser Form vorkommt.
Die Form ProzInfo:
Auch hier kommt nur eine API - Routine zum Einsatz. Diese liefert allerdings mehr als eine Information. Sie würde noch mehrere Informationen liefern, allerdings sind diese in diesem Programm nicht wichtig. Benötigt werden nur zwei Informationen: Die Anzahl der Prozessoren und den Typ der/des Prozessoren/Prozessors. Diese Informationen werden in einer benutzerdefinierten Variable namens "SysInfo" gespeichert. Hier der Code:
'DEKLARATION DER VARIABLEN
DIM SYSINFO AS SYSTEM_INFO 'BENUTZERDEFINIERTER DATENTYP
DIM M AS STRING
GETSYSTEMINFO SYSINFO 'API - AUFRUF
M$ = "PROZESSORTYP: "
'PROZESSORTYP
SELECT CASE SYSINFO.DWPROCESSORTYPE
CASE PROCESSOR_INTEL_386
 M$ = M$ + "INTEL 386"
CASE PROCESSOR_INTEL_486
 M$ = M$ + "INTEL 486"
CASE PROCESSOR_INTEL_PENTIUM
 M$ = M$ + "INTEL PENTIUM"
CASE PROCESSOR_MIPS_R4000
 M$ = M$ + "MIPS R4000"
CASE PROCESSOR_ALPHA_21064
 M$ = M$ + "ALPHA WORKSTATION"
...
M$ = M$ + VBCRLF
M$ = M$ + "ANZAHL DER PROZESSOREN: "
'ANZAHL DER INSTALLIERTEN PROZESSOREN
ANZ& = SYSINFO.DWNUMBERORFPROCESSORS
M$ = M$ + STR$(ANZ&)

Zu Beginn werden die verschiedenen Variablen initialisiert. "SysInfo" wird als benutzerdefinierte Variable SYSTEM_INFO und "m" als Zeichenkette initialisiert. Die API - Routine wird mit der Anweisung GetSystemInfo aufgerufen. Die verschiedenen Werte werden an die Variable SysInfo übergeben. In der Variable m steht, was später im Bezeichnungsfeld in der Form ausgegeben werden soll. Zuerst das Wort Prozessortyp, dann der dazugehörige Wert, eine Zeilenschaltung und dann die Zeichenfolge "Anzahl der Prozessoren" und deren Wert.

Der Prozessortyp ist in einer Untervariable der Variable SysInfo gespeichert. Diese Untervariable lautet "dwProcessorType". Die gesamte Variable lautet demzufolge "SysInfo.dwProcessorType". Die zweite Untervariable betrifft die Anzahl der Prozessoren und lautet "dwNumberOrfProcessors". Die zusammengesetzte lautet demzufolge "SysInfo.dwNumberOrfProcessors".

In dem Modul Modul.bas befinden sich die Konstanten, die benötigt werden, um den Prozessortyp zu bestimmen, da die Variable dwProcessorType nur einen Hexadezimalwert liefert. Der richtige Prozessor wird durch eine Case - Anweisung ausgewählt.
Die Form OSInfo:
Diese Form stellt Informationen, die das Betriebssystem betreffen, dar. Auch hier wird wieder ein benutzerdefinierter Datentyp verwendet.

DIM VI AS OSVERSIONINFO 'BENUTZERDEFINIERTER DATENTYP
DIM MAJORVERSION AS STRING 'HAUPT VERSION
DIM MINORVERSION AS STRING 'UNTER VERSION
GETVERSIONEX VI 'API - AUFRUF: SPEICHERT INFORMATIONEN IN DER VARIABLE VI
SELECT CASE VI.DWMAJORVERSION
...
VERSIO$ = MA$ + "." + MI$ + "." + M$
...
INFO$ = VI.SZCSDVERSION
...
LABEL1.CAPTION = "MAJOR VERSION: " + MAJORVERSION + VBCRLF
LABEL1.CAPTION = LABEL1.CAPTION + "MINOR VERSION: " + MINORVERSION + VBCRLF
LABEL1.CAPTION = LABEL1.CAPTION + "BUILD: " + STR$(VI.DWBUILDNUMBER) + VBCRLF
LABEL1.CAPTION = LABEL1.CAPTION + "PLATFORM ID: " + STR$(VI.DWPLATFORMID) + VBCRLF
LABEL1.CAPTION = LABEL1.CAPTION + "VERSION: " + VERSIO$ + VBCRLF
LABEL1.CAPTION = LABEL1.CAPTION + "ZUSATZINFORMATIONEN " + INFO$ + VBCRLF
...

Hier wird die Variable "Vi" als benutzerdefinierter Datentyp dimensioniert. Außerdem werden zwei weitere Variablen benötigt: Die Hauptversion und die Unterversion des Betriebssystem. Existiert kein zweites Betriebssystems, so soll eine Meldung im Bezeichnungsfeld auf der Form stehen. Die hier benötigte API - Routine lautet mit vollem Aufruf: "GetVersionEx Vi". Durch diesen werden sämtliche Werte in der Variable Vi gespeichert.

Die Versionsnummer setzt sich aus mehreren Komponenten zusammen. Der Nummer der Hauptbetriebsystems, der Nummer des Unterbetriebsystems und aus der Build Number, die ebenfalls ein Teilbereich der Variable Vi ist.

Eventuelle Zusatzinformationen werden noch in der Variable "szCSDVersion" gespeichert und schlußendlich wird die Information in das Bezeichnungsfeld der Form "OsInfo" eingetragen.
Die Form RamInfo:
Diese Form ist zwar etwas komplizierter aufgebaut, ist allerdings dasselbe wie die vorhergehenden Formen. Sie beinhaltet wiederum eine einzelne API - Routine, die sämtliche Werte in einer Variable abspeichert. Diese werden dann jeweils durch 1024 dividiert, um die nächst - größeren Einheiten zu erhalten (Kbyte, Mbyte, ...).
DIM MEMINFO AS MEMORYSTATUS
GLOBALMEMORYSTATUS MEMINFO
USED& = MEMINFO.DWMEMORYLOAD
'PHYSIKALISCHER SPEICHER (WIRKLICH)
PHYSICAL& = MEMINFO.DWTOTALPHYS / 1024
AVAIL& = MEMINFO.DWAVAILPHYS / 1024
PIP& = 100 * AVAIL& / PHYSICAL&
'PAGE FILE - SPEICHER
PAGEFILE& = MEMINFO.DWTOTALPAGEFILE / 1024
AVAILPAGE& = MEMINFO.DWAVAILPAGEFILE / 1024
PFIP& = 100 * AVAILPAGE& / PAGEFILE&
'VIRTUELLER SPEICHER
VIRTUAL& = MEMINFO.DWTOTALVIRTUAL / 1024
AVAILVIRTUAL& = MEMINFO.DWAVAILVIRTUAL / 1024
VIP& = 100 * AVAILVIRTUAL& / VIRTUAL&

Die Variable memInfo wird hier, wie bei den anderen Formen, als ein benutzerdefinierter Datentyp dimensioniert. Nun wird der API Aufruf mit "GlobalMemoryStatus memInfo" vollzogen. Die Variable beinhaltet nun die verschiedenen Werte für den physikalischen Speicher, den Page File - Speicher und den Virtuellen Speicher in Byte. Sie beinhaltet sowohl den zur Zeit benutzten als auch den zur Zeit freien Systemspeicher. Nun werden die einzelnen Angaben der Reihe nach in Kbyte und in Prozent umgewandelt, um besser lesbare Werte zu erhalten. Zum Schluß werden diese wieder in drei verschiedene Bezeichnungsfelder eingetragen.
Die Form SysInfo:
Diese Form stellt verschiedene Möglichkeiten zur Auswahl, wie Windows beendet werden soll. Dies sind genau die Funktionen, die man beim Abschalten des Computers erhält. Diese Funktionen sind ebenfalls API - Routinen. Genauer gesagt sie sind eine einzelne API - Routine, der als Parameter übergeben werden muss, wie Windows beendet werden soll. Dieses Problem wurde mit vier Optionsknöpfen gelöst (Windows beenden, Windows neu starten, MS - DOS - Modus, Neu Anmelden). Außerdem enthält die Form zwei Schaltflächen, durch die die Auswahl bestätigt oder abgebrochen werden soll (OK, Abbrechen).

IF OPTION1.VALUE = TRUE THEN R& = EXITWINDOWSEX(1, 0)
IF OPTION2.VALUE = TRUE THEN R& = EXITWINDOWSEX(2, 0)
IF OPTION3.VALUE = TRUE THEN R& = EXITWINDOWSEX(8, 0)
IF OPTION4.VALUE = TRUE THEN R& = EXITWINDOWSEX(0, 0)

Dies ist der ganze Code, der für diese vier Möglichkeiten benötigt wird. Die API - Routine lautet "ExitWindowsEx". Ihr wird ein Parameter übergeben, der bestimmt, auf welche Art dies geschieht. Der zweite Parameter ist nicht wichtig. Er wird daher auf 0 (Null) gesetzt. Um unterscheiden zu können, welches Optionsfeld aktiviert wurde, wird die If - Bedingung verwendet.
Die Form SmallDriveDir
Diese Form beinhaltet eigentlich keinen richtigen API - Aufruf. Dennoch ist sie wichtig, um eine Datei auszuwählen, die dann einer anderen Form als globale Variable übergeben wird. Mit Hilfe einer API werden dann aus dieser Datei verschiedene Informationen genommen, die z.B.: bestimmen, ob es eine 32bit - EXE(cute) - Datei ist. Sie ist demzufolge nur ein kleiner Baustein, der in meinem Programm genutzt wird und beinhaltet keine API - Routinen.
Die Form GenInfo:
Diese Datei beinhaltet verschiedene API - Routinen, die den Benutzernamen bzw. den Namen des Computers ermitteln, die Multimedia - Ausrüstung (Soundkarte) ermitteln, den Batteriestatus ermitteln (nur bei einem Notebook interessant), die Systempfade für das Windows - Systemverzeichnis bzw. das temporäre Verzeichnis ermitteln und auch die Sprungplattform zur Form SmallDriveDir ist (32bit - Programme). Diese Form ist sehr komplex und unterschiedet sich von den bisherigen Formen dadurch, dass nicht nur eine einzelne API - Routine, sondern gleich mehrere Funktionen vorkommen.
Hier ein paar Bruchstücke aus dem Code dieser Form:

PRIVATE SUB FORM_LOAD()
X = VBCRLF
' WERTE IN BEZEICHNNGSFELDER EINTRAGEN
LABEL1.CAPTION = "COMPUTERNAME:" + X
LABEL1.CAPTION = LABEL1.CAPTION + "BENUTZERNAME:" + X
LABEL5.CAPTION = ""
'VERSCHIEDENE PROZEDUREN AUSFüHREN
GENINFOSZEIGEN
GETAKKUINF
GETSYSTEMDIRS
GETMMINFO
END SUB

Wird diese Form geladen, so werden als erstes die Beschriftungen in die Bezeichnungsfelder eingetragen. Danach werden verschiedene Prozeduren ausgeführt, von denen jede für einen bestimmten Teil der API - Routinen zuständig ist (GenInfosZeigen: Computer - und Benutzername; GetAkkuInf: Ladezustand des Akkus anzeigen; GetSystemDirs: Systemverzeichnisse ermitteln; GetMMInfo: Multimedia - Informationen ermitteln).
Zuerst zur Prozedur GenInfosZeigen:

AUSGABE = SPACE$(255)
LENGTH = LEN(AUSGABE)
VERWERFEN% = GETCOMPUTERNAME(AUSGABE, LENGTH)
AUSGABE = LEFT$(AUSGABE, LENGTH)
LABEL2.CAPTION = AUSGABE + X
AUSGABE = SPACE$(255)
LENGTH = LEN(AUSGABE)
A% = GETUSERNAME(AUSGABE, LENGTH)
LABEL2.CAPTION = LABEL2.CAPTION + LEFT$(AUSGABE, LENGTH)

Hier wird zuerst die Variable Ausgabe auf 255 Zeichen dimensioniert, d.h. sie hat eine Länge von 255 Zeichen, egal ob nur 10 Zeichen in sie geschrieben werden. Die restlichen Zeichen werden der Einfachheit halber durch Nullen bzw. Leerzeichen ersetzt. Hierauf wird die Länge auf die Länge der Variable Ausgabe gesetzt (in diesem Fall 255). Nun wird die API - Routine GetComputerName aufgerufen. Diese erhält als Übergabewerte zwei Argumente, nämlich den Text (Variable: Ausgabe) und die Länge des Textes (Variable: Length). Damit nun die restlichen Leerzeichen abgeschnitten werden, wird der Befehl "Left" verwendet. Dieser erhält nun ebenfalls zwei Argumente, genau dieselben, die zuvor der API - Routine entnommen wurden. Mit dem Befehl Left werden von der Variable "Ausgabe" soviel Zeichen behalten, wie in der Längenangabe "Length" enthalten sind. Ist Length zum Beispiel 15, so werden 15 Zeichen genommen, der Rest wird abgeschnitten. Nun wird noch die Variable "Ausgabe", die nun genauso viel Zeichen enthält, wie die Information wirklich hat, in das Bezeichnungsfeld eingetragen. Dasselbe geschieht nun mit der API - Routine GetUserName, nur mit dem Unterschied, dass diese Routine den Benutzernamen anstatt des Computer - Namens ausgibt.

Die zweite Prozedur gilt den Akku - Ladestatus - Informationen:

DIM PSTATUS AS SYSTEM_POWER_STATUS
IF GETSYSTEMPOWERSTATUS(PSTATUS) THEN
ELSE
 MSGBOX "FEHLER BEIM ABFRAGEN DES BATTERIESTATUS"
END IF
LABEL3.CAPTION = "AC POWER STATUS:" 'BATTERIESTATUS
SELECT CASE PSTATUS.ACLINESTATUS
 CASE 0
 ..... 
Hier wird zu Beginn die Variable pStatus (steht für Power Status) als benutzerdefinierter Datentyp deklariert. Nun folgt eine Überprüfung, ob der Computer Informationen über den Batteriestatus liefert. Tut er dies nicht, so wird eine Fehlermeldung ausgegeben. Hier wurde die API - Routine in eine If - Schleife mit eingebaut. Auch auf diese Art erhält Visual Basic den Wert der API - Routine (bzw. die Werte). Der API - Routine wird nur ein Argument übergeben, nämlich die Variable, in der die Informationen gespeichert werden sollen. Nun wird je nach Wert mit Hilfe einer Case - Auswahlschleife die Information ermittelt und der dazu passende Text ausgegeben. Nun folgen verschiedene Aufrufe, die verschiedene Werte (alle aus dem benutzerdefinierten Datentyp pStatus) ausgelesen. Diese werden dann in die verschiedenen Bezeichnungsfelder geschrieben.
Die Prozedur GetSystemDirs:

'WINDOWS SYS - VERZEICHNIS ERMITTELN
TEMP$ = SPACE$(255)
LENGTH& = GETSYSTEMDIRECTORY(TEMP$, LEN(TEMP$))
LABEL6.CAPTION = "WINDOWS SYSTEMVERZEICHNIS: " + LEFT(TEMP$, LENGTH&)

'TEMPORäRES VERZEICHNIS ERMITTELN
TEMP$ = SPACE$(255)
LENGTH& = GETTEMPPATH(LEN(TEMP$), TEMP$)
LABEL6.CAPTION = LABEL6.CAPTION + VBCRLF + "WINDOWS TEMP - VERZEICHNIS: " + LEFT(TEMP$, LENGTH&)

Dies ist wiederum eine kurze Prozedur, die nur zwei Aufrufe erfordert. Genau wie bei dem Computernamen wird auch hier die Variable "Temp" (entspricht der Variable "Ausgabe" beim Computernamen) auf die Länge von 255 Zeichen gebracht. Der einzige Unterschied zum Computernamen besteht darin, dass die Länge nicht einzeln als Variable dimensioniert wird. Sie wurde bereits in die API - Funktion mit einbezogen. Ansonsten verläuft der gesamte Aufbau gleich wie bei der ersten Prozedur dieser Form.

Die letzte Prozedur liest aus verschiedenen API - Routinen Informationen zur Multimedia Ausstattung aus.

VERSIONOFMM% = MMSYSTEMGETVERSION
WINOD% = WAVEINGETNUMDEVS 'ANZAHL DER WAVE - IN GERäTE
WONOD% = WAVEOUTGETNUMDEVS 'ANZAHL DER WAVE - OUT GERäTE
'EINTRAGEN
LABEL7.CAPTION = "VERSION DES MM - SYSTEMS: " + STR$(VERSIONOFMM%) + VBCRLF
LABEL7.CAPTION = LABEL7.CAPTION + "ANZAHL DER WAVE - IN GERäTE: " + STR$(WINOD%) + VBCRLF
LABEL7.CAPTION = LABEL7.CAPTION + "ANZAHL DER WAVE - OUT GERäTE: " + STR$(WONOD%)

Zuerst wird mit der Routine mmsystemGetVersion die Versionsnummer des Multimedia - Subsystems ausgelesen. Danach werden noch die Anzahl der Wave - In - (Geräte, die Musik aufzeichnen können) und die Anzahl der Wave - Out - (Geräte , die Musik abspielen können) Geräte ausgelesen. Zum Schluß werden diese Informationen noch in diese Form eingetragen. Damit ist auch die Form GenInfo fertig.

Die Form DiffAPI:
Diese Form stellt mehr oder weniger Funktionen zur Verfügung, die auch über die Systemsteuerung einzustellen sind. Unter anderem beinhaltet sie eine Möglichkeit zum Einstellen der Doppelklickgeschwindigkeit. Diese Form ist nicht dazu da, wirklich zum Nutzen meines Programmes beizutragen. Diese Form ist eher als Darstellung der verschiedenen Möglichkeiten, die mit API - Funktionen möglich sind, zu sehen. Sie beinhaltet im wesentlichen drei Teile: Der erste Teil dient dem Einstellen der Doppelklickgeschwindigkeit. Dazu gehört auch, dass der aktuelle Wert zunächst ausgelesen wird. Dies geschieht bereits beim ersten Öffnen der Form. Außerdem werden hier auch gleich die Werte des Tastaturzeichens ausgelesen (CaretBlinkTime)

'DOPPELKLICKZEIT UND CARET - BLINKZEIT - INFORMATION HOLEN UND EINTRAGEN
LABEL2.CAPTION = STR$(GETDOUBLECLICKTIME) + " MS"
LABEL3.CAPTION = STR$(GETCARETBLINKTIME) + " MS" 

In das erste Bezeichnungsfeld (Label2) wird über die API - Routine "GetDoubleClickTime" die Doppelklickzeit ausgelesen. Durch den Befehl Str$ wird diese in einen Zeichenfolgen - Datentyp umgewandelt und der Zusatz MS (Millisekunden) wird an den Wert angehängt. Das Selbe geschieht mit dem Tastaturzeichen.

Um die Doppelklickgeschwindigkeit einzustellen, benötigt man eine andere API - Routine: Die zur Get - dazugehörende Set - Anweisung

ANFANG:
NEWDCTIME = INPUTBOX("NEUE DOPPELKLICKZEIT EINGEBEN")
IF ISNUMERIC(NEWDCTIME) = TRUE THEN 
 NEWDCTIME = CLNG(NEWDCTIME)
 XXX& = SETDOUBLECLICKTIME(NEWDCTIME)
 STARTPROZ
ELSE 'SONST: FEHLERMELDUNG
 MSGBOX ("BITTE GEBEN SIE EINE GüLTIGE ZAHL IN MS EIN (STANDARD = 500)")
 GOTO ANFANG
END IF

Gleich zu Beginn wird eine Zeilenmarke eingeführt, an die das Programm im Falle eines Fehlers bei der Ausführung springt. Die neue Doppelklickzeit wird über eine InputBox eingegeben. Nun wird überprüft, ob dies überhaupt eine Zahl ist (IsNumeric). Ist dies der Fall, so wird die Zeit vom Zeichenfolgen - Datentyp in den Datentyp Long umgewandelt (Long = Lange Ganzzahl). Mit Hilfe der Funktion SetDoubleClickTime, der als Argument der Wert der neuen Doppelklickzeit übergeben wird, wird nun die neue Doppelklickzeit eingestellt. Zum Schluß wird noch einmal die Prozedur StartProz aufgerufen, die die Werte neu liest und in der Form neu darstellt. Ist nun aber der eingegebene Wert keine Zahl, so wird eine Fehlermeldung ausgegeben und das Programm springt zum Anfang der Prozedur, es fordert demnach den Benutzer zu einer neuerlichen Eingabe auf.

Um die Blinkgeschwindigkeit der Tastaturcursors einzustellen, wird genau dieselbe Funktion verwendet. Die API - Routine für diese Prozedur lautet SetCaretBlinkTime. Der folgende Code bedarf keiner Erklärung, da eigentlich alles schon in der Prozedur zur Einstellung der Doppelklickgeschwindigkeit beschrieben wurde.

ANFANG:
NEWCBTIME = INPUTBOX("NEUE CARET BLINKZEIT EINGEBEN")
IF ISNUMERIC(NEWCBTIME) = TRUE THEN 
 NEWCBTIME = CLNG(NEWCBTIME)
 XXX& = SETCARETBLINKTIME(NEWCBTIME)
 STARTPROZ
ELSE
 MSGBOX ("BITTE GEBEN SIE EINE GüLTIGE ZAHL IN MS EIN (STANDARD = 500)")
 GOTO ANFANG
END IF 

Der nächste Teil, der dem Einstellen der Mauscursor - Koordinaten dient, ist nicht viel komplexer, allerdings wird hier ein benutzerdefinierter Datentyp verwendet, der den X - Wert (horizontal) und den Y - Wert beinhaltet. Im Gegenteil zu den beiden vorhergehenden Funktionen werden die angezeigten Werte nicht nur einmal aktualisiert, sondern bei jeder Bewegung der Maus über der Form.

DIM LPPOINT AS POINTAPI
D& = GETCURSORPOS(LPPOINT)
KOOX = STR$(LPPOINT.X)
KOOY = STR$(LPPOINT.Y)
LABEL1.CAPTION = "AKTUELLE X - KOORDINATE DES MAUSZEIGERS " + KOOX + " PIXEL" + VBCRLF
LABEL1.CAPTION = LABEL1.CAPTION + "AKTUELLE Y - KOORDINATE DES MAUSZEIGERS " + KOOY + " PIXEL"

Zuerst wird die Variable lpPoint als benutzerdefinierter Datentyp dimensioniert. Mit der Funktion GetCursorPos werden die aktuellen Werte in die Variable lpPoint eingetragen. Nun werden die einzelnen Werte aus der Variable ausgelesen, umgewandelt, formatiert und in die Form eingetragen.

Um die Werte zu setzen wird die API - Routine SetCursorPos verwendet.

ON ERROR GOTO ENDE 
DIM XPOS AS LONG 
DIM YPOS AS LONG
XPOS = CLNG(INPUTBOX("BITTE GEBEN SIE DIE X - KOORDIANTE EIN:"))
YPOS = CLNG(INPUTBOX("BITTE GEBEN SIE DIE Y - KOORDIANTE EIN:"))
IF ISNUMERIC(XPOS AND YPOS) = TRUE THEN 
 XXX& = SETCURSORPOS(XPOS, YPOS)
ELSE
 MSGBOX ("FEHLER!!!!!!!!!!!!!!!!")
END IF

ENDE:
Hier wird eine Sprungmarke eingesetzt, um bei einem Fehler zu einem anderen Teil des Programms zu verzweigen. Hierauf werden die X - und Y - Koordinaten als Long - Datentyp dimensioniert. In zwei Eingabekästchen wird der Benutzer aufgefordert die gewünschten Variablen einzugeben. Es folgt eine Gültigkeitsüberprüfung mit dem Verknüpfungsoperator AND. Sind nun beide eine gültige Zahl, so wird das Programm normal fortgesetzt und die API - Routine SetCursorPos kann aufgerufen werden (als Argumente werden ihr der X - und der Y - Wert übergeben). Ist dies nicht der Fall, so wird dieser Teil einfach ausgelassen und es geschieht nichts, außer dass eine Fehlermeldung ausgegeben wird.

Die Form LWInfo:
Diese Form ist wohl die komplexeste Form innerhalb meiner Programmes. Obwohl nur drei API - Routinen vorkommen, ist sie sehr komplex, da verschiedene Werte miteinander verknüpft werden.

Der gesamte Code dieser Form befindet sich in einer einzelnen Prozedur, die aufgerufen wird, sobald die Form geladen wird.

DIM PFAD AS STRING
DIM DRIVETYP AS STRING
DIM DISKNAME AS STRING
DIM T AS STRING
LET X = VBCRLF

PFAD = LEFT$(UEBERGEBEL, 1) + ":\"

RESL& = GETDISKFREESPACE(PFAD$, LPSECTORPERCLUSTER&, LPBYTESPERSECTOR&, LPNUMBEROFFREECLUSTERS&, LPTOTALNUMBEROFCLUSTERS&)

IF RESL& = 0 THEN
 L_INFO = "FEHLER - - - - LAUFWERK NICHT BEREIT"
 EXIT SUB
END IF

BPC& = LPSECTORPERCLUSTER& * LPBYTESPERSECTOR&

PROZ! = LPNUMBEROFFREECLUSTERS& / LPTOTALNUMBEROFCLUSTERS&

‚LAUFWERKSTYP ERMITTELN
SELECT CASE GETDRIVETYPE(PFAD)
 CASE DRIVE_REMOVEABLE
 DRIVETYP$ = "AUSTAUSCHBARE WECHSELPLATTE"
 CASE DRIVE_FIXED
 DRIVETYP$ = "FESTPLATTENLAUFWERK"
 CASE DRIVE_REMOTE
 DRIVETYP$ = "NETZWERKLAUFWERK"
 CASE DRIVE_CDROM
 DRIVETYP$ = "CD - ROM (ISO 9660/JOLIET/DVD)"
 CASE DRIVE_RAMDISK
 DRIVETYP = "RAM - DISK - LAUFWERK"
 CASE ELSE
 DRIVETYP$ = "UNBEKANNT - ANDERER TYP"
END SELECT

‚LAUFWERKSNAMEN ERMITTELN
DISKNAME$ = STRING$(100, 32)
FILESYSTEMNAME$ = DISKNAME$
RESL& = GETVOLUMEINFORMATION(PFAD, DISKNAME$, LEN(DISKNAME$), SERIENNR&, MAXIMUMCOMPONENTLENGTH&, FILESYSTEMFLAGS&, FILESYSTEMNAME$, LEN(FILESYSTEMNAME$))

'NAMEN KAPPEN
DISKNAME$ = LEFT$(DISKNAME$, INSTR(DISKNAME$, CHR$(0)) - 1)
FILESYSTEMNAME$ = LEFT$(FILESYSTEMNAME$, INSTR(FILESYSTEMNAME$, CHR$(0)) - 1)

'DATEISYSTEM FLAGS AUSWERTEN
'UNICODE?
IF FILESYSTEMFLAGS& AND FILE_UNICODE_ON_DISK THEN
 FILESYSTEMNAME$ = FILESYSTEMNAME$ + " (UNICODE)"
END IF
'KOMPRIMIERT?
IF FILESYSTEMFLAGS& AND FILE_VOLUME_IS_COMPRESSED THEN
 FILESYSTEMNAME$ = FILESYSTEMNAME$ + " (KOMPRIMIERT)"
END IF

'VERSION
VERSIONX$ = STR(GETVERSION&)

'EINTRAGEN DER INFORMATIONEN IN DIE RECHTE SEITE
T = DISKNAME + X
T = T + STR$(SERIENNR&) + X
T = T + FORMAT$(FILESYSTEMNAME$, "#,0") + X
T = T + DRIVETYP$ + X + X
T = T + FORMAT$(LPTOTALNUMBEROFCLUSTERS& * BPC&, "#,0") + X
T = T + FORMAT$(LPTOTALNUMBEROFCLUSTERS& * BPC& / 1024, "#,0") + X
T = T + FORMAT$(LPTOTALNUMBEROFCLUSTERS& * BPC& / 1048576, "#,0") + X
T = T + FORMAT$((LPTOTALNUMBEROFCLUSTERS& - LPNUMBEROFFREECLUSTERS&) * BPC&, "#,0") + X
T = T + FORMAT$(LPNUMBEROFFREECLUSTERS& * BPC&, "#,0") + X + X
T = T + FORMAT$(LPTOTALNUMBEROFCLUSTERS&, "#,0") + X
T = T + FORMAT$(LPTOTALNUMBEROFCLUSTERS& - LPNUMBEROFFREECLUSTERS&, "#,0") + X
T = T + FORMAT$(LPNUMBEROFFREECLUSTERS&, "#,0") + X + X
T = T + FORMAT$(LPSECTORPERCLUSTER&) + X
T = T + FORMAT$(LPBYTESPERSECTOR&, "#,0") + X
T = T + FORMAT$(BPC&, "#,0") + X

L_INFO.CAPTION = T

Zu Beginn dieser Prozedur werden verschiedene Variablen dimensioniert, in welchen später die verschiedenen Werte abgelegt werden. Beim Aufruf der Form aus der Form DateiInfo wird der Form LWInfo auch ein Laufwerksbuchstabe mitgeteilt, der hier global übergeben wird (Variable "uebergebel"). Um diesen zu vervollständigen, werden noch ein Doppelpunkt und ein verkehrter Schrägstrich angehängt (\). Somit "weiß" das Programm nun, welches Laufwerk untersucht werden soll. Nun wird die erste API - Routine aufgerufen, der als Argument der Laufwerksbuchstabe (Pfad$) übergeben wird. Die Variablen die sie von der Funktion übernimmt werden in den Variablen lpSectorPerCluster (Sektoren pro Cluster), lpBytesPerSector (Anzahl der Bytes pro Sektor), lpNumberOfFreeClusters (Anzahl der freien Cluster) und lpTotalNumberOfClusters (Gesamtanzahl der Cluster - Einheiten) gespeichert. Es folgt eine Überprüfung, ob der Aufruf gültig war - ansonsten wird eine Fehlermeldung ausgegeben.

Es werden nun die Anzahl der Sektoren / Cluster mit der Anzahl der Bytes /Sektoren multipliziert, um die Anzahl der Bytes / Sektor zu ermitteln. Um eine Prozentanzahl zu erhalten, wird nun die Anzahl der Freien Cluster durch die Anzahl der gesamten Cluster dividiert. Mit Hilfe der API - Routine GetDriveType, der das Laufwerk als Argument übergeben wird, wird der Laufwerkstyp ermittelt (Festplatte, Diskettenlaufwerk, CD - ROM).

Um den Laufwerksnamen und ähnliche Informationen zu ermitteln, wird die dritte Routine benötigt. Sie lautet GetVolumeInformation und gibt als Rückgabewerte den Namen des Laufwerks (und die Länge des Namens), die Seriennummer, Dateisystem - Flags (also Bytes, die verschiedene Eigenschaften der Dateisystems identifizieren), und den Dateisystem - Namen (ebenfalls die Länge) zurück.

Um einen String in passender Länge für das Dateisystem und den Namen zu erhalten, werden diese Variablen nun gekappt. Es werden genau soviel Zeichen verwendet, wie der Rückgabewert liefert (VB Funktion Left$()). Hierauf werden die Dateisystem - Flags "dekodiert". Je nachdem, was für ein Wert zurückgegeben wird, wird entweder der String UNICODE (egal, ob Gross - oder Kleinschreibung) oder komprimiert an den Dateisystem - String angehängt. Die Version wird schlußendlich mit einer kleinen API - Routine namens GetVersion() ermittelt. Schlußendlich werden noch die gesammelten Informationen formatiert (Format$) in das rechte Bezeichnungsfeld eingetragen. Das "X" ersetzt hierbei einen Zeilenschub (vbCrLf).
Das Modul Modul1.bas
Dieses Modul beinhaltet sämtliche API - Aufrufe, die für mein Programm von Bedeutung sind. Ich stelle an dieser Stelle nur zwei vor, die sich in ihrem Aufruf etwas voneinander unterscheiden. Auch beinhaltet dieses Modul die Typdefinitionen. All diese Informationen können direkt aus dem Microsoft API - Katalog kopiert werden. Dieser beinhaltet alle verfügbaren API - Routinen und Typdefinitionen.
'LAUFWERKSBELEGUNG
DECLARE FUNCTION GETDISKFREESPACE LIB "KERNEL32" ALIAS "GETDISKFREESPACEA" (BYVAL LPROOTPATHNAME AS STRING, LPSECTORPERCLUSTER AS LONG, LPBYTESPERSECTOR AS LONG, LPNUMBEROFFREECLUSTERS AS LONG, LPTOTALNUMBEROFCLUSTERS AS LONG) AS LONG

Diese Funktion wird im Programm benötigt, um den Speicherplatz zu ermitteln. Mit der Variable lpRootPathName wird dem Programm mitgeteilt, welches Laufwerk untersucht wird. Diese Variable muss angegeben werden. Die restlichen Namen liefern Informationen wie z.B.: die Anzahl der Sektoren pro Cluster, die Anzahl der Bytes pro Sektor, die Anzahl der freien Cluster und die Anzahl der gesamten Cluster. Mit der Hilfe dieser Funktion kann die Größe der Festplatte oder anderer Laufwerken angegeben werden.

'SYSTEM POWER STATUS - STROMRESSOURCEN
DECLARE FUNCTION GETSYSTEMPOWERSTATUS LIB "KERNEL32" (LPSYSTEMPOWERSTATUS AS SYSTEM_POWER_STATUS) AS LONG

Diese Funktion ermittelt die Akku - Informationen und speichert sie in der als SYSTEM_POWER_STATUS deklarierten Variable lpSystemPowerStatus.
Literaturverzeichnis:
Aitken, Peter G.: Visual Basic for Win95 Insider: The Guide to Hard - To - Find and Undocumented Features. 1. Auflage 1996
Appleman, Daniel: Visual Basic Programmer's Guide to the Win32 Api, 1. Auflage 1996
Heiligensetzer, Stefan / Monadjemi, Peter / Markt und Technik: Visual Basic - Das Kompendium. 1.Auflage München 1992
Hergert, Douglas A. / SYBEX Verlag: Visual Basic - Das Buch. 1.Auflage Düsseldorf 1992
Löffelmann, Klaus / Vüllers Dieter / tewi - Verlag: Visual Basic 3.0 - Professional Edition. 1. Auflage München 1994
Maslo, Andreas / Verlag Data Becker: Visual Basic 5 - Das große Buch. 1.Auflage Düsseldorf 1997
Monadjemi, Peter / SYBEX Verlag: Visual Basic ganz einfach. 1.Auflage Düsseldorf 1992
Steiner, Josef / Valentin, Robert / Hückstädt, Jürgen / Verlag Markt und Technik: Visual Basic 4. 1.Auflage 1996
tewi - Verlag: Visual Basic 4.0 - Das Buch. 1. Auflage 1996
Tischler, Michael / SYBEX Verlag: Visual Basic - Der Einstieg in 20 Schritten. 1.Auflage Düsseldorf 1991
Protokoll
August und Anfang September 97:
Sammeln von Informationen bezüglich des Themas "Visual Basic"
Anfang September:
Festlegen des Themas Visual Basic - API Programmierung
19.9.1997:
Abgabe des Anmeldungsformulars:
Prüfungsgebiet: Informatik
Betreuender Lehrer: Prof. Walter RIGGER
Thema: Visual Basic - API Programmierung:
Oberfläche, Programmierung von Beispielprogrammen, Programmierung (mit Hilfe von Windows - APIs), Versionen der Programmiersprache Visual Basic, Vergleich mit JAVA und C / C++, Object Linking and Embedding (OLE); Selbständig erstelltes Programm zur API - Programmierung
1.10.1997 - 2.10.1997:
Einleitung
Grundlegendes
Programm zur API Programmierung (Aufbau der Formen (Fenster))
4.10.1997:
Kapitel: Programmerstellung mit Visual Basic
Programm zur API Programmierung
5.10.1997:
Programmdesign mit Visual Basic (Namenskonventionen und Quelltextformatierung)
Die grafische Oberfläche
Programm zur API - Programmierung
6.10.1997 - 9.10.1997:
Kapitel: DDE und OLE
Programm zur API Programmierung
15. - 23.10 1997:
Kapitel: API: Aufrufen der Routinen, Multimedia - Funktion wurde in das Programm eingebaut
18.12.1997: Besprechung mit Herrn Professor Walter Rigger wegen des Programmes
Weihnachtsferien (24.12.1997 - 5.1.1998):
Fertigstellung des Beispielprogrammes
Kapitel: Deklaration von API - Routinen, Aufrufkonventionen
Kapitel Unterschiede bzw. Vor und Nachteile zwischen verschiedenen Programmierarten
Glossar, vollständig abgedruckter Quellcode des Beispielprogrammes + Form als Text
9.1.1998: Besprechung mit Herrn Prof. Rigger bezüglich Inhalt: Wegstreichen eines Teils, Dokumentation des Programms nur teilweise vornehmen (wichtigste Passagen genau erklären); Frage bez. Formatierung
12.1.1998 - 17.1.1998: Erklärung des Inhalts der Formen: DateiInfo (Hauptform), ProzInfo, OSInfo, RamInfo und der Form SysInfo
24.1.1998: Erklärung der Form: SmallDriveDir und GenInfo
25.1.1998: Erklärung der Form LWInfo
26.1.1998: Erklärung des Moduls
18.2.1998: letzte Besprechung mit Prof. Rigger wegen Abgabe


[1] Vgl. Appleman, David Visual Basic Programmer’s Guide to the Win32 API 1.Auflage 1996, Seite 20 - 25
[2] Vgl. tewi Verlag / Visual Basic 4.0 - Das Buch. 1.Auflage 1996, Seite 763 - 776
[3] Vgl. Appleman, David Visual Basic Programmer’s Guide to the Win32 API 1.Auflage 1996, Seite 37 - 39, 58 - 59
[4] Vgl. tewi Verlag / Visual Basic 4.0 - Das Buch. 1.Auflage 1996, Seite 897 - 899
[5] Vgl. tewi Verlag / Visual Basic 4.0 - Das Buch. 1.Auflage 1996, Seite 823 - 830
[6] Vgl. Appleman, David Visual Basic Programmer’s Guide to the Win32 API 1.Auflage 1996, Seite 1408 - 1418

10362 Worte in "deutsch"  als "hilfreich"  bewertet