26
Office 2000 Developer Edition Kompendium 301 7 API-Funktionen aufrufen Windows bietet für die Anwender eine hübsche Oberfläche und für uns VBA-Programmierer insgesamt mehrere Tausend Funktionen, die unter dem Namen Application Programming Interface, kurz API, zusammenge- fasst werden. Diese API-Funktionen stehen allen Anwendungen zur Verfü- gung und werden von diesen benötigt, um alle wichtigen Aufgaben während der Ausführung der Anwendung zu erledigen. Zwar sind VBA-Programme nicht auf API-Funktionen angewiesen (um die Details kümmert sich die sog. Laufzeit-DLLs von Office), es gibt allerdings Situationen, in denen sie eine sinnvolle Ergänzung zum Befehlsatz darstellen. Mit Hilfe von API-Funktio- nen lassen sich u.a. Systeminformationen abfragen, Daten aus der Registry auslesen oder in Ini-Dateien schreiben, Disketten formatieren, die Bild- schirmfarben ändern oder die Symbole auf dem Desktop vorübergehend unsichtbar machen. Der Aufruf einer API-Funktion ist einfach, denn er setzt lediglich voraus, dass ein passender Declare-Befehl im Programm enthalten ist. Die eigentliche Schwierigkeit besteht darin, den Funktionsnamen, die Datentypen der Funktionsargumente und vor allem die Arbeitsweise der Funktion zu kennen. Der Aufruf von API-Funktionen ist, auch wenn er nicht besonders kompli- ziert ist, in erster Linie ein Thema für erfahrene VBA-Programmierer, die vor recht speziellen Problemstellungen stehen. Aus diesem Grund sind auch die Beispiele in diesem Kapitel teilweise recht speziell. API-Funktionen wer- den vor allem dann benötigt, wenn man etwas vom Betriebssystem »möchte« und die zur Verfügung stehenden Office-Anwendungen dieses »Etwas« nicht über Objekte und deren Eigenschaften und Methoden zur Verfügung stellen. Für die reine Office-Programmierung sind API-Funktio- nen im Allgemeinen kein Thema. Sie stellen keine Alternative zu den vor- handenen Objekten dar. Stichworte für dieses Kapitel: Allgemeines über API-Funktionen Ein (ganz) einfaches Beispiel Der Declare-Befehl Die Rolle der Datentypen

API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Embed Size (px)

Citation preview

Page 1: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 301

7 API-Funktionen aufrufen

Windows bietet für die Anwender eine hübsche Oberfläche und für unsVBA-Programmierer insgesamt mehrere Tausend Funktionen, die unterdem Namen Application Programming Interface, kurz API, zusammenge-fasst werden. Diese API-Funktionen stehen allen Anwendungen zur Verfü-gung und werden von diesen benötigt, um alle wichtigen Aufgaben währendder Ausführung der Anwendung zu erledigen. Zwar sind VBA-Programmenicht auf API-Funktionen angewiesen (um die Details kümmert sich die sog.Laufzeit-DLLs von Office), es gibt allerdings Situationen, in denen sie einesinnvolle Ergänzung zum Befehlsatz darstellen. Mit Hilfe von API-Funktio-nen lassen sich u.a. Systeminformationen abfragen, Daten aus der Registryauslesen oder in Ini-Dateien schreiben, Disketten formatieren, die Bild-schirmfarben ändern oder die Symbole auf dem Desktop vorübergehendunsichtbar machen. Der Aufruf einer API-Funktion ist einfach, denn er setztlediglich voraus, dass ein passender Declare-Befehl im Programm enthaltenist. Die eigentliche Schwierigkeit besteht darin, den Funktionsnamen, dieDatentypen der Funktionsargumente und vor allem die Arbeitsweise derFunktion zu kennen.

Der Aufruf von API-Funktionen ist, auch wenn er nicht besonders kompli-ziert ist, in erster Linie ein Thema für erfahrene VBA-Programmierer, dievor recht speziellen Problemstellungen stehen. Aus diesem Grund sind auchdie Beispiele in diesem Kapitel teilweise recht speziell. API-Funktionen wer-den vor allem dann benötigt, wenn man etwas vom Betriebssystem»möchte« und die zur Verfügung stehenden Office-Anwendungen dieses»Etwas« nicht über Objekte und deren Eigenschaften und Methoden zurVerfügung stellen. Für die reine Office-Programmierung sind API-Funktio-nen im Allgemeinen kein Thema. Sie stellen keine Alternative zu den vor-handenen Objekten dar.

Stichworte für dieses Kapitel:

Allgemeines über API-Funktionen

Ein (ganz) einfaches Beispiel

Der Declare-Befehl

Die Rolle der Datentypen

Page 2: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium302

Kapitel 7 API-Funktionen aufrufen

Überblick über die Windows-API

Das WinAPI-Viewer-Add-In der MOD 2000

Beispiele

Der Zugriff auf die Registry sowie auf Ini-Dateien wird in Kapitel 8 behan-delt, wo es speziell um das Zusammenspiel mit dem Betriebssystem geht.Dort werden Sie auch erfahren, dass es für einige Situationen, in denen frü-her an API-Aufrufen kein Weg vorbei zu gehen schien, komfortablere Alter-nativen, etwa das FileSystemObject-Objekt, zur Verfügung stehen.

Hinweis:

Lassen Sie sich nicht von der Fülle an API-Funktionen abschrecken. Für dieVBA-Programmierung sind im Allgemeinen höchstens mehrere DutzendAPI-Funktionen interessant. Aus Platzgründen werden in diesem Kapitelnicht sämtliche Deklarationen der vorgestellten API-Funktionen abge-druckt. Für den Fall, dass Sie sich eine Deklaration anschauen möchten, fin-den Sie diese in der Datei Win32api.txt, die vom API-Viewer-Add-Ininnerhalb von MOD 2000 angezeigt wird.

7.1 Allgemeines über API-Funktionen

API-Funktionen sind für die VBA-Programmierer eine tolle Sache, denn sieerweitern VBA um teilweise nicht gekannte Möglichkeiten. Wie schon inder Einleitung angedeutet wurde, muss man allerdings wissen, wann API-Funktionen sinnvoll sind und wann nicht. Folgende Dinge müssen beimAufruf von API-Funktionen berücksichtigt werden:

Beim Aufruf einer API-Funktion gibt VBA die Kontrolle vorübergehendan das Betriebssystem ab. Geht beim Aufruf etwas schief (etwa weil einArgument mit einem falschen Datentyp übergeben wurde) kann es pas-sieren, dass der VBA-Editor und die dazugehörige Office-Anwendung»gnadenlos« abstürzen.

API-Funktionen sind in erster Linie »Servicefunktionen« des Betriebs-systems und als solche in der Regel eher schlicht und einfach. ErwartenSie daher am Anfang nicht zu viel. Die meisten API-Funktionen sindSpezialisten für einen ganz speziellen Zweck. Für Office-Programmekommen sie nur in Ausnahmesituationen in Frage.

Die API ist sehr umfangreich, sodass es eine Weile dauern kann, bisman interessante Funktionen gefunden hat.

API-Funktionen sind zwar keine »Geheimfunktionen«, aus der Sichteines VBA-Programmierers sind sie aber im Allgemeinen unzureichendoder gar nicht dokumentiert. Alleine herauszufinden, welche Funktio-nen es überhaupt gibt und welche für ein bestimmtes Problem in Frage

Page 3: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 303

Allgemeines über API-Funktionen Kapitel 7

kommen (und welche nicht), erfordert eine gewisse Ausdauer beim»Aufspüren« verborgener Informationen und setzt bereits eine gehörigePortion Erfahrung voraus.

Und zum Schluss: Nicht immer ist eine API-Funktion erforderlich. SowohlExcel als auch Word erhalten in ihren Objektmodellen manche unschein-bare Methode oder Eigenschaft, die den Aufruf einer API-Funktion über-flüssig macht (ein Beispiel ist das Task-Objekt von Word mit seiner Send-WindowMessage-Methode, die viele recht spezielle API-Aufrufe überflüssigmachen kann).

Das Fazit aus den »Warnungen« ist, dass API-Funktionen sehr nützlich seinkönnen, man die Erwartungen am Anfang aber nicht zu hoch schraubendarf. Das Beste ist, Sie fangen klein an und verschaffen sich nach und nacheinen Überblick.

7.1.1 Wann sollte man auf API-Funktionen zurückgreifen?

Da es so wichtig ist, hier noch einmal das Kurzresümee des letztenAbschnitts: Für den Aufruf von API-Funktionen gibt es bei der Office-Pro-grammierung keinen zwingenden Grund. Mit zunehmender Erfahrung wer-den Sie allerdings feststellen, dass sich nicht alles mit Hilfe der VBA-Befehleund der Objekte der einzelnen Office-Anwendungen erledigen lässt. Jetztbetreten die API-Funktionen als natürlicher Service des Betriebssystems dieBühne. Welche API-Funktion für welchen Zweck am besten geeignet ist, isteine Frage, die sich erst mit einer gewissen Erfahrung beantworten lässt. Ofttippt man lediglich Funktionsaufrufe ab, die im Rahmen einerTipps&Tricks-Rubrik oder eines Zeitschriftenartikels veröffentlicht wur-den. Zumindest die Mechanik, also das genaue Wie, sollte nach Durchar-beiten dieses Kapitels klar sein.

Ein Wort zu WordBasic und AccessBasic

Dies soll zumindest nicht unerwähnt bleiben: Wer alte WordBasic-Makrosaus Word 6.0 nach Word ab Version 97 oder alte AccessBasic-Programmeaus Access 2.0 oder früher nach Access ab Version 97 übertragen will, musseventuell vorhandene API-Aufrufe von 16 nach 32 Bit umstellen. Für dieseKonvertierung gibt es keine allgemein gültige Anleitung, da es eine Reihevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32(so wird die API von 32-Bit-Windows, also Windows ab Version 95 oderWindows NT) genannt. Grundsätzlich gilt, dass sowohl der Name der Bibli-othek (also z.B. Kernel32 statt Kernel) geändert werden muss und alleInteger-Datentypen zu Long-Datentypen werden. Mit dieser simplen Regellassen sich bereits viele 16-Bit-API-Funktionen mit wenig Aufwand in die

Page 4: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium304

Kapitel 7 API-Funktionen aufrufen

32-Bit-Welt übernehmen. In der MSDN-Hilfe zu Office 2000 (bzw. allge-mein in der Microsoft Knowledge Base) findet man weitere Hilfestellungenund Beispiele.

Unterschiede zwischen Windows 95/98 und Windows NT/2000

Auch dieser Aspekt soll kurz angesprochen werden, wenngleich er im VBA-Alltag nur selten eine Rolle spielen dürfte. Windows 95/98 undWindows NT/2000 unterscheiden sich nicht nur grundlegend in ihrerArchitektur, es gibt auch eine Reihe kleinerer Unterschiede bei den API-Funktionen. Das bedeutet konkret, dass einige wenige Funktionen nur unterWindows NT/2000 zur Verfügung stehen und sich ein und dieselbe Funk-tion in einigen seltenen Fällen unter Windows 95/98 etwas anders verhältals unter Windows NT/2000. Auch hier sei auf die umfangreiche Win32-Referenz der MSDN-Hilfe verwiesen, die für jede Funktion angibt, unterwelchen Windows-Spielarten (es gibt z.B. noch Windows CE, das eine Teil-menge der Win32-API unterstützt) sie zur Verfügung steht. Wer auf Num-mer sicher gehen will, fragt vor dem Aufruf einer »kritischen« API-Funktionmit der API-Funktion GetVersionEx den Typ des Betriebssystems ab undpasst den Aufruf entsprechend an.

Tipp:

Über die API-Funktion GetVersionEx lässt sich relativ einfach feststellen,ob ein VBA-Programm unter Windows 95/98 oder Windows NT/2000läuft. Ein Beispiel finden Sie in Kapitel 8, in dem es um das Zusammenspielmit dem Betriebssystem geht.

7.2 Ein (ganz) einfaches Beispiel

API-Funktionen sind Funktionen des Betriebssystem und als solche aufjedem Windows-PC vorhanden. Sie müssen also nichts installieren, um API-Funktionen nutzen zu können. Zu den wenigen API-Funktionen, derenDeclare-Befehl (mehr dazu im nächsten Abschnitt) halbwegs erfahreneVBA-Programmierer nach kurzer Zeit auswendig hinschreiben können,gehört die Sleep-Funktion, die das Programm, das sie aufruft, für eine vor-gegebene Zeitspanne in einen »Schlafzustand« versetzt1. Das kann immerdann praktisch sein, wenn der nächste Befehl (aus welchen Gründen auchimmer) mit einer festgelegten Verzögerung ausgeführt werden soll. JedeAPI-Deklaration beginnt mit dem Declare-Befehl gefolgt von Function oderSub, da API-Funktionen wie eingebaute VBA-Funktionen oder -Prozedurenaufgerufen werden. Auch wenn es sich bei Sleep um eine Funktion handelt,kann der Rückgabewert getrost ignoriert werden. Wir entscheiden unsdaher für:

Declare Sub Sleep

1 Zumindestens geht es mir so.

Page 5: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 305

Ein (ganz) einfaches Beispiel Kapitel 7

Nun müssen wir VBA über Lib mitteilen, wo (also in welcher Datei) sich dieFunktion befindet. Die Datei heißt Kernel32.dll und da sie sich als System-datei im Windows-Systemverzeichnis befindet, können Erweiterung undPfad entfallen:

Declare Sub Sleep Lib "Kernel32"

Nun kommt der wichtigste Teil, denn die Datentypen der übergebenenArgumente müssen der Reihe nach aufgeführt werden. Die Sleep-Funktionist sehr anspruchslos – ihr genügt lediglich die Dauer der Schlafperiode inMillisekunden als ein Wert vom Typ Long:

Declare Sub Sleep Lib "Kernel32" (ByVal msZeitspanne As Long)

Warum »msZeitspanne«? Nun, warum nicht, denn die Namen der Argu-mente spielen keine Rolle. Es kommt für den späteren Aufruf lediglich aufden Datentyp und die Angabe an, ob das Argument als Wert (ByVal) oderals Referenz (ByRef oder keine Angabe) übergeben werden soll. Da es sichum ein Sub handelt, wird am Ende kein Datentyp aufgeführt. Bei einerFunktion würde hier in der Regel Long stehen.

Das war's. Natürlich lassen sich API-Funktion nur selten so einfach zusam-menstellen, doch soll dieses Beispiel deutlich machen, dass hinter demDeclare-Befehl nichts Geheimnisvolles steckt. Geübte API-Programmiererbenötigen daher auch keine 1.000 Seiten umfassenden »Telefonbücher«,sondern lediglich die Parameter mit ihren Datentypen. Anhand der Datenty-pen lässt sich die Bedeutung eines Arguments dann meistens herleiten. Auchwenn der Name eines Arguments für den Aufruf keine Rolle spielt, wird erim Allgemeinen so gewählt, dass sich über ihn auf die Bedeutung des Argu-ments schließen lässt.

Zum Schluss soll natürlich ein Beispiel für die Sleep-API-Funktion nicht feh-len.

Beispiel

(Sleep.xls):Das folgende Beispiel zeigt in einer Excel-Arbeitsmappe alle geladenenTabellenblätter für genau drei Sekunden an.

Declare Sub Sleep Lib "Kernel32" (ByVal Zeit As Long)For Each shtTemp In ActiveWorkbook.Worksheets shtTemp.Activate DoEvents Sleep 3000Next

Page 6: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium306

Kapitel 7 API-Funktionen aufrufen

In diesem kleinen Beispiel kommt als Verstärkung der DoEvents-Befehl zumEinsatz (»Arbeite die anstehenden Ereignisse ab«), damit Excel die Gelegen-heit erhält, das Tabellenblatt anzuzeigen. Lassen Sie DoEvents einfach weg,um den Unterschied kennen zu lernen.

7.3 Der Declare-Befehl

Jede externe Funktion, die in einem Visual-Basic-Programm aufgerufenwird, benötigt im Allgemein-Teil eines Moduls einen Declare-Befehl. Überdiesen Befehl erfährt VBA vier wichtige Dinge:

Den Namen der Funktion/Prozedur.

Den Namen der DLL, in dem sie sich befindet.

Die Anzahl der Argumente und ihre Datentypen.

Den Datentyp des Rückgabewertes, sofern es sich um eine Funktionhandelt.

In der Regel werden die Deklarationen in einem allgemeinen Modul einge-tragen, da sie so in allen Modulen zur Verfügung stehen. Erfolgt die Dekla-ration in einem Objektmodul (also etwa in einem Benutzerformular oderKlassenmodul) muss dem Declare-Befehl das Schlüsselwort Private voraus-gehen, was bedeutet, dass die Deklaration nur in diesem einen Modul zurVerfügung steht.

Syntax:

Für eine API-Prozedur:

[Public | Private ] Declare Sub Name Lib "Libname" _ [Alias "Aliasname" ][([Argumentenliste])]

oder für eine API-Funktion

[Public | Private ] Declare Function Name Lib "Libname" _[Alias "Aliasname" ] [([Argumentenliste])][As Datentyp]

Die Syntax ist absichtlich etwas ausführlicher. Alle Angaben in eckigenKlammern dürfen wie üblich auch entfallen.

Page 7: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 307

Die Rolle der Datentypen Kapitel 7

7.3.1 Die Bedeutung des Alias

Damit die Dinge nicht zu einfach werden, besitzen viele API-Funktioneneinen sog. Aliasnamen. Dies ist nichts anderes als der »wahre« Name einerFunktion. Jener Name, der unmittelbar auf Declare Sub oder Declare Func-tion folgt, ist nur ein Stellvertretername. Enthält der Declare-Befehl dasSchlüsselwort Alias, ist der Name vor dem Schlüsselwort der neue Name fürden Aufruf innerhalb des Programms, der Name nach dem SchlüsselwortAlias dagegen der wahre Name der Funktion. Die Verwendung eines Aliasbringt mehrere Vorteile:

Bei API-Funktionsnamen kommt es auf die Groß-/Kleinschreibung an.Wird der wahre Funktionsname über einen Alias vereinbart, spielt dieGroß-/Kleinschreibung für den Zweitnamen keine Rolle.

Ein und dieselbe API-Funktion kann mehrfach deklariert werden (etwa,um verschiedene Datentypen für ein und dasselbe Argument übergebenzu können – das erspart die Verwendung von As Any). Ein Beispiel istdie Funktion GetPrivateProfileString, der für den Sektionsnamen zumeinen ein Sektionsname (String), zum anderen ein Nullzeiger (darge-stellt durch die Konstante vbNullString) übergeben werden kann.

Lange Funktionsnamen können einen Zweitnamen in Kurzschreibweiseerhalten.

Und es gibt noch einen weiteren Grund, der etwas mit dem Umstand zutun hat, dass es viele API-Funktionen in einer ANSI- und einer Uni-code-Varianten gibt. Da VBA mit dem ANSI-Zeichensatz arbeitet,kann es nur die ANSI-Varianten aufrufen. Um die »A«-Version etwaseinfacher aufrufen zu können, werden diese Funktionen mit einem Ali-asnamen ausgestattet, bei dem die Unterscheidung nicht getroffen wird.

Hinweis:

In den meisten Fällen müssen Sie sich um die Bedeutung eines Aliasnamenskeine Gedanken machen. Sollte eine API-Funktion einen Alias erforderlichmachen, ist dieser im Declare-Statement bereits enthalten.

7.4 Die Rolle der Datentypen

Entscheidend für den Aufruf einer API-Funktion sind die Datentypen derFunktionsparameter. Diese müssen beim Aufruf mit jenen Datentypen über-einstimmen, die die Funktion erwartet. Normalweise ist dies kein Thema,da Sie den Declare-Befehl aus dem API-Viewer-Add-In übernehmen undsich über die Datentypen keine Gedanken machen müssen, da diese bereitsstimmen. Es gibt aber auch Ausnahmen:

Page 8: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium308

Kapitel 7 API-Funktionen aufrufen

Sie möchte eine Funktion aufrufen, für die es keinen Declare-Befehlgibt.

Sie möchte einen bereits vorhandenen Declare-Befehl modifizieren.

Der Declare-Befehl aus Win32api.txt ist fehlerhaft.

In allen drei Situationen müssen Sie in der Lage sein, den Originaldatentyp(der der Programmiersprache C entstammt) in den entsprechenden VBA-Datentyp zu »übersetzen«. Dabei soll Ihnen Tabelle 7.1 behilflich sein. ImZweifelsfall verwenden Sie »ByVal As Long«. Das garantiert zwar nicht injedem Fall, dass die Funktion funktioniert, führt aber auch nicht zu einemAbsturz.

Tabelle 7.1:Die wichtigsten API-

Datentypen undihre VBA-Pendants

Original API-Datentyp

Größe in Byte

VBA-Deklaration

Besonderheiten beim Aufruf

BOOL 4 As Long Anders als unter VBA steht ein True-Wert für 1 und nicht für -1. Eine Abfrage auf True muss daher wie folgt ausse-hen:

If IsWindowVisible(hWnd) Then

Würde man auf True prüfen, würde die Abfrage nicht funktionieren.

LPSTR 4 As String API-Funktionen erwarten eine Zeichen-kette, die mit einem Null-Byte beendet wird. Damit VBA eine solche Zeichen-kette übergibt, müssen String-Parame-ter immer mit ByVal übergeben werden.

SHORT 2 As Integer 16-Bit-Parameter spielen bei API-Funk-tionen normalerweise keine Rolle.

WORD 2 As Integer 16-Bit-Parameter spielen bei API-Funk-tionen normalerweise keine Rolle.

UINT 2 As Integer Vorzeichenlose Datentypen werden von VBA nicht unterstützt, spielen bei API-Aufrufen im Allgemeinen auch keine Rolle.

hwnd 4 As Long Benutzerformulare und Steuerele-mente besitzen keine hWnd-Eigen-schaft. Diese muss z.B. über die Find-Windows-API-Funktion erfragt werden.

Page 9: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 309

Überblick über die Windows-API Kapitel 7

7.5 Überblick über die Windows-API

Die Windows-API ist sehr umfangreich und zudem nicht einheitlich struktu-riert, da mit jeder neuen Windows-Version, jeder neuen Version des InternetExplorer und jedem kleinen Shell-Update unter Umständen neue Funktio-nen hinzukommen können. Es ist also nicht ganz einfach, sich einen Über-blick zu verschaffen. Zu den Kernfunktionen gehören die Funktionen derdrei Systemdateien:

Gdi32.dll – Grafikfunktionen, wobei Windows auch Textausgaben alsGrafikausgaben durchführt. Auch die Druckerausgabe fällt in die Kate-gorie Grafikausgabe und unterscheidet sich nur durch einen anderenGerätekontext.

Kernel32.dll – Kernfunktionen, z.B. Speicherverwaltung und Task-Management.

User32.dll – Fenstermanagement, Nachrichtenverwaltung, Umgangmit Menüs, Textmarken, Zeitgeber usw.

Neben diesen Kern-DLLs existieren zahlreiche »Extensions«, wie z.B.Comctl32.dll, Mapi32.dll, Netapi32.all und Winmm.dll, die ebenfalls wich-tige API-Funktionen enthalten. VBA-Programmierer müssen nichts überdiese DLLs wissen. Sie wurden nur aufgezählt, um deutlich zu machen, dasssich API-Funktionen nicht an »geheimnisvollen Orten«, sondern stets inSystemdateien (in der Regel handelt es sich um Dateien mit der Erweiterung.Dll) aufhalten.

Hinweis:

Verwenden Sie in einem VBA-Programm »exotische« API-Funktionen (z.B.Funktionen aus der Speech-API), kann nicht vorausgesetzt werden, dassdiese auf jedem Office-PC vorhanden sind. Soll ein Office-Programm, dasdiese API-Funktionen benutzt, auf einen solchen PC übertragen werden,muss die Systemdatei zusammen mit dem Programm ausgeliefert werden.

NULL 4 beliebig oder As Any

Für sog. NULL-Werte gibt es bei VBA vordefinierte Konstanten: vbNullString (für Strings) und vbNullChar für ein ein-zelnes Zeichen. NULL-Werte vom Typ Long werden als 0& übergeben.

CHAR 1 As String * 1 Ein Char-Wert steht für einen einzelnen, vorzeichenbehafteten 1-Byte-Wert. Spielt bei API-Funktionen im Allgemei-nen keine Rolle.

Original API-Datentyp

Größe in Byte

VBA-Deklaration

Besonderheiten beim AufrufTabelle 7.1:Die wichtigsten API-Datentypen und ihre VBA-Pendants(Forts.)

Page 10: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium310

Kapitel 7 API-Funktionen aufrufen

Um diese Dinge kümmert sich im Allgemeinen der Packet- und Weitergabe-Assistent (ein Add-In aus MOD 2000), der in Kapitel 27 an der Reihe ist.

7.6 Der WinAPI-Viewer von VBA

Der WinAPI-Viewer von VBA ist ein nützliches Add-In, das den Inhalt derTextdatei Win32api.txt im Rahmen des VBA-Editors zugänglich macht. DieDatei Win32api.txt ist eine in der VB/VBA-Welt sehr verbreitete Textdatei,in der die Deklarationen über 1.000 API-Funktionen, Typen und Konstan-ten enthalten sind. Win32api.txt ist jedoch keine Referenz, in der die Funk-tionen auch erklärt werden. Sie finden hier lediglich die Declare-, Type- undConst-Befehle, die Sie über die Zwischenablage bequem in ein Modul über-nehmen. Das erspart Ihnen nicht nur das Abtippen, sondern stellt auchsicher, dass Sie stets die richtige Deklaration verwenden (allerdings enthältWin32api.txt auch ein paar kleinere Fehler und Unstimmigkeiten).

Hinweis:

Der WinAPI-Viewer zeigt die API-Deklarationen nicht sofort an. Die DateiWin32api.txt muss erst über den Befehl DATEI/TEXTDATEI LADEN geladenwerden. Das Umwandeln in eine Datenbank bringt im Allgemeinen keineVorteile2.

2 Auch wenn der WinAPI-Viewer einen anderen Eindruck erweckt, es gibt außer Win32api.txt keine anderen Dateien, die geladen werden könnten.

Abbildung 7.1:Der Win32-API-

Viewer bietetüber die DateiWin32api.txtviele fertige

Deklarationen vonAPI-Funktionen

und derenDatentypen an

Page 11: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 311

Beispiele Kapitel 7

Hinweis:

Der API-Viewer ist lediglich ein Betrachter für die Textdatei Win32api.txt.Wenn ein Office-Programmierer nicht MOD 2000 besitzt, heißt das natür-lich nicht, dass derjenige in seinen VBA-Programmen keine API-Funktionenbenutzen kann. Zum einen findet man die Datei an verschiedenen Stellen imWeb (u.a. auch auf der Microsoft-Office-Entwicklerseite), zum anderenkann man notfalls eine Deklaration auch abtippen.

7.7 Beispiele

Den Umgang mit API-Funktionen lernt man am besten an kleinen Beispie-len, zumal diese in den meisten Fällen rein zweckgebunden eingesetzt wer-den und man lediglich möchte, dass es funktioniert, ohne genau zu fragen,warum es funktioniert. Bei den folgenden Beispielen geht es in erster Linieum das Prinzip des API-Aufrufs und der Parameterübergabe. Weitere Bei-spiele finden Sie in Kapitel 8, da API-Funktionen vor allem beim Zusam-menspiel mit dem Betriebssystem eine Rolle spielen.

Hinweis:

Jedes Beispiel befindet sich aus Gründen der besseren Übersichtlichkeit ineiner eigenen Xls-Datei. Nach dem Laden der Xls-Datei können Sie das Bei-spiel entweder über die Symbolleiste starten oder auf den VBA-Editorumschalten und das Benutzerformular starten.

7.7.1 Lassen sich API-Beispiele für Visual Basic nach VBA übertragen?

Bevor es mit den Beispielen losgeht, noch ein kurzer Hinweis. Im Web findetman sehr viele API-Beispiele für Visual Basic. Lassen sich diese 1:1 nachVBA übertragen? Im Prinzip ja, denn die Syntax des Declare-Befehls und dieDatentypen sind identisch. Allerdings bietet Visual Basic eine Umgebung,die etwas besser auf die API abgestimmt ist. So besitzen Formulare und Bild-felder bei Visual Basic eine hDC-Eigenschaft, die einen direkten Zugriff aufden Gerätekontext der Zeichenfläche erlaubt. Praktisch alle Steuerelemente(mit Ausnahme des Bezeichnungsfeldes, der Linien- und Figurenelementeund der Anzeige) sind ebenfalls Fenster mit hWnd-Eigenschaft. DasMsForms 2.0-Modell ist dagegen eine »Eigenkonstruktion«, die mit demFormularmodell von Visual Basic nur oberflächliche Gemeinsamkeiten auf-weist. Benutzerformulare und die Anzeige bieten keine hDC-Eigenschaft,sodass sich alle GDI-API-Funktionen nicht benutzen lassen. Bei Benutzer-formularen muss die hWnd-Eigenschaft zunächst über eine FindWindow-API-Funktion ermittelt werden. Es muss also von Fall zu Fall geprüft wer-den, ob eine API-Funktion überhaupt aus dem VBA-Editor heraus aufgeru-fen werden kann.

Page 12: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium312

Kapitel 7 API-Funktionen aufrufen

7.7.2 Abspielen einer Sounddatei

Leider bietet VBA keinen Befehl zum Abspielen von Wav-Dateien (also vonSoundateien, die im Wave-Format vorliegen). Das ist ein wenig schade,denn mehr »Multimedia« wird in vielen Fällen gar nicht benötigt. Um einenVBA-Programm dennoch ein paar Klänge entlocken zu können, gibt esmehrere Möglichkeiten:

Man ruft über die Shell-Funktion (siehe Kapitel 8.1) die Medienwieder-gabe (Mplayer2.exe) und übergibt als Parameter den Namen der abzu-spielenden Mediendatei (z.B. eine MP3-Datei oder einen MPEG2-Vide-oclip auf einer DVD). Dies ist eine einfache und für viele Zwecke auchausreichende Lösung.

Man verwendet eines der zahlreichen »Multimedia«-Steuerelemente,die man im Internet findet, die allerdings auf einem Benutzerformularangeordnet werden müssen.

Man ruft die API-Funktion sndPlaySoundA auf. Das ist der einfachsteWeg, wenn lediglich Wav-Dateien abgespielt werden sollen.

Beispiel

(PlaySound.xls):Das folgende Beispiel benutzt die API-Funktion sndPlaySoundA, um dieWav-Datei Exclame.wav im Verzeichnis C:\Windows\Media abzuspielen(tragen Sie für strDateiname den Pfad einer Wav-Datei auf Ihrem PC ein).Beachten Sie, dass die API-Funktion im Declare-Befehl einen Alias erhält –im Programm wird sie PlaySound genannt. Die Funktion erwartet als Argu-mente neben dem Dateinamen der Wav-Datei eine oder mehrere Konstan-ten, die den Arbeitsmodus bestimmen.

Sollte sich die Datei nicht im aktuellen Verzeichnis der Anwendung oderdem Verzeichnis, von dem die Anwendung aus gestartet wurde, befinden,durchsucht Windows das Systemverzeichnis, das 16-Bit-Systemverzeichnis(nur Windows NT) und schließlich alle Verzeichnisse, die über die Umge-bungsvariable Path festgelegt werden.

Option Explicit

Private Declare Function sndPlaySound Lib "WINMM.DLL" Alias _ "sndPlaySoundA" (ByVal lpszSoundName As String, _ ByVal uFlags As Long) As Long

Const SND_SYNC = &H0Const SND_ASYNC = &H1Const SND_NODEFAULT = &H2Const SND_LOOP = &H8Const SND_NOSTOP = &H10

Sub WavSpielen ()

Page 13: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 313

Beispiele Kapitel 7

Dim strDateiname As String Dim lngRet As Long, lngFlags As Long strDateiname = "C:\Windows\Media\Exclame.wav" lngFlags = SND_ASYNC Or SND_NODEFAULT lngRet = PlaySound(strDateiname, lngFlags)End Sub

Die SND-Konstanten legen die Arbeitsweise der API-Funktion fest. Sobestimmt SND_ASYNC, dass die Funktion nicht wartet, bis die Wav-Dateiabgespielt wird, das Abspielen also im »Hintergrund« stattfindet (sieheTabelle 7.2).

Hinweis:

Auch die Konstantendeklarationen finden Sie in Win32api.txt und stehendamit über den API-Viewer zur Verfügung. Sie müssen die Konstantende-klarationen daher weder abtippen, noch die Werte der Konstanten kennen.

Tabelle 7.2:Die Bedeutung der SND-Konstanten der API-Funktion sndPlaySound

Konstante Bedeutung

SND_SYNC Die Klangdatei wird synchron abgespielt, d.h. das Pro-gramm wird erst dann fortgesetzt, nachdem die Klangda-tei vollständig abgespielt wurde.

SND_ASYNC Die Klangdatei wird asynchron abgespielt, d.h. das Pro-gramm wird unmittelbar nach dem Aufruf der Funktion fortgesetzt.

SND_NODEFAULT Ist die Klangdatei ungültig, wird nicht die Standardklang-datei abgespielt.

SND_LOOP Es wird eine »Endlosschleife« bis zum nächsten Aufruf der Funktion gestartet.

SND_NOSTOP Die aktuell abgespielte Klangdatei wird nicht angehalten.

SND_NOWAIT Die Funktion wartet nicht, bis der Soundtreiber bereit ist.

SND_MEMORY Das Argument lpszSoundName ist kein Dateiname, son-dern ein Zeiger auf einen Arbeitsspeicherbereich.

SND_ALIAS Der angegebene Parameter für den Dateinamen ist ein Alias für einen Systemklang.

Page 14: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium314

Kapitel 7 API-Funktionen aufrufen

Abspielen von Systemklängen

Die sndPlaySoundA-API-Funktion ist auch in der Lage, Systemklänge abzu-spielen. Dies sind Klangdateien, die über die Systemsteuerung (Applet Akus-tische Signale bzw. Sounds und Multimedia bei Windows 2000) mit System-ereignissen, wie dem Öffnen eines Fensters oder Beenden von Windows,verbunden wurden. Dazu muss beim Aufruf der API-Funktion anstelle desDateinamens der Name eines Systemereignisses angegeben und zusätzlichdie Konstante SND_ALIAS übergeben werden.

Beispiel:

Der folgende Befehl spielt die Wav-Datei ab, die mit dem SystemereignisFrage verbunden ist:

lngRet = PlaySound("SystemQuestion", SND_ALIAS)

Die Namen der Systemereignisse sind in der Registry im ZweigHKEY_CURRENT_USER\AppEvents\Schemes\Apps\.Default abgelegt. Zu-sätzlich existiert ein Zweig für jedes angelegte Soundschema.

Tabelle 7.3:Die Namen vonSystemsounds

SND_FILENAME Der angegebene Parameter für den Dateinamen ist ein Dateiname. Kann im Allgemeinen entfallen.

SND_RESOURCE Der angegebene Parameter für den Dateinamen ist eine Ressourcenbezeichnung. In diesem Fall befindet sich die Klangdatei eingebettet in einer Ressourcendatei. Der Zugriff auf Ressourcendateien muss bei VBA 6.0 über API-Funktionen (LoadResource) erfolgen. Ressourcenda-teien, sie werden mit einem Ressource-Editor erstellt, wie er u.a. Teil von Visual Basic 6.0 ist, bieten den Vorteil, dass sie mehrere Wav-Dateien (oder Bitmaps oder Texte) in einer einzigen Datei vereinigen.

Konstante BedeutungTabelle 7.2:

Die Bedeutung derSND-Konstantender API-FunktionsndPlaySound

(Forts.)

Name des Systemsounds Wird aufgerufen beim ...

EmptyRecylceBin Papierkorb leeren.

MailBeep Eintreffen neuer E-Mail-Nachrichten.

Maximize Vergrößern des Fensters.

MenuCommand Auswahl eines Menübefehls.

MenuPopup Öffnen eines Menüs.

Open Öffnen eines Programms.

SystemExit Beenden von Windows.

Page 15: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 315

Beispiele Kapitel 7

7.7.3 Suchen nach einem Fenster

Zunächst vorweg: Die Suche nach einem Fenster bedeutet nicht festzustel-len, ob ein bestimmtes Fenster vorhanden oder sichtbar ist. Es bedeutet indiesem Zusammenhang lediglich, die sog. Bezugsnummer eines Fensters zuermitteln. Die meisten Anwendungen arbeiten mit mindestens einem Fens-ter. Aus der Sicht von Windows ist ein Fenster ein »Objekt«, das überbestimmte Attribute (z.B. ob es zu einem anderen Fenster gehört oder wel-chen Fensterhintergrund es besitzt) verfügt. Jedes Fenster besitzt drei festeMerkmale: Einen »Klassennamen« (die Klassen haben nichts mit den VBA-Klassen zu tun, die Namensübereinstimmung ist rein zufällig), durch dieu.a. auch die Fensterattribute bestimmt werden, eine Fensterbezugsnummerund einen Titel. Möchte man per API-Funktion auf ein Fenster zugreifen,muss man dessen Fensterbezugsnummer kennen. Diese lässt sich über dieFindWindow-Funktion herausfinden. Der Funktion wird entweder derKlassenname oder der Titel des Fensters übergeben. Hat man das Fensterauf diese Weise gefunden (also die richtige Fensterbezugsnummer herausge-funden), kann man es z.B. in den Vordergrund bringen, einzelne Fenster-attribute ändern oder das Fenster schließen. Wohlgemerkt gilt dies für jedesFenster und nicht nur für jene Fenster, die Teil der VBA-Anwendung sind.

Beispiel (Fenster-

Suche.xls):Das folgende Beispiel ermittelt über die FindWindow-API-Funktion dieFensterbezugsnummer des Benutzerformulars usrFindWindow. Und damitmit dem Fenster etwas passiert, wird es über die API-Funktion SetWindow-Pos zum »Topmost Window« erklärt, das sich stets an oberster Stelle allerFenster befindet. Durch einen Klick auf die Schaltfläche, der einen erneutenAufruf der API-Funktion SetWindowPos zur Folge hat, erhält das Fenstersein normales Verhalten wieder zurück.

Das Projekt besteht aus zwei Modulen: Dem allgemeinen Modul basFens-terSuche, das die API-Deklarationen enthält, und dem BenutzerformularusrFensterSuche:

SystemStart Start von Windows

SystemQuestion Anzeigen eines Fragezeichensymbols.

SystemExclamation Anzeigen eines Ausrufezeichensymbols.

SystemHand Kritischen Abbruch.

Name des Systemsounds Wird aufgerufen beim ...Tabelle 7.3:Die Namen von Systemsounds(Forts.)

Page 16: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium316

Kapitel 7 API-Funktionen aufrufen

Das Modul basFensterSuche

Option Explicit

Private Declare Function FindWindow Lib "user32" _ Alias "FindWindowA" (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long

Private Declare Function SetWindowPos Lib "user32" _ (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _ ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _ ByVal cy As Long, ByVal wFlags As Long) As Long

Const SWP_NOMOVE = 2Const SWP_NOSIZE = 1Const FLAGS = SWP_NOMOVE Or SWP_NOSIZEConst HWND_TOPMOST = -1Const HWND_NOTOPMOST = -2

Sub FensterPosition(ByVal strTitel As String, Modus As Boolean)' Übergabe von UserForm funktioniert anscheinend nicht,' Caption-Eigenschaft steht in Kopie nicht zur Verfügung Dim lngRet As Long Dim hwnd As Long hwnd = FindWindow(vbNullString, strTitel) If hwnd = 0 Then MsgBox "Fenster wurde nicht gefunden!" Exit Sub End If

If Modus = True Then lngRet = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, _ FLAGS) Else lngRet = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, _ FLAGS) End IfEnd Sub

Das Benutzerformular usrFensterSuche

Das Benutzerformular besteht aus den Schaltflächen cmdImmerAnSpitzeund cmdNormal.

Option Explicit

Private Sub cmdImmerAnSpitze_Click() FensterPosition Me.Caption, True

Page 17: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 317

Beispiele Kapitel 7

End Sub

Private Sub cmdNormal_Click() FensterPosition Me.Caption, FalseEnd Sub

7.7.4 Auflisten aller aktiven Fenster

Unter Windows sind nicht nur die sichtbaren Fenster aktiv, viele Anwen-dungen legen unsichtbare Fenster an, die entsprechend nur im Hintergrundarbeiten und im Allgemeinen sehr spezielle Funktionen übernehmen. Unternormalen Umständen sind schnell 80 bis 100 Fenster aktiv. Möchte manaus irgendeinem Grund eine Liste aller Fenster erhalten, muss man entwedermit der FindWindow-Funktion jedes Fenster einzeln ausfindig machen(wobei hier die Eltern-/Kind-Hierarchie zwischen den Fenstern berücksich-tigt werden muss) oder die EnumWindows-Funktion genau einmal aufru-fen. Diese Funktion gibt aber nicht (wie man es erwarten könnte) eine Listemit den Titeln und den Bezugsnummern aller Fenster zurück. Statt dessenruft die Funktion für jedes Fenster eine (VBA-) Funktion auf, deren Adressebeim Aufruf von EnumWindows übergeben wurde. Dadurch ist die Funk-tion sehr viel flexibler einsetzbar. Da in diesem Fall das Betriebssystem eineFunktion in unserem Programm »zurückruft«, spricht man von einer Call-back-Funktion. Callback-Funktionen sind ein Spezialfall von API-Funktio-nen, die in einigen (allerdings recht speziellen) Situationen zum Einsatzkommen. Bevor eine Callback-Funktion aufgerufen werden kann, mussnoch ein kleines Problem geklärt werden. Wie teilt man der API-Funktionmit, welche VBA-Funktion es aufrufen soll? Übergibt man lediglich denNamen der Funktion kommt es zu einer Fehlermeldung, da VBA als Argu-mente einer Funktion immer einen Wert oder den Namen einer Variablenerwartet. Die Lösung ist der AddressOf-Operator in VBA, der genau fürdiesen einen Zweck da ist.

SyntaxDie Syntax des AddressOf-Operators ist simpel, es folgt lediglich der Nameder Prozedur. Dabei muss berücksichtigt werden, dass der Operator nur imZusammenspiel mit API-Funktionen aufgerufen werden kann:

AddressOf ProzedurName

Beispiel (Fenster-

Auflisten.xls):Das folgende Beispiel füllt ein Listenfeld mit den Titeln aller vorhandenenFenster. Dazu wird die EnumWindows-Funktion mit der Adresse einer Call-back-Funktion und dem Listenfeld des Benutzerformulars (als beliebigen)Parameter aufgerufen. Das Projekt besteht aus zwei Modulen: Dem allge-meinen Modul basFensterEnum, das neben den API-Deklarationen auch dieCallback-Funktion enthält, und dem Benutzerformular usrFensterEnum,das die Befehlsschaltfläche und das Listenfeld enthält.

Page 18: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium318

Kapitel 7 API-Funktionen aufrufen

Das Modul basFensterEnum.bas

Private Declare Function EnumWindows Lib "user32" _ (ByVal pCallBack As Long, lParam As Any) As LongPrivate Declare Function GetWindowText Lib "user32" Alias _ "GetWindowTextA" (ByVal hwnd As Long, ByVal strBuffer As _ String, ByVal cch As Long) As Long

Private Declare Function SendMessage Lib "user32" Alias _ "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, lParam As Any) As Long

Private Declare Function PostMessage Lib "user32" Alias _ "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long

Private Const WM_CLOSE = &H10

Function FensterListeFüllen(lstListe As MsForms.ListBox) _ As Long Dim lngRet As Long lstListe.Clear lngRet = EnumWindows(AddressOf EnumWindowProz, lstListe)End Function

Function EnumWindowProz(ByVal hwnd As Long, _ lParam As MsForms.ListBox) As Long Dim strTemp As String * 128 Dim Länge As Long Länge = GetWindowText(hwnd, strTemp, 128) If Länge > 0 Then With lParam .AddItem Left(strTemp, Länge) & ":" & hwnd End With End If EnumWindowProz = 1End Function

Sub FensterSchließen(hwnd As Long) Dim lngRet As Long lngRet = PostMessage(hwnd, WM_CLOSE, 0, 0)End Sub

Das Modul usrFensterEnum.frm

Das Benutzerformular besteht aus den Schaltflächen cmdEnumerieren undcmdKill.

Page 19: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 319

Beispiele Kapitel 7

Option Explicit

Private Sub cmdEnumerieren_Click() FensterListeFüllen lstFenster lblAnzahlFenster.Caption = lstFenster.ListCount & " Fenster"End Sub

Private Sub cmdKill_Click() FensterSchließen Right(lstFenster.Text, _ Len(lstFenster.Text) – InStrRev(lstFenster.Text, ":")) FensterListeFüllen lstFenster lblAnzahlFenster.Caption = lstFenster.ListCount & " Fenster"End Sub

7.7.5 Formatieren einer Diskette

VBA besitzt keinen Befehl zum Formatieren einer Diskette. Auch das File-SystemObject-Objekt muss in diesem Punkt leider (oder besser zum Glück)passen. Das Formatieren eines Wechsellaufwerks muss entweder über denAufruf des Format-Kommandos über die Shell-Funktion in VBA oder überdie undokumentierte API-Funktion SHFormatDrive erledigt werden. Aller-dings gibt es hier eine Besonderheit zu beachten. SHFormatDrive ist als sog.Shell-Funktion nicht offiziell dokumentiert3. Das bedeutet, dass es keineGewähr gibt, dass sie mit neuen Versionen der Shell (wie sie z.B. durch eineneue Version des Internet Explorer einhergehen können) noch auf die glei-che Weise aufgerufen werden. Für VBA-Programmierer, deren Programmeüber einen längeren Zeitraum ohne Möglichkeiten eines Eingriffs funktio-nieren sollen, ist dies ein gewisses Risiko.

Beispiel

(Format.xls):Das folgende Beispiel zeigt über den Aufruf der SHFormatDrive-API-Funk-tion das Formatieren-Dialogfeld an.

' ***********************************************' Beispiel für den Aufruf der SHFormatDrive-Funktion' ***********************************************

Option ExplicitPrivate Declare Function SHFormatDrive Lib "Shell32.dll" _ (ByVal hwnd As Long, ByVal Drive As Integer, _ ByVal fmtID As Integer, ByVal Options As Integer) As Long

3 Wieso ist die dann trotzdem bekannt? Nun, irgend jemand findet immer heraus, wie »verborgene« Funktionen funktionieren und schon landet die »Enthüllung« in den Tipps&Tricks-Rubriken.

Page 20: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium320

Kapitel 7 API-Funktionen aufrufen

' Nicht vergessen: Diskette einlegenSub Formatieren() Dim lngRet As Long lngRet = SHFormatDrive(0, 0, -1, 1) Select Case lngRet Case -1 MsgBox "Es trat ein Fehler auf!" Case -2 MsgBox "Operation wurde abgebrochen" Case -3 MsgBox "Laufwerk kann nicht formatiert werden" Case Else MsgBox "Auftrag ausgeführt!" End SelectEnd Sub

7.7.6 Zeitgeber

Ein Zeitgeber ist ein Programmelement, das in regelmäßigen und vorherfestgelegten Intervallen ein Ereignis auslöst, das zum Aufruf einer Ereignis-prozedur führt. Über Zeitgeber lassen sich Programmteile in regelmäßigenAbständen aufrufen. Diese liegen allerdings in der Regel im Sekundenbe-reich (für größere Zeiträume bietet Windows z.B. mit dem Taskplaner einepassende Einrichtung). Während Visual Basic mit dem Zeitgeber ein einge-bautes Steuerelement zur Verfügung stellt, bietet die MsForms-Steuerele-mentesammlung nichts Vergleichbares. Es gibt nun zwei Alternativen:

Man verwendet ein dafür vorgesehenes ActiveX-Steuerelement (z.B.HiTimer von Mabry Software – http://www.mabry.com).

Man richtet sich über die API-Funktion SetTimer einen Zeitgeber aufBetriebssystemebene ein. Beim Aufruf von SetTimer wird neben derIntervalldauer in Millisekunden über AddressOf die Adresse einer Call-back-Prozedur übergeben.

Hinweis:

Der Aufruf von SetTimer funktioniert bei VBA nicht in Objektmodulen(also in Benutzerformularen und Klassenmodulen), sondern nur in allgemei-nen Modulen, da VBA nicht in der Lage ist, die Adresse einer Prozedur zuermitteln, wenn sich diese in einem Objektmodul befindet.

Beispiel

(Timer.xls):Das folgende Beispiel richtet über die SetTimer-API-Funktion einen Zeitge-ber ein, der nichts anderes macht als bei jedem Aufruf eine Variable hochzu-zählen. Es besteht aus zwei Modulen: Dem allgemeinen Modul basTimerund dem Benutzerformular usrTimer.

Page 21: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 321

Beispiele Kapitel 7

Das Modul basTimer

Option Explicit

Private Declare Function SetTimer Lib "user32" _ (ByVal hwnd As Long, ByVal nIDEvent As Long, _ ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long

Private Declare Function KillTimer Lib "user32" _ (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Private lngZähler As LongPrivate lngTimerID As Long

Sub TimerInit() Dim lngRet As Long lngRet = basTimer.SetTimer(0, 88, 1000, _ AddressOf Test)End Sub

Sub Test() lngZähler = lngZähler + 1 usrTimer.lblZähler.Caption = lngZählerEnd Sub

Sub Terminate() Dim lngRet As Long lngRet = KillTimer(0, lngTimerID)End Sub

Das Benutzerformular usrTimer

Das Benutzerformular besteht aus der Befehlsschaltfläche cmdStart.

Option Explicit

Private Sub cmdStart_Click() basTimer.TimerInitEnd Sub

Private Sub UserForm_Terminate() basTimer.TerminateEnd Sub

Page 22: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium322

Kapitel 7 API-Funktionen aufrufen

7.7.7 Kleine Spielereien

Zum Abschluss ein paar nicht ganz ernst gemeinte API-Spielereien. Wiewäre es denn zur Abwechslung mit ovalen Benutzerformularen oder einerMöglichkeit, alle Symbole auf dem Desktop verschwinden (und anschlie-ßend wieder erscheinen) zu lassen? Auch für diesen Zweck hält die Win-dows-API etwas bereit.

Beispiel

(Spielereien.xls):Das folgende Beispiel verleiht einem Benutzerformular eine ovale Form undmacht auf Wunsch die Symbole des Desktops unsichtbar und wieder sicht-bar. Das Projekt besteht aus zwei Modulen: dem allgemeinen Modul bas-Spielereien.bas und dem Benutzerformular usrSpielereien.

Das Modul basSpielereien.bas

Option Explicit

Private Declare Function FindWindowEx Lib "user32" Alias _ "FindWindowExA" (ByVal hwnd As Long, _ ByVal hWndChild As Long, _ ByVal lpszClassName As String, _ ByVal lpszWindow As String) As Long

Private Declare Function FindWindow Lib "user32" Alias _ "FindWindowA" (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long

Private Declare Function ShowWindow Lib "user32" _ (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long

Private Declare Function CreateEllipticRgn Lib "gdi32" _ (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, _ ByVal Y2 As Long) As Long

Private Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As Long

'Konstanten für ShowWindow()Private Const SW_HIDE = 0Private Const SW_SHOW = 5

' Stellvertretername der Windows-ShellPrivate Const g_cstrShellViewWnd As String = "Progman"

Sub DeskopSichtbar() Dim hwnd As Long hwnd = FindWindowEx(0&, 0&, g_cstrShellViewWnd, vbNullString)

Page 23: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 323

Beispiele Kapitel 7

If hwnd <> 0 Then ShowWindow hwnd, SW_SHOW End IfEnd Sub

Sub cmdDeskopUnsichtbar() Dim hwnd As Long hwnd = FindWindowEx(0&, 0&, g_cstrShellViewWnd, vbNullString) If hwnd <> 0 Then ShowWindow hwnd, SW_HIDE End IfEnd Sub

Sub FensterRund(intBreite As Integer, intHöhe As Integer, _ strTitel As String) Dim lngRet As Long, hwnd As Long hwnd = FindWindow(vbNullString, strTitel) lngRet = SetWindowRgn(hwnd, CreateEllipticRgn(0, 0, _ intBreite, intHöhe), True)End Sub

Das Benutzerformular usrSpielereien

Das Benutzerformular umfasst eine Schaltfläche cmdDesktopSichtbar, eineSchaltfläche cmdDesktopUnsichtbar, eine Schaltfläche cmdEnde und eineSchaltfläche cmdOval.

Option Explicit

Private Sub cmdDesktopSichtbar_Click() basSpielereien.DeskopSichtbarEnd Sub

Private Sub cmdDesktopUnsichtbar_Click() basSpielereien.cmdDeskopUnsichtbarEnd Sub

Private Sub cmdEnde_Click() Unload MeEnd Sub

Private Sub cmdOval_Click() Dim intBreite As Integer, intHöhe As Integer intBreite = 400: intHöhe = 320 FensterRund intBreite, intHöhe, Me.CaptionEnd Sub

Private Sub UserForm_Terminate()

Page 24: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium324

Kapitel 7 API-Funktionen aufrufen

EndEnd Sub' ***********************************************

7.7.8 Wo erfährt man alles über die API-Funktionen?

Im Allgemeinen möchten angehende VBA-Programmierer, die Gefallen anden API-Funktionen gefunden haben, sich diese nicht mühsam zusammen-suchen, sondern wünschen sich die ultimative Referenz, in der alle Funktio-nen möglichst mit Beispielen enthalten sind. Nun, diese Referenz gibt es lei-der nicht. Weder von Microsoft noch irgendwo im Internet. Es gibtimmerhin ein Buch für Visual-Basic-Programmierer, das dieser Referenzbereits sehr nahe kommt: Visual Basic Programmers Guide to the Win32API von Dan Applemann (Verlag ZD Press, ISBN 1-56276-287-7). Dochda es für Visual-Basic-Programmierer gedacht ist, lassen sich nicht alleFunktionen (aus den in Abschnitt 7.4 erläuterten Gründen) nach VBA über-tragen. VBA-Programmierern bleibt daher zunächst nichts anderes übrig alssich eine eigene Bibliothek von API-Beispielen zusammenzustellen. Idealer-weise auf der Basis von Klassen (damit sich die Funktionen etwas komfor-tabler nutzen lassen) und/oder des Codebibliothekars von MOD 2000 (derbereits ein paar simple API-Beispiele enthält).

7.8 Goldene Regeln für den Umgang mit API-Funktionen

Damit Sie beim Aufruf von API-Funktionen vor unnötigem Frust und allge-meine Schutzverletzungen weitestgehend verschont bleiben, sollten Sie fol-gende Regeln beherzigen:

Speichern Sie vor jedem Programmstart das Projekt. Sollte die Office-Anwendung abstürzen, ist zumindest der Programmtext nicht verloren.

Den allermeisten Argumenten geht bei API-Deklarationen ByVal vo-raus. Verwenden Sie daher im Zweifelsfall ByVal falls Sie sich beimZusammenstellen einer Deklaration nicht sicher sind. Damit muss dieFunktion zwar nicht funktionieren, ein Absturz wird dadurch aber imAllgemeinen vermieden. Normalerweise übernimmt man eine Deklara-tion aus dem API-Viewer und muss sich um die Datentypen der Argu-mente nicht kümmern. Sollten Sie sich aber aus irgendeinem Grund beieinem Argument bezüglich des Aufrufs nicht sicher sein, setzen Sie einByVal voraus.

Sollte der Aufruf einer API-Funktion zu einer »Falsche DLL-Aufruf-konvention«- oder »Typen nicht verträglich«-Fehlermeldung führen,müssen Sie die Datentypen in der Deklaration mit den Datentypen, diebeim Aufruf übergeben wurden, vergleichen (die Namen der Argu-mente spielen keine Rolle).

Page 25: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder

Office 2000 Developer Edition Kompendium 325

Goldene Regeln für den Umgang mit API-Funktionen Kapitel 7

Auch Kleinigkeiten können einen API-Aufruf scheitern lassen. Enthältder »wahre« Funktionsname, der dem Alias-Schlüsselwort folgt, etwaein führendes Leerzeichen, beschwert sich VBA mit der Fehlermeldung»DLL-Einsprungspunkt nicht gefunden« (Fehlernummer 453).

Bei den »wahren« Funktionsnamen einer Win32-API kommt es auf dierichtige Groß-/Kleinschreibung an. Viele Funktionen gibt es in zweiAusführungen, der letzte Buchstabe ist entweder »A« (ANSI) oder »W«(Unicode). Verwenden Sie bei VBA 6.0 immer die »A«-Variante.

Zahlen sind bei API-Funktionen meistens vom Typ Long. Insbesonderewenn Sie Beispiele aus Zeitschriften oder Büchern übernehmen, dienoch für 16-Bit-Windows gedacht sind (meistens handelt es sich umalte Access- oder WordBasic-Makros), sollten Sie grundsätzlich alleInteger-Argument gegen Long-Argumente austauschen. Das gilt auchfür zusammengesetzte Datentypen (z.B. RECT).

Übergeben Sie keine uninitialisierten Strings. Wenn Sie eine Stringvari-able übergeben, in die eine API-Funktion etwas eintragen soll, füllen Siedie Variable zuvor, etwa über die Space-Funktion, mit einer ausrei-chenden Anzahl an Leerzeichen (256 sollten in der Regel ausreichendsein). Alternativ können Sie eine Stringvariable fester Länge definieren(z.B. String * 256)

Die Datei Win32api.txt enthält ein paar kleinere Fehler. Sollte eineAPI-Funktion also partout nicht funktionieren, auch wenn der Declare-Befehl direkt aus Win32api.txt übernommen wurde, sollten Sie denDeclare-Befehl überprüfen. Häufige Fehlerquellen sind ein fehlendesByVal vor einem Argument oder ein As Any wo es z.B. As Long oderAs String heißen müsste.

Page 26: API-Funktionen aufrufen · PDF filevon Sonderfällen gibt und einige Funktionen der 16-Bit-API unter Win32 (so wird die API von 32-Bit-Windows, also Windows ab Version 95 oder