Multimediaprogrammierung mit Visual Basic

Natürlich darf bei der Programmierung mit Visual Basic der Spaß nicht zu kurz kommen. Zum Glück hat Visual Basic in diesem Punkt auch etwas zu bieten. Hardcore-Game-Programmierung wird in diesem Tutorial zwar nicht geboten, doch erfahren Sie, wie Sie mit dem MCI-Steuerelement Sounddateien abspielen oder einen CD-Spieler programmieren können. Als kleines "Highlight" lernen Sie eine überaus nützliche Windows-DLL kennen, mit der Sie ein paar Asse aus dem Ärmel zaubern können (Solitaire-Spieler dürften die Anspielung verstanden haben).

Es sei allerdings bereits an dieser Stelle erwähnt, daß für professionelle Multimediaprogrammierung zusätzliche Ingredenzien benötigt werden, die in Visual Basic leider nicht enthalten sind. Dazu gehört z.B. das, inzwischen allerdings veraltete, Video für Windows SDK. Dazu gehört vorallem das DirectX- und Game SDK, auf das am Ende diesem Tutorial ein kurzer Ausblick gegeben wird. Wer wirklich Action-Spiele programmieren will, muß sich mit diesen API-Funktionen intensiver beschäftigen. Die schlechte Nachricht: Ein Aufruf dieser Funktionen aus einem Visual Basic-Programm aufgrund der Tatsache, daß diese Funktionen Datentypen verwenden, die es in Visual Basic nicht gibt, nicht möglich bzw. relativ umständlich oder nur unter Zuhilfenahme von "Helper"-DLLs zu realisieren. Hier empfiehlt es sich, auf eine "API-nahe" Programmiersprache, wie C++ oder Delphi zurückzugreifen. Visual Basic stößt in diesem Punkt zwangsläufig an die eigenen Grenzen.

Sie lernen in diesem Tutorial etwas über:

Am Ende dieser Übersicht können Sie mit dem MCI-Steuerelement ihre Programm um Sound- und Videoelemente ergänzen.

Hinweis

Alle Angaben in diesem "Tutorial" beziehen sich noch auf die Visual Basic-Version 4, da dieses Kapitel ursprünglich ein Teil des Visual Basic 4.0-Kompendiums war und seit dem nicht mehr grundlegend überarbeitet wurde. Bei der aktuellen Version 6.0 hat sich im Punkto "Multimedia-Programmierung" aber nichts Grundsätzliches geändert, so daß Sie die hier vorgestellten Beispiele (im allgemeinen) problemlos mit Visual Basic 6.0 austesten können.

Was heißt Multimediaprogrammierung

Multimedia war noch vor nicht allzu langer Zeit ein Zauberwort, das die Titelseiten der PC- und Spielemagazine füllte, eine Menge schlauer und weniger schlauer Definitionen besaß und letztendlich alles und nichts bedeutete. Inzwischen wurde Multimedia als Schlagwort natürlich vom Internet und dem Web verdrängt. Das ist gut so, denn Multimedia ist letztendlich nichts anderes als die Anreicherung eines Programms mit Sound-, Bild- und Videoelementen. Mit anderen Worten, Multimedia ist kein Alleinstellungsmerkmal für Software, "das" Multimediaprogramm gibt es nicht. Dennoch gibt es so etwas wie Multimediaprogrammierung. Diese findet immer dann statt, wenn man auf die Multimediakomponenten des Betriebssystems, die in Gestalt einer Reihe von DLLs und damit API-Funktionen vorliegen, zugegriffen wird.

Multimedia ist bereits seit Windows 3.1 "fester" Bestandteil des Betriebssystems. Bei Windows 95/98 wurde die Multimediaunterstützung durch die Umstellung auf 32 Bit, die bessere Integration in das Betriebssystem und vorallem durch leistungsfähigere Treiber für die Video- und Soundkomprimierung deutlich verbessert. Wer Programme mit Multimediakomponenten entwickeln möchte, sollte daher auf Windows 95/98 vertrauen Seit Version 4 ist aber auch Windows NT eine Alternative, das ebenfalls die DirectX-API unterstützt.

Multimediaunterstützung durch Visual Basic

Die Multimediaunterstützung in Visual Basic (auch in der Version 6.0) verdient auch bei wohlwollender Betrachtung allerhöchstens die Note Befriedigend. Zwar ist über das MCI-Steuerelement (mehr dazu gleich) der Profi- und Enterprise-Edition eine einfache Ansteuerung aller Multimediageräte, für die ein MCI-Treiber existiert, möglich, doch wer an simplen Spezialeffekten oder die Einbeziehung von Hypertext (Text mit Querverbindungen) und mit Hotspots versehenen Bitmaps interessiert ist, die Grundelemente eines Multimediatitels, muß wieder einmal auf die Trickkiste der Windows-API, zusätzliche (und in der Regel nicht gerade billige) Zuatzsteuerelemente zurückgreifen oder sich besser gleich ein anderes Entwicklungswerkzeug suchen.

Die MCI-Schnittstelle

Im Mittelpunkt der Multimediaprogrammierung unter Windows steht die MCI-Schnittstelle. MCI steht für und ist ein industrieweit anerkannter Standard für den Zugriff auf Multimediageräte. Die MCI-Schnittstelle ist eine Software-Schnittstelle, die den Zugriff auf alle angeschlossenen Multimediageräte über einfache Basic ähnliche Befehle erlaubt. Sounddateien (die in diesem Zusammenhang als Gerät bezeichnet werden), Videodateien, MIDI-Geräte und Bildplattenspieler lassen sich gleichermaßen über die MCI-Schnittstelle ansteuern. Sollte also morgen der neue Super-Videodisk-Player mit wiederbeschreibbaren CDs für unter 500 Mark einer bekannten japanischen Firma auf den Markt kommen, so stehen die Chancen nicht schlecht, daß Sie ihn sofort über die MCI-Schnittstelle programmieren können. Das Schöne an MCI ist, daß es von allen wichtigen Herstellern unterstützt wird.

Die MCI-Schnittstelle kann auf zwei verschiedene Weisen programmiert werden. Über den direkten Aufruf der Windows-API-Funktionen oder über einfache Befehle, die mit Basic-Anweisungen große Ähnlichkeit besitzen. Im letzteren Fall sorgt die sogenannte MCI-Commandstring-Schnittstelle dafür, daß die MCI-Befehle in die entsprechenden Windows-API-Funktionsaufrufe umgesetzt werden. Die MCI-Commandstring-Schnittstelle hat allerdings nichts mit Visual Basic zu tun, denn die MCI-Befehle lassen sich von jeder beliebigen Sprache aus aufrufen. So läßt sich das Abspielen einer Audio-CD zum Beispiel über die beiden folgenden MCI-Commandstrings in Gang setzen:

open cdaudio alias cd

play cd

Bei open handelt es sich nicht um die gleichnamige Visual-Basic-Anweisung, sondern um einen MCI-Befehl. Wer Multimedia-Programmierung mit Visual Basic realisieren will, muß also nur die Syntax dieser Kommandosprache lernen, um seinen Programmen dadurch den Weg in die bunte Welt des Multimedia zu ebnen. Genauso gut können Sie die MCI-Befehle von einem C- oder Delphi-Programm oder von einem VBA-Programm in Excel aus zur Ausführung bringen. Werfen wir zunächst einen Blick auf die grundsätzlichen Konzepte der Multimedia-Steuerung unter Windows, das heißt auf die Programmierung der MCI-Commandstring-Schnittstelle.

Die Grundlagen der MCI-Programmierung

Das MCI stellt die zentrale Anlaufstelle für alle Multimedia-Aktivitäten unter Windows dar und wird in Form der DLL MMSYSTEM.DLL bei der Installation von Windows auf die Festplatte kopiert. Der Zugriff auf die verschiedenen Multimediageräte wird allerdings nicht direkt durch das MCI abgewickelt, sondern vom MCI an verschiedene Gerätetreiber delegiert, die von den Hardware-Anbietern zusammen mit ihrer Multimediahardware ausgeliefert werden. Das ist das gleiche Konzept, das Windows auch beim Zugriff auf die Grafikkarte verfolgt, um mit möglichst vielen verschiedenen Grafikkarten zusammenarbeiten zu können, ohne auf die unterschiedliche Hardware dieser Karten direkt eingehen zu müssen.

Die MCISendString-Funktion

Der Zugriff auf die MCI-Commandstring-Schnittstelle erfolgt von einem Programm über Funktionen der DLL MMSYSTEM.DLL. Diese Funktion veranlassen die MCI-Schnittstelle zu einem Zugriff auf die verschiedenen Multimediagerätetreiber um Aktionen, wie das Abspielen einer Wav-Datei oder das Abspielen eines CD-Tracks in Gang zu setzen. Die MCI-Schnittstelle ist dabei für die Zusammenarbeit mit einer ganzen Anzahl von Geräten ausgelegt, deren Namen in Tabelle 1 aufgeführt sind. Die wichtigste Funktion der Multimedia-DLL lautet . Ihre Aufgabe ist es, einen MCI-Befehl an ein Multimediagerät zu schicken.

Syntax

Declare Function MCISendString LIB "MMSYSTEM.DLL" (ByVal lpstrCommand As String, ByVal ReturnString AS Any, ByVal uReturnLength As Integer, ByVal hwndCallBack As Integer) AS Long

Erläuterungen zu den Parametern:

Parameter

Bedeutung

lpstrCommand

Zeichenkette, die das zu sendende Kommando enthält.

ReturnString

Zeichenkette, in die ein Rückgabetext übertragen wird. Wird hier ein Nullwert übergeben, gibt die Funktion keinen Wert zurück.

uReturnLenght

Länge der Zeichenkette für den Rückgabetext.

hwndCallBack

Bezugsnummer des Fensters, das eine sogenannte Notify-Nachricht erhalten soll. Kann unter Visual Basic ohne ein Zusatzsteuerelement, das Callback-Funktionen ermöglicht, nicht eingesetzt werden. Anstelle einer Bezugsnummer wird für diesen Fall eine Null übergeben.

Rückgabewert

Gibt ab, ob das Kommando fehlerfrei ausgeführt wurde (Rückgabewert=0). Ansonsten wird ein Fehlercode übergeben.

Beispiel

FehlerCode = MCISendString ("play videodisc to 1000", 0, 0, 0)

Diese Anweisung sendet einen MCI-Befehl an einen angeschlossenen Videodisk-Spieler.

Die MCIGetErrorString-Funktion

Diese Funktion macht nichts anderes als den Rückgabewert der MCISendString-Funktion in den dazugehörigen Fehlertext umzuwandeln.

Syntax

Declare Function MCIGetErrorString LIB "MMSYSTEM.DLL" (ByVal ErrorCode AS Single, ByVal StrBuffer AS String, ByVal Länge AS Integer) AS Long

Erläuterungen zu den Parametern:

Parameter

Bedeutung

ErrorCode

Fehlercode, der durch den letzten MCI-Befehl verursacht wurde.

StrBuffer

Name einer Stringvariablen, die den Fehlertext aufnehmen soll.

Länge

Maximale Länge des Fehlertextes.

Rückgabewert

Gibt lediglich an, ob die Funktion erfolgreich ausgeführt werden konnte, das heißt ob zur angegebenen Fehlernummer ein Fehlertext existierte.

 

Name

Beschreibung

AVIVideo

Softwarebasiertes Video von der Festplatte oder CD-ROM

CDAudio

CD-Spieler

DAT

digitaler Audio-Recorder

DigitalVideo

Digitales Video in einem Bildschirmfenster (zum Beispiel mit Intel's DVI-Boards)

MMMovie

Multimedia-Movie-Player

Overlay

Overlay-Board (Frame-Grabber), analoges Video in einem Bildschirmfenster

Scanner

Scanner

Sequencer

MIDI-Sequencer

Vcr

Videorecorder

Videodisc

Bildplattenspieler

WaveAudio

Auido-Karte zum Aufnehmen und Abspielen digitaler Audio-Sequenzen oder Treiber für den PC-Lautsprecher

Tabelle 1: Die Namen der über die MCI-Schnittstelle ansteuerbaren Geräte

Wie die Tabelle deutlich macht, kümmert sich die MCI-Schnittstelle um alle im Zusammenhang mit Multimedia erwähnenswerten Geräten. Die in der Tabelle aufgeführten Gerätenamen sind Teil der MCI-Commandstring-Syntax, jenem Wortschatz, über den die verschiedenen Geräte mit Hilfe der API-Funktion MCISendString angesprochen werden. Jeder MCI-Commandstring besitzt den allgemeinen Aufbau

Kommando Gerätename Argumente

In jedem Kommando muß dabei der Name eines Geräts auftauchen, damit die MCI-Schnittstelle das betroffene Gerät ansteuern kann. Wie einfach die MCI-Befehle angewendet werden, machen die folgenden beiden Befehle deutlich, die das Abspielen einer Audio-CD starten:

MCISendString("open cdaudio alias cd", 0, 0, 0)

MCISendString("play cd", 0, 0 ,0)

Wurde der Audio-CD-Treiber über die Windows-Systemsteuerung installiert, ertönen aus dem an das CD-Laufwerk angeschlossenen Lautsprecher oder Kopfhörer nun die auf der CD gespeicherten Klänge. Ähnlich einfach gestaltet sich das Abspielen einer Wav-Datei:

MCISendString("open \window\intercom.wav type waveaudio alias startrek", 0, 0, 0)

MCISendString("play startrek", 0, 0 ,0)

Ist ein Gerät einer bestimmten Kategorie in einem System mehrmals vertreten, muß an den Namen eine fortlaufende Nummer angehängt werden. Sind an den PC beispielsweise mehrere CD-Spieler angeschlossen, trägt der erste den Namen cdaudio0, der zweite cdaudio1, der dritte cdaudio2 usw. Eine Liste der wichtigsten MCI-Befehle für den Zugriff auf Audio-CDs und Wav-Dateien finden Sie in den weiter unten folgenden Befehlsübersichten sowie in der bereits erwähnten Multimedia Programmer's Reference.

Ein Wort zu Wav-Dateien

Wav-Dateien stellen das Standardformat für Sounddateien unter Windows dar. Bei einer Wav-Datei handelt es sich um die digitalisierte Form eines analogen Audiosignals, das über eine Soundkarte in eine Folge von Bits umgewandelt wurde. Dazu miß ein sogenannter Analog-Digital-Wandler in bestimmten Zeitabständen (in Regel 11000 bis 44000 mal pro Sekunde) das analoge Signal, das von einem CD-Spieler oder einem Mikrofon stammen kann. Die Klangqualität hängt dabei von der Genauigkeit bei der Aufzeichnung ab. Je höher die sogenannte Samplingrate ist, das heißt je öfter das Analogsignal abgetastet wurde, desto besser sollte auch die Qualität sein. Die pro Zeiteinheit ermittelten Werte können in einem Byte oder in zwei Bytes abgelegt werden. Davon wird allerdings auch der Platzbedarf einer Wav-Datei beeinflußt. Eine Wav-Datei, die bei einer Auflösung von 16 Bit und eine Samplingrate von 44.1 kHz mit zwei Aufnahmekanälen, das heißt in Stereo aufgenommen wurde, bringt es immerhin auf knapp zehn Mbyte.

Compound Devices und Simple Devices

Bei den verschiedenen ansteuerbaren Geräten muß man zwischen sogenannten simple devices und compound devices unterscheiden. Zu deutsch bedeutet das so viel wie einfache Geräte und zusammengesetzte Geräte. Simple Devices sind alle Geräte, die nur zu einem bestimmten Zeitpunkt nur auf einen Datenträger zugreifen können, der in der Regel jedoch wechselbar ist. Dazu zählen CD-Spieler, Videorecorder und Bildplattenspieler, deren Datenträger als Hardware vorliegen (Audio-CD, Videokassette, Bildplatte etc.). Compound Devices können hingegen mehrere Datenträger gleichzeitig verwalten, die in Form von Dateien auf einem Massenspeicher mit wahlfreiem Zugriff (engl. "random access") vorliegen. Nehmen Sie als Beispiel das Gerät WaveAudio, dessen Datenträger die bekannten Wav-Dateien bilden. In ihnen werden akustische Sequenzen digital aufgezeichnet, im besten Fall sogar in CD-Qualität. Einige dieser Dateien werden bei der Installation von Windows in das Windows-Unterverzeichnis kopiert. Mehrere hundert weitere Exemplare mit den unterschiedlichsten Soundeffekten, die meistens aus bekannten US-TV-Serien oder Kinofilmen stammen, sind inzwischen in Form von Free- oder Shareware-Programmen erhältlich.

Ob Sie es mit einem Compound Device oder einem Simple Device zu tun haben, ist eigentlich nur beim Öffnen von Multimediageräten wichtig. Denn jedes Gerät muß genau wie eine Datei zunächst mit dem MCI-Befehl open geöffnet werden, bevor Sie mit weiteren Befehlen darauf zugreifen können. Dabei gilt folgender Unterschied zwischen Simple und Compound Devices: Wenn Sie in ihrem Programm beispielsweise mit mehreren akustischen Meldungen arbeiten möchten, die über das Gerät WaveAudio (Soundkarte) abgespielt werden sollen, dann können Sie alle zugehörigen Wav-Dateien am Anfang ihres Programms öffnen und im Laufe der Programmausführung beliebig oft ablaufen lassen. Schließlich handelt es sich bei WaveAudio um ein Compound Device, das gleichzeitig mehrere Datenträger (sprich: Dateien) verwalten kann.

Anders dagegen CDAudio, der CD-Spieler. Dieses Gerät muß nach dem Aufruf des open-Befehls erst wieder mit einem close-Befehl geschlossen werden, bevor ein neuer open-Aufruf erfolgen kann. Dieser Unterschied zwischen Simple Devices und Compound Devices zeigt sich bereits an der Syntax des open-Befehls. Bei einem Simple Device lautet die Syntax:

open GeräteName [Shareable] [Alias aliasname]

Der Parameter GeräteName vertritt einen der Gerätenamen, die in Tabelle 1 aufgeführt sind. Die beiden Parameter in eckigen Klammern sind optional. Möchten Sie diese Parameter angeben, müssen Sie die eckigen Klammern weglassen, doch dazu gleich mehr. Die Groß-/Kleinschreibung ist bei diesem Befehl übrigens unerheblich, genau wie bei allen anderen MCI-Commandstrings auch.

Vergleichen Sie nun die Syntax des open-Befehls, wenn sie auf Compound Devices angewandt wird. Sie lautet:

open ElementName [Shareable] Type GeräteName [Alias aliasname]

Mit ElementName ist hier der Name der Datei gemeint, die durch das Gerät abgespielt werden soll, während GeräteName wieder ein Gerätenamen gemäß Tabelle 1 darstellen muß. Den optionalen Parameter Shareable sollten Sie nutzen, wenn der Zugriff auf das jeweilige Gerät gleichzeitig auch anderen Windows-Applikationen gestattet sein soll, wenn Sie also keinen exklusiven Zugriff wünschen. Darüber müssen Sie sich zunächst jedoch keine Gedanken machen.

Der Aliasname eines Gerätes

Auch der Alias-Parameter spielt eine wichtige Rolle. Mit seiner Hilfe können Sie dem geöffneten Gerät einen zweiten Namen, den sogenannten , verleihen, über den es bei allen folgenden Zugriffen angesprochen werden kann. Das empfiehlt sich vor allem bei Compound-Devices, weil hier anstelle des Gerätenamens ein Dateiname angegegeben werden muß und der mitunter recht lang ist, vor allem, wenn er eine Pfadbezeichnung beinhaltet. In der folgenden Sequenz von MCI-Commandstring-Befehlen wird davon Gebrauch gemacht, um das Knarren einer Tür durch Abspielen der Wav-Datei DOOR.WAV erklingen zu lassen:

open door.wav type waveaudio alias door

play door

close door

In diesem Beispiel wird die Wav-Datei zunächst mit einem open-Befehl geöffnet und ihr dabei der Aliasname door verliehen. Über ihn wird es anschließend in Verbindung mit dem play-Befehl angesprochen, denn das MCI hat sich den Namen der Datei gemerkt, der mit diesem Alias verbunden ist. Natürlich hätte man auch den Befehl

play \windows\system\door.wav

ausführen können, aber das wäre bei häufigeren Zugriffen innerhalb eines Programms unnötige Tipparbeit.

Der Umgang mit Wav-Dateien

Nach dem Abspielen wird die Wav-Datei wieder geschlossen, denn MCI-Geräte müssen genau wie Dateien geschlossen werden, wenn man sie nicht mehr benötigt. Nur muß das nicht sofort geschehen. Wenn Sie das Knarren der Tür innerhalb Ihres Programms mehrmals erklingen lassen wollen, reicht es vollkommen aus, diese Wav-Datei am Anfang des Programms mit dem open-Befehl zu öffnen und es am Ende mit einem close-Befehl wieder zu schließen. Dazwischen können Sie es so oft abspielen, wie Sie wollen. Allerdings wird bereits der zweite play door-Befehl nicht mehr das gewünschte Resultat zeitigen, denn in Bezug auf das Abspielen verhält sich das WaveAudio-Gerät wie ein normaler Kassettenrecorder. Nach der Wiedergabe einer Wav-Datei muß es deshalb wieder "zurückgespult" werden.

Für das Zurückspulen einer Wav-Datei gibt es zwei Möglichkeiten: Zum einen können Sie sich des seek-Befehls bedienen, der die Wav-Datei um eine bestimmte Anzahl an Einheiten, zum Beispiel Millisekunden, vor- oder zurückspult. Diese Anweisung gibt es in drei Variationen:

Befehl

Aufgabe

seek Name to start

Spult die Wav-Datei bis zum Start zurück.

seek Name to end

Spult die Wav-Datei bis zum Ende zurück

seek Name to position

Spult die Wav-Datei bis zur angegebenen Position.

Bei der dritten Variante muß für den Parameter position die gewünschte Position eingesetzt werden.

Beispiel

seek door to 55

Wie dieses Beispiel zeigt, werden also auch Zahlen im Rahmen der MCI-Commandstrings erfaßt, wobei hier automatisch die Einheit Millisekunden zugrunde gelegt wurde. Den seek-Befehl kann man sich im vorliegenden Fall allerdings sparen, denn der play-Befehl kennt die optionalen Parameter from position und to position, mit deren Hilfe sich die Start- und Endposition festlegen läßt.

Beispiel

play door from 0

spielt die Wav-Datei also wieder von vorne ab. Fast alle MCI-Commandstring-Befehle kennen derartige optionale Parameter, wie auch die weiter unten folgenden Befehlsübersichten zeigen. Hier sind die wichtigsten MCI-Befehle zur Steuerung von CD-Spielern und WaveAudio-Geräten aufgeführt.

Die Syntax der MCI-Commandstring-Befehle

Wenn Sie die beiden Befehlssätze in den etwas später folgenden Übersichten vergleichen, werden Sie zahlreiche Gemeinsamkeiten feststellen. Das ist kein Zufall, denn tatsächlich bemüht sich die MCI-Schnittstelle um eine weitestgehende Standardisierung der einzelnen Befehle. Das zeigt sich bereits bei der allgemeinen Syntax: Ein MCI-Commandstring beginnt immer mit einem Verb (open, play etc.) auf das als Zweites der Geräte- bzw. Aliasname folgt. Erst dann schließen sich je nach Befehl (Verb) die verschiedenen Parameter an.

Doch die Standardisierung geht noch weiter und verlangt von den verschiedenen Multimediageräten, daß sie einen bestimmten Grundwortschatz an Befehlen in jedem Fall unterstützen. Dazu zählen Befehle wie open, close und status. Andere wie play, load, pause oder seek sind nicht bei allen, aber bei den meisten Geräten vertreten und werden deshalb als »basic commandsge des Videofensters definieren und bei anderen Geräten wegen der fehlenden Videounterstützung nicht benötigt werden.

Die verschiedenen Zeiteinheiten

Viele MCI-Commandstring-Befehle erwarten Zeit- oder Positionsangaben und bieten verschiedene Bezugssysteme an, in denen diese Angaben formuliert werden können. Einstellen läßt sich das Bezugssystem jeweils mit Hilfe des Befehls

set time format ZeitFormat

CD-Spieler unterstützen drei Zeitformate: Millisekunden, MSF und TMSF, wobei die beiden Abkürzungen für Minutes Seconds Frames und Tracks Minutes Seconds Frames stehen und festlegen, auf welche Weise Positionsangaben für das Abspielen einer bestimmten Stelle auf einer CD festgelegt werden. Am besten läßt sich in der Regel mit der Einheit TMSF arbeiten, die über den Befehl

set time format tmsf

eingestellt wird. Bei diesem Format wird als Zeitangabe die Nummer des Tracks, sowie die gewünschte Minute, Sekunde und der Frame angegeben, wobei diese Parameter durch einen Doppelpunkt getrennt werden müssen. Die Angabe

2:02:03:45

bezeichnet damit den zweiten Track einer CD, auf dem bereits 2 Minuten, 3 Sekunden und 45 Frames gespielt wurden. Der Begriff steht dabei für die unterste Ebene, die die eigentlichen Klanginformationen verkörpert. Da von einer CD pro Sekunde 75 Frames geladen werden, beträgt der Maximalwert für den Frame-Parameter 74 (es wird ab 0 gezählt).

Bei einer Zeitangabe im TMSF-Format müssen jedoch nicht alle Parameter genannt werden. Vielmehr genügt es, von links nach rechts Track, Minute und Sekunde aufzuführen, bis einer dieser Parameter 0 ist. Für alle weiteren Parameter setzt die MCI-Schnittstelle dann automatisch 0 ein.

Neben dem TMSF-Format ist auch das MSF-Format gebräuchlich, das sich nicht auf Tracks, sondern auf die reine Spieldauer der CD bezieht. Es wird über den Befehl

set time format msf

eingestellt. Hier wird nur die Anzahl der Minuten, Sekunden und der Frames relativ zum Start der CD erwartet, ganz unabhängig davon, welcher Track dadurch berührt wird. Die verschiedenen Komponenten müssen dabei wiederum durch einen Doppelpunkt getrennt werden und können entfallen, sobald sie und die darauffolgenden Parameter 0 sind.

Auf der gleichen Grundlage wie MSF beruht das Millisekunden-Format, das über den Befehl

set time format milliseconds

eingestellt wird, und bei dem die gewünschte Position als Entfernung vom Start der CD in Millisekunden gemessen wird. Als einziges der drei Formate steht milliseconds auch bei WaveAudio-Geräten zur Verfügung und wird dort als Standardformat verwandt. Mit anderen Worten, um eine Wav-Datei vor- oder zurückspulen zu können, muß die Distanz stets in Millisekunden angegeben werden. Sie können das aktuelle Zeitformat übrigens auch über den Befehl

status time format

abfragen. Über den Befehl

status cdaudio position

erhalten Sie dagegen stets die aktuelle Position innerhalb einer Audio-CD oder eine Wav-Datei unter Berücksichtigung des aktuellen Formats.

Übung 1

Das Beispielprogramm der folgenden Übung demonstriert den Einsatz der MCI-Befehle in der Praxis. Es handelt sich um ein Programm, das einzig und allein dazu da ist, die einzelnen MCI-Befehle ausprobieren zu können.

Wie funktioniert’s?

Das Beispielprogramm wurde so konzipiert, daß Sie es leicht in Ihre eigenen Multimediaprogramme integrieren können. Im Mittelpunkt des Programms steht die Funktion MCISend, die über die Ereignisprozedur Click der Ausführen-Schaltfläche aufgerufen wird. Weil es sich hier um die Defaultschaltfläche (Default=True) handelt, erfolgt dieser Aufruf auch nach Betätigen der [Eingabe]-Taste. Die MCISend-Funktion nimmt von ihrem Aufrufer den zu sendenden MCI-Commandstring sowie einen weiteren String entgegen. Die Funktion btAusführen_Click isoliert den Befehlsstring aus dem Eingabefeld, indem es die Zeile innerhalb des Textfeldes heraustrennt, in der sich der Textcursor befindet.

Während im ersten String der eigentliche MCI-Befehl übergeben wird, erwartet die MCISend-Funktion im zweiten String keinerlei Informationen, sondern legt darin den Rückgabestring der MCI-Schnittstelle ab. Auf diese Weise wird dem Aufrufer der MCISend-Funktion eine "Rückmeldung" in Form eines Textes zugänglich gemacht. Darüberhinaus liefert die MCISend-Funktion als Funktionsparameter einen Fehlercode der MCI-Schnittstelle zurück. Diese Meldung wird in dem Beispielprogramm der Übung 1 im Bezeichnungsfeld Status sichtbar gemacht.

Die MCISend-Funktion basiert auf zwei Funktionen des Windows-API, die durch die MCI-Schnittstelle, genauer gesagt durch die Datei MMSYSTEM.DLL, zur Verfügung gestellt werden. Es handelt sich um die bereits vorgestellten Funktionen MCISendString, mit deren Hilfe ein MCI-Commandstring an die MCI-Schnittstelle gesandt wird, und um die Funktion MCIGetErrorString, die den numerischen Fehlercode der MCISendString-Funktion in einen Fehlerstring umwandelt.

MCI-Befehle in der Praxis

Das Beispielprogramm aus Übung 1 arbeitet nach einem einfachen Schema: Sie geben zunächst den bzw. die auszuführenden MCI-Befehlsstrings in das Textfeld mit dem Titel MCI-Kommandos ein. Das Betätigen der [Eingabe]-Taste kommt dabei dem Anklicken der Ausführen-Schaltfläche gleich. Dadurch wird der Inhalt der aktuellen Eingabezeile mit Hilfe der Windows-Funktion MCISendString an die MCI-Schnittstelle gesandt und ausgeführt. Voraussetzung ist natürlich, daß kein Syntaxfehler vorliegt. Beachten Sie aber, daß nach dem Betätigen der [Eingabe]-Taste immer nur eine Kommandozeile ausgeführt wird.

Die Rückmeldung der MCISendString-Funktion wird im Bezeichnungsfeld mit dem Namen Rückgabestring angezeigt. Im Statusfeld erscheinen entweder die Fehlermeldungen der MCI-Schnittstelle oder der Text »ok« wenn ein Befehl ordnungsgemäß ausgeführt werden konnte. Da es sich um ein Listenfeld handelt, werden alle Meldungen, die beim Zugriff auf die MCI-Schnittstelle entstehen, gesammelt. Das Anklicken mit der rechten Maustaste löscht das Listenfeld. Strings, die die MCI-Schnittstelle zurückliefert, wie zum Beispiel bei der Ausführung eines status-Befehls, mit dem sich etwa die Länge einer CD oder die Anzahl der Titel ermitteln läßt, werden in dem Bezeichnungsfeld Rückgabestring dargestellt.

Bereits eingegebene und ausgeführte MCI-Befehle lassen sich jederzeit wiederholen, indem Sie den Textcursor in die jeweilige Zeile bewegen und erneut die [Eingabe]-Taste betätigen. Das Einfügen einer neuen Zeile geschieht über die Tastenkombination [Strg][Eingabe], da die [Eingabe]-Taste bereits eine Funktion besitzt. Über das Löschen-Menü kann der komplette Inhalt des Eingabefeldes gelöscht werden.

Über die beiden Kommandos des MCI-DEMO-Menüs lassen sich Wav-Dateien und Audio-CDs abspielen. Das Menü verfügt über die Untermenüs WAV-DATEI SPIELEN und AUDIO CD SPIELEN. Dabei handelt es sich sozusagen um Makros, die nach der Auswahl eines der beiden Kommandos im Textfeld ausgegeben werden.

Abspielen einer Wav-Datei

Nach Ausführung des WAV-DATEI SPIELEN-Kommandos erscheint folgende Befehlssequenz im Eingabefeld:

open filename.wav type waveaudio alias song1

play song1 from 0

status song1 length

close song1

Diese vier Befehle ermöglichen das Abspielen einer beliebigen Wav-Datei sowie die Abfrage ihrer Länge in Millisekunden. Sie werden zur Ausführung gebracht, indem Sie den Textcursor auf den open-Befehl setzen und die [Eingabe]-Taste oder die Ausführen-Schaltfläche betätigen. Das Programm setzt die Einfügemarke anschließend automatisch auf den Anfang der nächsten Zeile, so daß Sie nur immer wieder die [Eingabe]-Taste betätigen müssen, um die ganze Befehlssequenz "abzuspulen". Vergessen Sie jedoch nicht, zuvor den Ausdruck filename im open-Befehl durch den Namen einer Wav-Datei zu ersetzen, denn bei filename handelt es sich lediglich um einen Platzhalter für den Dateinamen.

Wenn Sie das Kommando WAV-DATEI ABSPIELEN mehrmals hintereinander aufrufen, werden Sie feststellen, daß durch das Programm immer ein anderer Aliasname gewählt wird. Auf song1 folgen song2, song3 usw. Das bietet Ihnen die Möglichkeit, gleichzeitig mehrere Wav-Dateien zu öffnen und nacheinander abzuspielen, ohne nach dem Abspielen gleich einen close-Befehl ausführen zu müssen.

Abspielen einer Audio-CD

Eine ganz andere Folge von MCI-Befehlen fügt das Kommando AUDIO CD SPIELEN in das Eingabefeld ein:

open cdaudio alias cd

set cd time format tmsf

play cd from 1 to 10

status cd mode

stop cd

status cd mode

close cd

Diese Befehle öffnen zunächst das CD-Laufwerk unter dem Aliasnamen CD, stellen dabei das Zeitformat TMSF ein und beginnen dann mit dem Abspielen der CD, genauer gesagt der Tracks 1 bis 10. Danach wird der Status des CD-Laufwerks abgefragt.

Wenn Sie diese Befehle einmal in der Praxis ausführen lassen, werden Sie sehr schnell feststellen, daß die Programmausführung nach dem Absetzen eines MCI-Commandstrings fortgeführt wird. Obwohl das Abspielen der CD mit dem play-Befehl eine ganze Weile in Anspruch nimmt (schließlich sollen die Stücke 1 bis 10 gespielt werden), erscheint die Textmarke gleich darauf wieder in dem Eingabefeld, und der Status kann mit dem status-Befehl abgefragt werden. Das macht deutlich, daß MCI-Befehle wie play parallel zum normalen Programmablauf ausgeführt werden, was aber nicht immer wünschenswert ist. Folgt auf einen play-Befehl nämlich ein close-Befehl, wird dieser womöglich ausgeführt, noch bevor das Abspielen beendet ist. Jedem MCI-Commandstring kann deshalb der Parameter wait nachgestellt werden, der dafür sorgt, daß die Programmausführung erst nach dem Ende der jeweiligen Aktion fortgeführt wird.

Sie können das einfach ausprobieren, indem Sie das Kommando WAIT-OPTION aus dem MCI-DEMO-Menü aufrufen, bevor Sie eines der beiden anderen Kommandos aus diesem Menü anwählen. In diesem Fall versieht das Programm die play-Befehle in den erzeugten Befehlssequenzen mit einem wait-Parameter, den Sie aber natürlich auch von Hand an den jeweiligen Befehl anhängen können. Infolgedessen vergeht dann eine ganze Weile, bis nach der Ausführung des Befehls

play cd from 1 to 10

wieder Eingaben möglich sind, denn die Programmausführung wird faktisch angehalten. Dauert Ihnen das zu lange, können Sie die Operation allerdings jederzeit durch die [Esc]-Taste abbrechen. Das Abspielen einer CD oder eine Wav-Datei im Hintergrund scheint über den Aufruf der MCISendString-Funktion nicht so richtig zu funktionieren. Wir werden auf diesen, für das Abspielen von Wav-Dateien sehr wichtigen Umstand, bei der Besprechung des MCI-Steuerelements noch einmal zurückkommen. In diesem Zusammenhang wird eine einfache Lösung präsentiert, die ein Programm davon unterrichtet, daß ein MCI-Befehl beendet wurde.

Das Beispielprogramm aus Übung 1 soll Ihnen in erster Linie als Anregung für die ersten Gehversuche bei der Multimediaprogrammierung mit Visual Basic dienen. Am einfachsten ist es, zunächst die verschiedenen Kommandostrings aus den Befehlsübersichten auszuprobieren und die entsprechenden MCI-Befehle dann in den eigenen Programmen per MCISend-Funktion an die jeweiligen Geräte abzusetzen.

Die Syntax der MCI-Befehle für das Abspielen von Audio-CDs

Der folgende Abschnitt enthält eine Auflistung wichtiger MCI-Befehle, die beim Abspielen einer Audio-CD eine Rolle spielen.

open cdaudio [shareable] [alias AliasName]

Öffnet den CD-Spieler für die weitere Programmierung. Durch die Angabe von [shareable] können auch andere Windows-Applikationen auf den CD-Spieler zugreifen. Mit dem alias-Parameter kann ein Aliasname für den weiteren Zugriff auf das Gerät festgelegt werden.

play cdaudio|AliasName [from position] [to position]

Setzt das Abspielen der CD in Gang. Ohne Angabe des optionalen Parameters [from position] beginnt das Abspielen mit dem Anfang des ersten Stücks. Durch den Parameter [from position] kann jedoch eine Startposition festgelegt werden, wobei sich das Format von position nach dem gerade eingestellten Zeitformat richtet (siehe set time format-Befehl). Genauso verhält es sich mit der Angabe [to position], die die Endposition angibt, nach deren Erreichen der CD-Spieler gestoppt wird. Fehlt dieser Parameter, wird die Wiedergabe erst nach dem Ende des letzten Stücks beendet.

pause cdaudio|AliasName

Wirkt in der derzeitigen Version des MCI-CD-Treibers wie ein stop-Befehl.

stop cdaudio|AliasName

Stoppt das Abspielen der CD. Durch einen play-Befehl wird das Abspielen an der aktuellen Position fortgesetzt.

close cdaudio|AliasName

Schließt den CD-Spieler wieder. Vor einem erneuten open-Befehl ist anschließend kein Zugriff mehr möglich.

set cdaudio|AliasName audio all off

set cdaudio|AliasName audio all on

Schaltet die Audio-Wiedergabe des CD-Spielers an oder aus, ohne einen Einfluß auf das Abspielen der CD zu nehmen.

set cdaudio|AliasName audio left off

set cdaudio|AliasName audio left on

Schaltet den linken Wiedergabe-Kanal an oder aus.

set cdaudio|AliasName audio right off

set cdaudio|AliasName audio right on

Schaltet den rechten Wiedergabe-Kanal an oder aus.

set cdaudio|AliasName door closed

Schließt den CD-Einschub. Da dies nicht bei allen CD-Spielern möglich ist, sollte man auf die Fehlermeldung "Das verwendete MCI-Gerät unterstützt diesen Befehl nicht".

set cdaudio|AliasName door open

Öffnet den CD-Einschub, falls möglich. Wenn nicht, erhält man die Fehlermeldung "Das verwendete MCI-Gerät unterstützt diesen Befehl nicht".

set cdaudio|AliasName time format milliseconds

Stellt das Zeitformat auf Millisekunden ein.

set cdaudio|AliasName time format msf

Stellt das Zeitformat auf Minute:Sekunde:Frame ein.

set cdaudio|AliasName time format tmsf

Stellt das Zeitformat auf Track:Minute:Sekunde:Frame ein.

info cdaudio|AliasName product

Liefert den Namen des MCI-Gerätetreibers für den CD-Spieler.

status cdaudio|AliasName current track

Liefert die Nummer des aktuellen Tracks.

status cdaudio|AliasName length

Liefert die Gesamtlänge der CD im aktuellen Zeitformat.

status cdaudio|AliasName length track TrackNo

Liefert die Länge des Tracks mit der Nummer TrackNo im aktuellen Zeitformat.

status cdaudio|AliasName media present

Liefert einen True-Wert, wenn sich eine CD im CD-Spieler befindet, ansonsten wird ein False-Wert zurückgegeben.

status cdaudio|AliasName mode

Zeigt den aktuellen Status des CD-Spielers an. Es wird einer der folgenden Strings zurückgeliefert: "not ready" "angehalten" "Wiedergabe" "seeking" oder "beendet".

status cdaudio|AliasName number of tracks

Liefert die Anzahl der Tracks der CD.

status cdaudio|AliasName position

Liefert die aktuelle Position beim Abspielen einer CD im eingestellten Zeitformat.

status cdaudio|AliasName ready

Liefert einen True-Wert, wenn das CD-Laufwerk bereit ist, ansonsten wird ein False-Wert zurückgegeben.

status cdaudio|AliasName

Liefert die Startposition des ersten Tracks im eingestellten Zeitformat.

status cdaudio|AliasName time format

Liefert das aktuelle Zeitformat als String im Format "milliseconds" für Milliseunden, "msf" für Minute:Sekunde:Frames oder "tmsf" für Tracks:Minute:Sekunde:Frames.

Hinweise zu obigen Anweisungen:

[x] = optionaler Parameter

x|y = X oder Y

name = Befehlswort

Name = Platzhalter

Die Syntax der MCI-Befehle für den Zugriff auf WaveAudio-Geräte

Der folgende Abschnitt enthält eine Auflistung wichtiger MCI-Befehle, die beim Zugriff auf Wave-Geräte eine Rolle spielen.

open ElementName type waveaudio [shareable] [alias AliasName] [buffer PufferGröße]

Öffnet das WaveAudio-Gerät für das Aufnehmen oder Abspielen von Wav-Dateien. Soll aufgenommen werden, muß für ElementName »newei festgelegt werden. Wird new als ElementName angegeben, muß ein Aliasname angegeben werden, sonst ist dieser Parameter optional. In jedem Fall optional ist der Parameter buffer, der die Größe des Puffers festlegt, über den das WaveAudio-Gerät im Zusammenhang mit der jeweiligen Wav-Datei verfügen soll. Der Parameter PufferGröße muß dabei in Sekunden angegeben werden. Die Standardeinstellung ist vier Sekunden, dieser Wert kann über die Systemsteuerung von Windows eingestellt werden.

play ElementName|AliasName [from position] [to position]

Startet das Abspielen einer Wav-Datei. Ohne Angabe des optionalen Parameters [from position] beginnt das Abspielen an der aktuellen Position, die durch den letzten play-Befehl oder einen seek-Befehl bestimmt wurde. Mit Hilfe des Parameters [from position] kann jedoch explizit eine Startposition festgelegt werden, wobei sich das Format von position an dem aktuell eingestellten Zeitformat orientieren muß (siehe set time format). Genauso verhält es sich mit dem Parameter [to position], der die Endposition angibt, nach deren Erreichen die Wiedergabe gestoppt wird. Fehlt dieser Parameter, wird die Wav-Datei bis zu ihrem Ende gespielt.

record ElementName|AliasName [from position] [to position] [insert]

Startet die Aufnahme in die Wav-Datei. Ohne Angabe des optionalen Parameters from position beginnt die Aufnahme an der aktuellen Position, die durch den letzten play-Befehl oder einen seek-Befehl bestimmt wurde. Mit Hilfe des Parameters from position kann jedoch explizit eine Startposition festgelegt werden, wobei sich das Format von position nach dem gerade eingestellten Format richtet (siehe set time format). Genauso verhält es sich mit dem Parameter to position, der die Endposition angibt, nach deren Erreichen die Aufnahme automatisch gestoppt wird. Fehlt dieser Parameter, wird die Aufnahme fortgesetzt, bis ein stop- oder pause-Befehl erteilt wird. Durch Angabe des insert-Parameters wird die neue Aufnahme in die bisherige Aufnahme eingefügt und überschreibt diese nicht, wie das sonst der Fall ist.

pause ElementName|AliasName

Hält das Abspielen oder die Aufzeichnung an. Kann durch einen resume-Befehl wieder rückgängig gemacht werden.

resume ElementName|AliasName

Setzt die Abspielung oder das Aufzeichnen einer Wav-Datei fort, nachdem zuvor ein pause-Befehl erteilt wurde.

save ElementName|AliasName Dateiname

Speichert die Wav-Datei unter dem angegebenen Dateinamen.

seek ElementName|AliasName to Position|to end|to start

Mit diesem Befehl läßt sich das WaveAudio-Gerät wie ein Kassettenrecorder bis zu einer angegebenen Position vor- oder zurückspulen. Der nächste play- oder record-Befehl startet dann an dieser Stelle. Soll das Gerät zum Anfang oder zum Ende der aktuellen Wav-Datei geführt werden, genügt die Angabe von to start oder to end. Wird eine bestimmte Position gewünscht, kann diese als numerischer Wert hinter to angegeben werden. Als Bezugssystem dient dabei wie immer das aktuelle Zeitformat.

delete ElementName|AliasName [from position] [to position]

Löscht einen Teil des angegebenen Elements. Ohne Angabe des optionalen Parameters from position beginnt das Löschen an der aktuellen Position. Durch den Parameter from position kann jedoch eine Startposition festgelegt werden, wobei sich das Format von position nach dem gerade eingestellten Format richtet (siehe set time format). Genauso verhält es sich mit dem Parameter to position, der die Endposition für den Löschvorgang angibt. Fehlt dieser Parameter, wird alles von der Startposition bis zum Ende des Stücks gelöscht.

stop ElementName|AliasName

Stoppt das Abspielen oder Aufnehmen einer Wav-Datei.

close waveaudio|ElementName|AliasName

Schließt das Gerät oder das angegebene Element wieder.

capability waveaudio|ElementName|AliasName can record

Liefert einen True-Wert zurück, wenn das Gerät aufnehmen kann, ansonsten wird ein False-Wert zurückgegeben.

capability waveaudio|ElementName|AliasName can save

Liefert einen True-Wert zurück, wenn das Gerät speichern kann, ansonsten wird ein False-Wert zurückgegeben.

info ElementName|AliasName file

Liefert den Dateinamen des angegebenen Elements.

info waveaudio|ElementName|AliasName product

Liefert den Namen des MCI-Gerätetreibers für das WaveAudio-Gerät.

status ElementName|AliasName bitspersample

Liefert die Anzahl der Bits pro Sample (8 oder 16) und damit die Auflösung einer Wav-Datei.

status ElementName|AliasName bytespersec

Liefert die Anzahl der Bytes, die in der Wav-Datei pro Sekunde gespeichert wurden.

status ElementName|AliasName channels

Liefert die Anzahl der Aufnahmekanäle. Der Wert beträgt 1, wenn die Wav-Datei in mono aufgenommen wurde und 2 bei einer stereo-Aufnahme.

status ElementName|AliasName length

Liefert die Länge der Wav-Datei in Bezug auf das gewählte Zeitformat.

status ElementName|AliasName level

Liefert den aktuell gesampelten Wert.

status ElementName|AliasName mode

Zeigt den aktuellen Status des WaveAudio-Geräts an. Es wird einer der folgenden Strings zurückgeliefert: "nicht bereit", "paused", "Wiedergabe", "seeking" oder "beendet".

status ElementName|AliasName position

Liefert die aktuelle Position innerhalb der Wav-Datei in Bezug auf das gewählte Zeitformat.

status ElementName|AliasName ready

Liefert einen True-Wert zurück, wenn das Gerät bereit ist, ansonsten wird ein False-Wert zurückgegeben.

status ElementName|AliasName samplespersec

Liefert die Samplerate der Wav-Datei in Samples pro Sekunde.

status ElementName|AliasName time format

Liefert das aktuelle Zeitformat als String. In Frage kommen die Formate bytes, milliseconds oder samples

set ElementName|AliasName time format bytes

Legt als Zeitformat die Einheit Bytes fest.

set ElementName|AliasName time format milliseconds

Legt als Zeitformat die Einheit Millisekunden fest.

set ElementName|AliasName time format samples

Legt als Zeitformat die Einheit Samples fest.

Übung 2

Das Beispielprogramm der folgenden Übung stellt einen einfachen CD-Spieler dar, der für das Abspielen von Audio-CDs verwendet werden kann. Wenngleich mit Windows 95/98 (insbesondere mit Microsoft Plus! für Windows 98) die Nachfrage nach selbst programmierten CD-Spielern etwas gefallen sein dürfte und das vorliegende Programm in Punkto Bedienerkomfort noch ein wenig verbesserungswürdig ist, faßt es die Grundlagen der Programmierung der MCI-Commandstring-Schnittstelle noch einmal gut zusammen. Und was noch wichtiger ist, es ist aufgrund seiner modularen Struktur leicht zu erweitern. Voraussetzung für die Ausführung ist allerdings, daß der CD-Audio-Treiber in der Windows-Systemsteuerung installiert wurde.

Wie funktioniert´s?

Auch im Mittelpunkt dieses Programms steht die Windows-API-Funktion MCISendString, die MCI-Befehle an die MCI-Commandstring-Schnittstelle schickt. Dank der Funktion MCISend wird die Windows-Funktion so verpackt, daß das Absenden eines Befehls und das Entgegennehmen der Rückmeldung in einem Aufruf erfolgen kann. Die Ansteuerung des CD-Spielers erfolgt über die bereits vorgestellten MCI-Befehle. Der Hauptteil des Programms beschäftigt sich daher auch mit der Realisierung der Benutzerschnittstelle. Das wird vor allem an der Form_Load-Prozedur deutlich, in der alle Daten der eingelegten CD ermittelt und angezeigt werden. Als Zeitformat muß TMSF gesetzt werden, da sich die CD nur so trackweise ansteuern läßt. Zwar wäre es auch möglich, die aktuelle Leseposition um einen Betrag in Millisekunden zu verschieben, doch wird davon kein Gebrauch gemacht. Dafür, daß während des Abspielens die aktuelle Position auch angezeigt wird, ist ein Zeitgeber zuständig. Dieser prüft auch, ob sich eine CD in dem Laufwerk befindet.

Erweiterungsvorschläge

In dem Beispielprogramm aus Übung 2 geht es in erster Linie darum, das allgemeine Prinzip eines CD-Spielers zu erläutern. Es sollte nicht allzu schwierig sein, das Beispielprogramm zu einem perfekten CD-Spieler zu erweitern, der kaum noch Wünsche in Punkto Bedienerkomfort und originellen Features offen läßt. Folgende Extras lassen sich mit wenig Arbeitsaufwand einführen:

Das MCI-Steuerelement

Im letzten Abschnitt wurde gezeigt, wie einfach sich der Zugriff auf einen CD-Spieler oder eine Wav-Datei mit Hilfe der Befehle der MCI-Commandstring-Schnittstelle gestaltet. In diesem Abschnitt geht es um das MCI-Steuerelement, welches die Multimediaprogrammierung mit Visual Basic weiter vereinfacht, da es für den Zugriff auf die einzelnen Geräte eine für den Anwender leicht zu bedienende und für den Entwickler leicht zu programmierende Funktionsleiste zur Verfügung stellt. Doch das MCI-Steuerelement macht mehr als nur die Befehle der MCI-Commandstring-Schnittstelle zusammenzufassen. Da es, anders als die MCISendString-Funktion, in der Lage ist, eine Rückmeldung von der Multimedia-DLL zu empfangen, wird eine echte "Parallelverarbeitung" möglich. Da dem ausführenden Programm nämlich über das Done- oder das ButtonCompleted-Ereignis mitgeteilt wird, wann eine MCI-Operation beendet wurde, kann es weder passieren, daß ein MCI-Befehl einen noch nicht vollständig abgearbeiteten MCI-Befehl "abwürgt«, noch daß ein MCI-Befehl mit gesetzter Wait-Option die weitere Programmausführung blockiert. Doch zunächst ein kleines Beispiel zur Einstimmung, das den grundsätzlichen Umgang mit dem MCI-Steuerelement verdeutlichen soll.

Bild: Das MCI-Steuerelement

Das MCI-Steuerelement in der Praxis

Wird das MCI-Steuerelement auf einem Formular angeordnet, stellt es neun Funktionsflächen zur Verfügung, die bereits über einen ihnen zugeordneten MCI-Befehl verfügen, der beim Anklicken der Funktionsfläche automatisch zur Ausführung gelangt. Wie Sie später noch sehen werden, ist es jedoch kein Problem, diese Standardfunktionalität aufzuheben. Die neun Funktionsflächen des MCI-Steuerelements besitzen feste Bezeichnungen, die in der Tabelle zusammen mit ihrer Bedeutung aufgeführt werden:

Funktionsfläche

Bedeutung

Prev

Zurückspulen an den Anfang

Next

Zurückspulen an das Ende

Play

Abspielen

Pause

Anhalten

Back

Einen Track zurück

Step

Einen Track nach vorne

Stop

Abbrechen

Record

Aufnehmen

Eject

Auswurf

Tabelle 2: Die Funktionsflächen des MCI-Steuerelements und ihre Bedeutung

Bereits diese Auflistung macht deutlich, daß nicht jede der Funktionsflächen für jedes MCI-Gerät in Frage kommt. So werden beim Abspielen einer Wav-Datei die Funktionsflächen Back, Step und Eject nicht benötigt, während eine Record-Funktionsfläche beim Abspielen einer Audio-CD oder Bildplatte keinen Sinn ergibt. Über die Eigenschaft ButtonVisible, wobei Button für den Namen einer der neun Funktionsflächen steht, kann eine einzelne Funktionsschaltfläche jederzeit ein- und ausgeblendet werden. Besitzt die Eigenschaft AutoEnable den Wert True, werden nach dem Öffnen eines Gerätes nur jene Funktionsflächen aktiv, die bei dem betreffenden Gerät eine Funktion besitzen. Sie sehen bereits an dieser ersten Übersicht, daß sich das MCI-Steuerelement sehr flexibel einsetzen läßt.

Ein kleines Beispiel

Bevor es an die Umsetzung einer richtigen Anwendung geht, soll Sie ein erstes Beispiel auf den Umgang mit dem MCI-Steuerelement einstimmen. Die Ausführung der folgenden Befehlssequenz führt dazu, daß eine Wav-Datei geladen und durch Anklicken der Play-Funktionsfläche abgespielt werden kann:

MMControl1.Wait = True

MMControl1.DeviceType = "WaveAudio"

MMControl1.FileName = "C:\WINDOWS\INTERCOM.WAV"

MMControl1.Command = "Open"

Das war bereits alles. Das Anklicken der Play-Funktionsfläche bewirkt nun, daß der Inhalt der Wav-Datei INTERCOM.WAV abgespielt wird. Das Setzen der Wait-Eigenschaft auf True ist nur dann erforderlich, wenn das nächste Kommando erst dann ausgeführt werden soll, wenn das Abspielen der Wav-Datei beendet wurde. Genauso optional ist das Zuweisen eines Wertes an die DeviceType-Eigenschaft, denn das MCI-Steuerelement kann den jeweiligen Gerätetyp bereits an der Dateierweiterung erkennen. Das Abspielen einer Wav-Datei reduziert sich damit auf zwei simple Zuweisungen.

Wenn Sie einmal einen Blick in die Visual Basic-Hilfe werden, werden Sie wahrscheinlich feststellen, daß es keine Möglichkeit zu geben scheint, dem open-Befehl zusätzliche Parameter wie etwa einen from-Wert oder einen Aliasnamen übergeben zu können. Nun, das ist nur teilweise richtig. Das MCI-Steuerelement verfügt nämlich über Eigenschaften, wie From, Notify, Wait und To, mit denen diese Parameter vorher eingestellt werden. Die Möglichkeit, einen Aliasnamen vergeben zu können, scheint es beim MCI-Steuerelement dagegen tatsächlich nicht zu geben.

Die wichtigsten Eigenschaften des MCI-Steuerelements

Das MCI-Steuerelement wird nahezu ausschließlich über das Setzen und Abfragen von Eigenschaftswerten während der Programmausführung programmiert. Methoden spielen keine und Ereignisse nur eine untergeordnete Rolle. Die folgende Auflistung enthält die wichtigsten Eigenschaften des MCI-Steuerelements. Wie Sie beim Durcharbeiten feststellen werden, sind diese relativ selbsterklärend. Sofern Sie sich bereits mit den MCI-Befehlen beschäftigt haben, sollte es bei der Anwendung der einzelnen Eigenschaften daher keine Probleme geben. Auch das MCI-Steuerelement läßt sich am besten durch "learning by doing" in den Griff kriegen. Das Schöne daran ist, daß Sie alle Eigenschaften während einer Programmunterbrechnung ausprobieren können und nicht auf die MCISend$-Funktion angewiesen sind.

Eigenschaft

Bedeutung

AutoEnable

Besitzt diese Eigenschaft den Wert True (Voreinstellung), werden nach dem Öffnen eines Gerätes automatisch jene Funktionsflächen aktiviert, die für das Gerät zur Verfügung stehen. Außerdem werden automatisch jene Funktionsflächen deaktiviert, die in dem aktuellen Arbeitsmodi nicht gewählt werden können. So schließt zum Beispiel eine aktiviert Record-Taste die Play-Taste aus.

ButtonEnabled

Besitzt diese Eigenschaft den Wert True, wird die betreffende Funktionsfläche aktiviert. Der Platzhalter Button steht dabei für die Werte Back, Eject, Next, Pause, Play, Prev, Record, Step oder Stop. Beispiel: EjectEnabled=False.

ButtonVisible

Besitzt diese Eigenschaft den Wert True, wird die betreffende Funktionsfläche unsichtbar gemacht. Der Platzhalter Button steht dabei für die Werte Back, Eject, Next, Pause, Play, Prev, Record, Step oder Stop. Beispiel: EjectVisible=False.

CanEject

Liefert einen True-Wert, wenn der Auswurf des Geräts betätigt werden kann.

CanRecord

Liefert einen True-Wert, wenn das Gerät aufnehmen kann.

Command

Über diese Eigenschaft wird ein MCI-Befehl, wie zum Beispiel open, close, play oder seek abgesetzt. Die benötigten Parameter werden durch das Setzen der entsprechenden Eigenschaften übergeben.

DeviceType

Liefert einen String, der das aktuell geöffnete Gerät kennzeichnet. In Frage kommen die Werte: AVIVideo, CDAudio, DAT, DigitalVideo, MMMovie, Other, Overlay, Scanner, Sequencer, VCR, Videodisk und WaveAudio.

Enabled

Besitzt diese Eigenschaft einen True-Wert, kann das MCI-Steuerelement auf Benutzereingaben reagieren.

Error

Enthält den Fehlercode des letzten MCI-Befehls.

ErrorMessage

Enthält den Fehlertext zu dem Fehler des zuletzt ausgeführten MCI-Befehls.

FileName

Legt den Dateinamen fest, bei der Ausführung des open- oder close-Befehls verwendet wird.

From

Legt die Startposition bei der Ausführung des play- oder seek-Befehls fest.

hWndDisplay

Legt die Bezugsnummer für das Formular oder das Bildfeld fest, in dem eine Ausgabe erfolgen soll. Ist zum Beispiel beim Abspielen einer AVI-Datei von Bedeutung.

Length

Liefert die Gesamtabspiellänge des geöffneten MCI-Gerätes.

Mode

Liefert einen Code für den aktuellen Betriebszustand.

Notifyt

Besitzt diese Eigenschaft den Wert True, führt das Beenden eines MCI-Befehls zum Aufruf der Done-Ereignisprozedur. Besitzt sie dagegen den Wert False (Voreinstellung), unterbleibt dieser Aufruf.

Orientation

Legt fest, ob das MCI-Steuerelement während der Programmausführung vertikal (Orientation=1) oder horizontal (Orientation=0, Standardeinstellung) dargestellt wird.

Position

Liefert die aktuelle Position beim Abspielen eines MCI-Gerätes. Diese Eigenschaft kann nur gelesen werden. Das Setzen der Position erfolgt über die From-Eigenschaft vor der Ausführung eines play-Befehls.

Silent

Über diese Eigenschaft kann der Ton während dem Abspielen eines Gerätes ausgeschaltet (Silent=True) und wieder eingeschaltet werden (Silent=False).

TimeFormat

Legt das zu verwendende Zeitformat für alle Positionsangaben fest. Die einzelnen Werte entnehmen Sie bitte der Online-Hilfe. Für Wav-Dateien ist als Format nur Millisekunden (MCI_FORMAT_MILLISECONDS, 0) erlaubt.

To

Legt bei der Ausführung eines play- oder record-Befehls fest, bis zu welcher Position das Gerät abgespielt werden soll.

Track

Wählt einen Track aus, über den Informationen eingeholt werden sollen.

TrackLength

Ermittelt die Länge des ausgewählten Tracks.

TrackPosition

Ermittelt die aktuelle Position innerhalb des Tracks.

Tracks

Liefert die Anzahl der Tracks auf dem geöffneten MCI-Gerät.

Wait

Besitzt diese Eigenschaft den Wert True, wird mit der Ausführung eines MCI-Befehls gewartet, bis der vorhergehende MCI-Befehl abgeschlossen wurde.

Tabelle 3: Die wichtigsten Eigenschaften des MCI-Steuerelements

Für die Mode-Eigenschaft kommen folgende Werte in Frage:

Wert

Konstante

Bedeutung

524

mciModeNotOpen

Nicht geöffnet

525

mciModeStop

Angehalten

526

mciModePlay

Abspielen

527

mciModeRecord

Aufnahme

528

mciModeSeek

Suchen

529

mciModePause

Unterbrochen

530

mciModeReady

Bereit

Tabelle 4: Die möglichen Einstellungen der Mode-Eigenschaft

Die wichtigsten Ereignisse

Ereignisse spielen, im Gegensatz zu anderen Steuerelementen, beim MCI-Steuerelement nur eine untergeordnete Rolle. Auch die nächsten beiden Beispielprogramme, bei denen es um das Abspielen von Wav- und AVI-Dateien geht, kommen (fast) vollständig ohne Ereignisse aus.

Das Done-Ereignis

Wenn Sie sich noch einmal an den Anfang dieses Kapitels zurückerinnern, werden Sie feststellen, daß der direkte Aufruf der MCI-Befehle zwar relativ leicht zu bewerkstelligen war, dafür aber leider einen kleinen Nachteil besaß. Es gab nämlich keine Möglichkeit in einem Visual-Basic-Programm festzustellen, wann eine MCI-Operation wie zum Beispiel das Abspielen einer Wav-Datei beendet wurde. Um ein solches Ereignis feststellen zu können, hätte man mit Hilfe eines Zeitgebers in periodischen Abständen den Status des MCI-Geräts abfragen können. Doch eine solche Lösung ist natürlich nicht besonders elegant, zumal sie, je nach Granularität des Zeitgebers, die Programmausführung unnötig verlangsamt. Schuld an dieser Einschränkung war allerdings nicht die MCI-Schnittstelle, sondern vielmehr Visual Basic, das nämlich nicht in der Lage ist, einer Windows-Funktion die Adresse einer Funktion zur Verfügung zu stellen, die im Falle eines Ereignisses aufgerufen werden kann.

Das MCI-Steuerelement behebt genau diesen Mangel. Zum einen verfügt es nämlich über das Ereignis ButtonCompleted, das immer dann ausgelöst wird, wenn ein über eine Funktionsfläche gestarteter MCI-Befehl beendet wird. Die Vorsilbe Button steht dabei für einen der neun Funktionsflächenamen. So wird das PlayCompleted-Ereignis ausgelöst, wenn eine Wav-Datei abgespielt wurde. Zum anderen verfügt das MCI-Steuerelement über die Ereignisprozedur Done, die immer dann aufgerufen wird, wenn ein MCI-Befehl abgearbeitet wurde, bei dem zuvor die Notify-Eigenschaft den Wert True erhielt.

Syntax

Sub MMControl_ButtonCompleted (ErrorCode AS Long)

und

Sub MMControl_Done (NotifyCode AS Long)

Unter Mitwirkung dieser Ereignisprozeduren ist es zum Beispiel überhaupt kein Problem, mehrere Wav-Dateien durch mehrere hintereinandergeschaltete play-Befehle abzuspielen, indem das folgende play-Kommando in der PlayCompleted- oder Done-Prozedur ausgeführt wird. Voraussetzung für den Aufruf der Done-Ereignisprozedur ist allerdings, daß die Eigenschaft Notify des MCI-Steuerelements den Wert True besitzt, denn ansonsten wird kein Done-Ereignis ausgelöst.

Der Parameter NotifyCode gibt dabei darüber Auskunft, auf welche Weise der letzte MCI-Befehl beendet wurde. Folgende Werte kommen für diesen Parameter in Frage:

Wert

Bedeutung

1

Befehl wurde erfolgreich ausgeführt.

2

Befehl wurde durch einen folgenden Befehl abgelöst.

4

Befehl wurde durch den Benutzer abgebrochen.

8

Befehl konnte nicht zu Ende gebracht werden.

Bei einem ButtonCompleted-Ereignis wird dagegen nur ein einfacher Fehlercode übergeben, der den Wert 0 besitzt, wenn der MCI-Befehl erfolgreich ausgeführt wurde, und ansonsten einen Fehlercode darstellt.

Das ButtonClick-Ereignis

Das Besondere am MCI-Steuerelement ist, daß seine Funktionsflächen bereits mit einem MCI-Befehl belegt sind. Dabei gilt folgende Standardbelegung:

Funktionsfläche

MCI-Befehl

Back

MCI_STEP

Step

MCI_STEP

Play

MCI_PLAY

Pause

MCI_PAUSE

Prev

MCI_SEEK

Next

MCI_SEEK

Stop

MCI_STOP

Record

MCI_RECORD

Eject

MCI_SET mit MCI_SET_DOOR_OPEN-Parameter

Immer, wenn der Benutzer eine der Funktionsflächen mit der Maus anklickt, wird ein ButtonClick-Ereignis ausgelöst, wobei die Vorsilbe Button auch hier durch den Namen der Funktionsfläche ersetzt werden muß. Das Anklicken der Play-Schaltfläche führt zum Aufruf der PlayClick-Prozedur, das Anklicken der Eject-Schaltfläche zum Aufruf der EjectClick-Prozedur usw. So weit, so gut. Doch nun kommt der interessante Teil. Wie die Syntaxbeschreibung nämlich offenbart, wird beim Aufruf der Prozedur ein Parameter übergeben.

Syntax

Sub MMControl_ButtonClick (Cancel AS Integer)

Setzt man den Cancel-Parameter auf True, wird der Standard-MCI-Befehl nicht ausgeführt und man kann der Funktionsfläche eine neue Bedeutung geben. In diesem Fall wird übrigens auch das ButttonCompleted-Ereignis nicht aufgerufen. Erhält der Cancel-Parameter dagegen den Wert False, werden zuerst alle Anweisungen innerhalb der Ereignisprozedur und anschließend der Standard-MCI-Befehl ausgeführt. In diesem Fall dient die ButtonClick-Prozedur dazu, das Standardverhalten der Funktionsschaltfläche zu modifizieren.

Übung 3

Das Beispielprogramm der folgenden Übung zeigt den Einsatz des MCI-Steuerelements in der Praxis. Diesmal geht es um ein Programm zum Abspielen von Wav-Dateien. Vergleichen Sie dazu dieses Beispiel mit dem Beispielprogramm aus Übung 1, welches direkt auf die MCI-Commandstring-Schnittstelle zugreifen mußte. Dieses Programm läßt sich nur ausführen, wenn der PC über eine Soundkarte verfügt, oder wenn der Lautsprechertreiber SPEAKER.DRV innerhalb der Windows-Systemsteuerung installiert wurde.

Wie funktioniert’s?

Das Abspielen einer Wav-Datei wird in der allgemeinen Prozedur SoundAbspielen vorgenommen, die alle benötigten Anweisungen des MCI-Steuerelements mit Werten belegt und abschließend den open-Befehl ausführt. Während des Abspielens wird die aktuelle Position innerhalb der Wav-Datei über eine Bildlaufleiste angezeigt. Das Skalieren der Bildlaufleiste ist extrem einfach, denn es genügt der Eigenschaft Max die Länge der Wav-Datei zuzuweisen, die über die Eigenschaft Length des MCI-Steuerelements in Millisekunden ermittelt wird. Jede geladende Wav-Datei wird in ein Listenfeld eingetragen, so daß das erneute Abspielen ein wenig vereinfacht wird. Beachten Sie allerdings, daß das Abspielen erst dann möglich wird, wenn die alte Datei über einen open-Befehl geschlossen wurde. Der Grund liegt darin, daß es bei Verwendung des MCI-Steuerelements scheinbar nicht möglich ist, einen Aliasnamen zu vergeben. Bliebe noch zu erwähnen, daß eine Wav-Datei während des Abspielens vor- oder zurückgespult werden kann, was zu interessanten Soundeffekten (Stichwort: Scratching) führen kann. Möglich wird dies durch die Ereignisprozedur Spieldauer_Scroll, die beim Verschieben der Schiebebox aufgerufen wird:

Sub Spieldauer_Scroll ()

If MMControl1.Mode = MCI_MODE_PLAY Or MMControl1.Mode = MCI_MODE_PAUSED Then

MMControl1.To = Spieldauer.Value

MMControl1.Command = "Seek"

End If

End Sub

Innerhalb dieser Prozedur wird der aktuelle Wert der Bildlaufleiste der Eigenschaft To des MCI-Steuerelements zugewiesen. Ein anschließendes Ausführen des seek-Kommandos führt dazu, daß das Abspielen der Sounddatei an dieser Position fortgesetzt wird.

Abspielen von Sounddateien

Für das simple Abspielen von Wav-Dateien kommt man auch ohne die MCI-Schnittstelle aus. Über die API-Funktion sndPlaySound läßt sich eine Wav-Datei durch einen einzigen Aufruf abspielen.

Syntax

Declare Function sndPlaySound Lib "mmsystem.dll" (ByVal lpSound As String, ByVal Flag As Integer) As Integer

Wert von Flag

Bedeutung

Flag=0

Die Steuerung wird erst nach dem Abspielen an das Programm zurückgegeben.

Flag=1

Die Steuerung wird sofort nach dem Aufruf wieder an das Programm zurückgegeben.

Abspielen von Videodateien

Eine Videodatei ist eine Datei, die aus einer Folge von Bildern besteht, die nacheinander dargestellt den Eindruck einer Bewegung erzeugen. Da eine Videodatei in der Regel auch einen Begleitsound enthält, hat das Abspielen einer Videodatei den gleichen Effekt als würden Sie in einem Fenster des Bildschirms ein Video über einen angeschlossenen Videorecorder oder Bildplattenspieler abspielen. Allerdings muß eine Videodatei nicht unbedingt "Live-Video" enhalten, auch Animationen oder der "Mitschnitt" von Bedienungssequenzen eines Programms werden in Videodateien abgelegt. Auch wenn die Videosequenzen einiger populärer Multimediatitel im QuickTime-Format vorliegen, muß da AVI-Format als Standard für Videodateien unter Windows bezeichnet werden. Mit Hilfe des MCI-Steuerelements ist das Abspielen von AVI-Dateien ein Kinderspiel.

Auch wenn der große Boom für Desktop-Video noch immer ausgeblieben ist und Videosequenzen, außer in Spielen, immer noch selten zu finden sind, bietet das MCI-Interface natürlich auch eine Vorrichtung für das Abspielen von AVI-Dateien. Die Abkürzung AVI steht für Audio Video Interlaced und beschreibt im wesentlichen ein Dateiformat, durch das Bildsequenzen und der dazugehörige Sound synchronisiert abgespeichert werden können. Eine AVI-Datei enthält somit bewegte Bilder mit dem dazugehörigen Stereoton. Mit Hilfe der Medienwiedergabe von Windows können AVI-Dateien abgespielt werden. Eine spezielle Hardware ist dazu nicht erforderlich. Allerdings hängt die erzielbare Bildwiederholfrequenz stark von der Hardware und den verwendeten Komprimierungsverfahren (aufgrund der hohen Datenmenge liegen Videosequenzen grundsätzlich komprimiert vor) ab. So läßt sich auf einem normalen Pentium eine Bildwiederholrate von mindestens 15 Bildern pro Sekunde erreichen, während auf einem schnellen Pentium-PC mit einer schnellen Grafikkarte ohne weiteres eine Bildwiederholrate von 24 Bildern pro Sekunde (Kinoqualiät) erzielt werden kann.

Und noch ein Nachteil soll nicht verschwiegen werden. AVI-Dateien sind extrem speicherintensiv. So belegt bereits eine AVI-Datei mit einem knapp 15 Sekunden langen "Film" bereits mehr als 2 Mbyte auf der Festplatte. Ein 5-Minuten-Musikvideo bereits über 50 Mbyte. Und dabei handelt es sich bereits um komprimierte Bildaten, die sich mit Pkzip kaum noch verkleinern lassen.

Trotz kleinerer Nachteile stellt die Möglichkeit, AVI-Dateien in ein Windows-Programm integrieren zu können einen echten Fortschritt dar. Spielprogramme mit "Reality effects", Trainings- und Lernprogramme, bei denen das zu erklärende Objekt mit Hilfe einer Bildsequenz dargestellt wird, oder E-Mail-Programme, die mit einem persönlichen Grußwort versehen werden können, seien als Beispiele erwähnt.

Für Visual-Basic-Programmiere» ist das Einbinden einer Videosequenz, zu welchem Zweck auch immer, kein Problem, denn selbstverständlich kann das MCI-Steuerelement auch mit AVI-Dateien umgehen. Das nächste Beispiel zeigt, daß für das Abspielen eines Films, der in Form einer AVI-Datei vorliegen muß, lediglich sechs Zuweisungen notwendig sind. Auch wenn die Möglichkeiten dieses "Videoplayer" recht begrenzt sind, sollte Sie dieses Beispiel unbedingt einmal selber ausprobieren, wen ist schon ein tolles Gefühlt, wenn auf einmal ein richtiges Video auf dem Bildschirm erscheint.

In sechs Schritten zu einem Videoplayer

Was ist zu tun, um auf dem Bildschirm AVI-Dateien abspielen zu können? Nicht viel, denn dank des MCI-Steuerelements reduziert sich der Aufwand auf ein absolutes Minimum. Alles, was das MCI-Steuerelement benötigt ist der Name der AVI-Datei und den MCI-Befehl zum Abspielen derselbigen.

Schritt 1: Anordnen des MCI-Steuerelements auf deme Formular

Grundvoraussetzung ist natürlich, daß das MCI-Steuerelement in Form der Datei MCI.OCX in die Werkzeugsammlung geladen und auf dem Formular angeordnet wurde.

Schritt 2: Anordnen eines Standarddialogs auf dem Formular

Um eine beliebige AVI-Datei laden zu können, wird der Standarddialog zur Auswahl der Datei benötigt.

Schritt 3: Einführen eines Menüs mit dem Namen DATEI

Die Auswahl einer AVI-Datei wird über ein Menü mit dem Namen mnuDatei durchgeführt.

Schritt 4: Aufruf des Standarddialogs

Wählt der Benutzer das Datei-Menü aus, soll ein Dialogfeld für die Auswahl einer AVI-Datei erscheinen:

StdDialog1.ShowOpen

Schritt 5: Dateinamen festlegen

Der in dem Dateidialogfeld ausgewählte Dateiname wird dem MCI-Steuerelement übergeben:

MMControl1.Filename = StdDialog1.Filename

Schritt 6: Die AVI-Datei wird abgespielt

Nachdem das MCI-Steuerelement den Namen der AVI-Datei kennt, steht dem Abspielen des Videos nichts mehr im Weg:

MMControl1.Command = "open"

Diese Anweisung sendet den open-Befehl an die MCI-Commandstring-Schnittstelle. Als Folge erwacht das MCI-Steuerelement zum Leben und es werden, dank AutoActivate=True, jene Funktionstasten aktiviert, die für das ausgewählte Gerät zur Verfügung stehen. Über die Funktionstaste Play kann die AVI-Datei nun gestartet werden.

Sicherlich ist das vorgeführte Beispiel noch zu primitiv, um es für irgend etwas gebrauchen zu können. So sollte in jedem Fall die Dateierweiterung .AVI in der Standarddialogbox bereits voreingestellt sein, damit die AVI-Datei mit der Maus ausgewählt werden kann. Außerdem sollten beim MCI-Steuerelement nur jene Funktionstasten angezeigt werden, die im Zusammenhang mit dem Abspielen von AVI-Dateien einen Sinn ergeben. Zwar lassen sich diese Erweiterungen mit ein paar zusätzlichen Anweisungen jederzeit hinzufügen, doch grundsätzlich ist der Sinn und Zweck des Programms sehr eingeschränkt. Das Beispiel macht aber dennoch gut deutlich, wie problemlos einfach der Zugriff auf AVI-Dateien dank des MCI-Steuerelements ist. Obwohl die MCI-Command-Schnittstelle auch für den Zugriff auf AVI-Dateien entsprechende Befehle zur Verfügung stellt, wird man in den allermeisten Fällen das MCI-Steuerelement vorziehen.

Die wichtigsten MCI-Befehle zum Abspielen einer AVI-Datei

Der folgende Abschnitt enthält eine Auflistung wichtiger MCI-Befehle, die beim Zugriff auf AVI-Geräte eine Rolle spielen.

open ElementName Type AVIVideo [alias Aliasname] [style overlapped|popup|child]

Öffnet eine AVI-Datei und stellt das Fenster in der festgelegten Weise dar.

play ElementName|Aliasname [from position] [to position]

Startet das Abspielen einer AVI-Datei, wobei sich die Angaben from position und to position auf das aktuelle Zeitformat beziehen.

pause ElementName|Aliasname

Hält das Abspielen einer AVI-Datei an.

resume ElementName|Aliasname

Setzt das Abspielen einer AVI-Datei fort.

seek ElementName|Aliasname to position|to end

Spult die AVI-Video auf die angegebene Position vor.

stop ElementName|Aliasname

Beendet das Abspielen einer AVI-Datei.

close ElementName|Aliasname

Schließt eine AVI-Datei. Anschließend ist auf diese Datei ohne einen open-Befehl kein Zugriff mehr möglich.

window ElementName|Aliasname handle hwnd

Legt fest, in welchem Fenster die Ausgabe des AVI-Bildes erfolgen soll. Für hwnd muß die Bezugsnummer, das heißt die hWnd-Eigenschaft, eines Formulars oder eines Bildfeldes eingesetzt werden.

status ElementName|Aliasname length

Liefert die Länge einer AVI-Datei.

status ElementName|Aliasname mode

Liefert den aktuellen Zustand einer AVI-Datei.

status ElementName|Aliasname position

Liefert die aktuelle Position beim Abspielen einer AVI-Datei.

where ElementName|Aliasname destination

Liefert die aktuellen Koordinaten des AVI-Bildes in Form einer Zeichenkette.

set ElementName|Aliasname time format milliseconds

Setzt das Zeitformat auf Millisekunden.

set ElementName|Aliasname time format frames

Setzt das Zeitformat auf Frames.

set ElementName|Aliasname audio on|off

Schaltet die Audio-Wiedergabe beim Abspielen der AVI-Datei ein oder aus.

Übung 4

Das Beispielprogramm der folgenden Übung demonstriert die Möglichkeiten des MCI-Steuerelements für das Abspielen von AVI-Dateien. Im Gegensatz zu dem ersten Beispiel in diesem Abschnitt wird das Video nicht in einem eigenen Fenster, sondern in einem Bildfeld dargestellt.

Wie funktioniert’s?

Auch wenn das Programmlisting auf den ersten Blick einen relativ umfangreichen Eindruck macht, so ist das Programm alles andere als schwer zu verstehen. Ein großer Teil der Programmlogik wird darauf verwendet, das AVI-Bild mit dem Bildfeld hbBildschirm und dem Fernseher-Bildfeld hbGehäuse, das in Form einer Metadatei vorliegt, in Einklang zu bringen. Ein wenig verkompliziert wird die ganze Angelegenheit durch den Umstand, daß mit dem Bildfeld shCtrBg noch ein weiteres Bildfeld beteiligt ist, das einzig und allein die Aufgabe besitzt, die maximale Größe des AVI-Bildes vorzugeben. In der allgemeinen Prozedur GetSize wird die Größe des AVI-Bildes über den MCI-Befehl where abgefragt und das Ergebnis in die Strukturvariable r eingetragen. Diese wird in der Datei T304_3.Bas definiert und besitzt den folgenden Aufbau:

Type rectType

x1 AS Long

y1 AS Long

x2 AS Long

y2 AS Long

End Type

Da die MCI-Schnittstelle die Koordinaten in Form einer Zeichenkette zurückliefert, müssen diese zunächst in numerische Werte umgewandelt werden, was über die Funktion RectStringToVal geschieht. In dieser Prozedur wird die Strukturvariable r mit den vier Koordinaten gefüllt. Dafür, daß das AVI-Bild überhaupt in einem Bildfeld, und nicht wie im letzten Beispiel in einem eigenen Fenster dargestellt wird, sorgt die Anweisung

mm1.hWndDisplay = pbLeinwand.hWnd

die die Bezugsnummer des Bildfeldes an die Eigenschaft hWndDisplay des MCI-Steuerelements zuweist. Anders als beim Abspielen einer Wav-Datei ist es bei einer AVI-Datei möglich, das Abspielen im Einzelschrittmodus durchzuführen, indem der Film Bild für Bild angezeigt wird. Dies geschieht in der Prozedur SeekAviToRegler, die dafür sorgt, daß das Abspielen bei jenem Frame (Bild) fortgesetzt wird, der durch die Bildlaufleiste hrStatus eingestellt wurde.

Kartenspiele

Wer sich für die Programmierung von Kartenspielen jeglicher Art interessiert, für den hält Windows ein nettes Bonbon bereit. Es heißt Cards.dll und ist eine Bibliothek, in der u.a. die Bitmaps aller 52 Spielkarten (allerdings ohne Joker) enthalten sind. Die DLL enthält nur drei wichtige Funktionen. Als erstes muß (warum auch immer) die Funktion cdtInit aufgerufen werden, die die Spielkarten initialisiert. Anschließend wird über die Funktion cdtDraw eine der 52 Spielkarten in ein Bildfeld übertragen. Zum Schluß wird das Ganze über die Funktion cdtTerm wieder deinitilaisiert.

Beispiel

Das folgende Beispiel enthält ein kleines Kartenspiel, das 5 Spielkarten in Bildfeldern ausgibt.

Der Allgemein-Teil

Option Explicit

 

' Diese API-Funktionen stammen aus der 32-Bit-DLL Cards.dll

Private Declare Function cdtInit Lib "\Windows\Cards.dll" (dy As Integer, dy As Integer) As Boolean

Private Declare Function cdtDraw Lib "\Windows\Cards.dll" (ByVal hdc As Integer, ByVal x As Integer, ByVal y As Integer, ByVal ordCard As Integer, ByVal ordDraw As Integer, ByVal clr As Long) As Boolean

Private Declare Function cdtTerm Lib "\Windows\Cards.dll" () As Integer

 

' Über diese Konstanten werden die zu ziehenden Kartentypen festgelegt

Const ordFaces = 0

Const ordInvert = 2

Const ordBacks = 1

Const ordRobot = 56

Const MaxKartenAnzahl = 5 ' Kartenstapel soll 5 Karten umfassen

 

Dim dxCard As Integer, dyCard As Integer ' Größe einer anzuzeigenden Karte

Dim KartenFeld() As Integer

Dim SelektiertFeld() As Boolean ' Hier werden die selektierten Karten eingetragen

Die Ereignisprozedur cmdZiehen_Click

Dim RetVal As Boolean

Dim KartenNr As Integer, n As Integer, m As Integer

Dim GefundenFlag As Boolean

ReDim KartenFeld(MaxKartenAnzahl)

ReDim SelektiertFeld(MaxKartenAnzahl)

' Es werden 5 Karten gezogen

For n = 0 To UBound(KartenFeld) - 1

Do

KartenNr = Int(Rnd * 52)

GefundenFlag = False

For m = 0 To n

If KartenNr = KartenFeld(m) Then

GefundenFlag = True

End If

Next m

Loop While GefundenFlag = True

KartenFeld(n) = KartenNr

' Anzeigen der Karte in dem Bildfeld picKarte

RetVal = cdtDraw(picKarte(n).hdc, 0, 0, KartenNr, ordFaces, 0&)

picKarte(n).Refresh

Next n

Die Ereignisprozedur Form_Load

Dim RetVal As Boolean, n As Integer

' Der Kartenstapel wird initialisiert

RetVal = cdtInit(dxCard, dyCard)

' Als Maßeinheit wird Pixel eingestellt

Me.ScaleMode = vbPixels

picKarte(0).ScaleMode = vbPixels

picKarte(0).Width = dxCard

picKarte(0).Height = dyCard

ReDim KartenFeld(MaxKartenAnzahl)

ReDim SelektiertFeld(MaxKartenAnzahl)

For n = 1 To UBound(KartenFeld) - 1

Load picKarte(n)

picKarte(n).Visible = True

picKarte(n).Width = dxCard

picKarte(n).Height = dyCard

picKarte(n).Left = picKarte(n - 1).Left + dxCard * 1.1

picKarte(n).Top = picKarte(0).Top

Next n

Me.Width = (picKarte(n - 1).Left + dxCard * 1.2) * Screen.TwipsPerPixelX

cmdZiehen.Left = (Me.ScaleWidth - cmdZiehen.Width) / 2

Die Ereignisprozedur Form_Unload

Private Sub Form_Unload(Cancel As Integer)

Dim RetVal As Boolean

RetVal = cdtTerm()

End Sub

Die Ereignisprozedur picKarte_Click

Private Sub picKarte_Click(Index As Integer)

' Es wurde eine Karte selektiert

Dim RetVal As Boolean

Dim KartenNr As Integer

KartenNr = KartenFeld(Index)

SelektiertFeld(Index) = Not SelektiertFeld(Index)

If SelektiertFeld(Index) = True Then

RetVal = cdtDraw(picKarte(Index).hdc, 0, 0, ordRobot, ordBacks, 0&)

Else

RetVal = cdtDraw(picKarte(Index).hdc, 0, 0, KartenNr, ordFaces, 0&)

End If

picKarte(Index).Refresh

End Sub

Zusammenfassung

Die Multimedia-Programmierung, das heißt das Abspielen von Wav-Dateien, das Ansteuern eines CD-Spielers oder das Abspielen eines Videos in Form einer AVI-Datei wird Visual-Basic-Programmierern dank der MCI-Schnittstelle sehr einfach gemacht. MCI steht für Media Command Interface und stellt eine leicht zu bedienende, dennoch aber sehr flexible Softwareschnittstelle dar, die das Ansteuern der unterschiedlichen Multimediageräten über eine Reihe einfacher, Basic-ähnlicher Befehle gestattet. Die MCI-Unterstützung steht dabei auf drei Ebenen zur Verfügung. Die unterste Ebene besteht in dem direkten Aufruf der Windows-API-Funktionen und kommt für die Visual-Basic-Programmierung im allgemeinen nicht in Frage. Der Grund ist einfach, alle elementaren Funktionen lassen sich sehr viel einfacher über die MCI-Commandstring-Schnittstelle absetzen, die Befehle, wie open, play, record oder close zur Verfügung stellt, die über die MCISendString-Funktion an den Multimediagerätetreiber geschickt werden. Allerdings besitzt diese Verfahren einen kleinen Nachteil. Rückmeldungen wie zum Beispiel die Beendigung eines MCI-Befehls kann ein Visual-Basic-Programm naturgemäß nicht in Empfang nehmen. Das ist erst auf der dritten Ebene mit Hilfe des MCI-Steuerelements möglich, das aber nur in der Professional-Version zur Verfügung steht. Das MCI-Steuerelement bietet dem Anwender eine aus maximal neun Funktionsflächen bestehende Leiste, über die alle Multimediageräte angesteuert werden können. Einfacher kann die elementare Multimediaprogrammierung in einer universellen Programmiersprache, wie es Visual Basic nun einmal ist, kaum noch werden. Ein wenig schade ist nur, daß sich an diesem Prinzip seit Visual Basic 2 nichts geändert hat.