DirectX 8 - Grundlagen
Falls ihr schon mit DirectX 7 programmiert habt, dann solltet ihr euch unbedingt die Änderungen und Neuerungen in der DirectX-MSDN (Bestandteil des DirectX 8-SDK) durchlesen. 
DirectX 8-Objekte erstellen
Arrays bei DirectX 8-Methoden
Bedeutung und Verwendung einer GUID
Bitmasken verwenden
DirectX 8-Aufzählungen (Enumeration)
Fehlerbehandlung
Flags bei DirectX 8-Methoden
Der IUnknown-Datentyp
DirectX8-Objekte erstellen
Jede Visual Basic-Anwendung die DirectX 8 verwendet, benötigt das DirectX8-Objekt. Es ist das Haupt-Objekt, dessen Methoden zur Erstellung der jeweiligen DirectX-Komponenten verwendet werden. Berechnungen für 3D stehen nicht mehr wie bei DirectX 7 über das DirectX-Objekt zur Verfügung, sondern können nur über das D3DX8-Objekt verwendet werden.
Damit ihr nicht durch die neuen Begriffe verwirrt werdet, hier eine kleine Erklärung der neuen Begriffe. DirectDraw und Direct3D wurden zu DirectGraphics zusammengefasst, wobei DirectGraphics jedoch nur ein "Ober"-Begriff, aber kein DirectX8-Objekt ist. Das DirectDraw-Objekt von DirectX 7 steht unter DirectX 8 nicht mehr zur Verfügung. Weiterhin neu ist DirectAudio, unter dem nun DirectMusic und DirectSound zusammengefasst sind. Auch DirectAudio ist kein DirectX8-Objekt, sondern lediglich wieder der entsprechende "Ober"-Begriff.
Gänzlich neu ist das DirectXFile-Objekt und es ermöglicht den Zugriff auf Microsoft DirectX X-Files. Mit DirectX 7 war dies nur über Direct3DRM (Retained Mode) möglich.
Die Erstellung eines DirectX8-Objekts ist einfach und geschieht gleich bei seiner Deklaration.
 
Public DX8 As New DirectX8
 
Um eine DirectX-Komponente zu erstellen, wie z.B. DirectSound, benötigt man zuerst eine Variablen-Deklaration für das Objekt. Danach wird das mit der entsprechenden DirectX8-Methode erstellte Objekt auf die Variable gesetzt.
 
Public gObjDSound As DirectSound8
Set gObjDSound = DX8.DirectSoundCreate("")
 
Die folgenden Objekte stehen für die DirectX-Komponenten, die über die DirectX 8-Methoden erstellt werden:
Komponente Objekt DirectX8 Create Methode
Direct3D Direct3D8 Direct3DCreate
DirectInput DirectInput8 DirectInputCreate
DirectMusic DirectMusicComposer8 DirectMusicComposerCreate
  DirectMusicLoader8 DirectMusicLoaderCreate
  DirectMusicPerformance8 DirectMusicPerformanceCreate
DirectPlay DirectPlay8Address DirectPlayAddressCreate
  DirectPlay8Client DirectPlayClientCreate
  DirectPlay8LobbiedApplication DirectPlayLobbiedApplicationCreate
  DirectPlay8LobbyClient DirectPlayLobbyClientCreate
  DirectPlay8Peer DirectPlayPeerCreate
  DirectPlay8Server DirectPlayVoiceClientCreate
  DirectPlayVoiceClient8 DirectPlayVoiceServerCreate
  DirectPlayVoiceServer8 DirectPlayServerCreate
  DirectPlayVoiceSetup8 DirectPlayVoiceSetupCreate
DirectSound DirectSoundCapture8 DirectSoundCaptureCreate
  DirectSound8 DirectSoundCreate
DirectXFile DirectXFile DirectXFileCreate
Die Direct3DX utility library (verschiedene Entwicklertools) wird nicht über das DirectX8-Objekt erstellt, sondern wird durch das D3DX8-Objekt repräsentiert. Das Objekt kann durch die Deklaration einer Variable als D3DX8-Objekt und dem Setzen einer neuen Instanz erstellt werden.
 
Dim myD3DX8 As D3DX8
Set myD3DX8 = New D3DX8
 
Arrays bei DirectX 8-Methoden
Einige DirectX 8-Methoden geben Daten in Parametern zurück, deren Typ nicht spezifiziert ist. So liefert z.B. die DirectSoundCaptureBuffer8.ReadBuffer-Methode einen Puffer vom Typ Any. Da es diesen Datentyp in VB nicht gibt, kann VB diesen Datentyp nicht interpretieren.
In Visual Basic ist es daher besser, wenn solche Methoden die Daten als Array of Bytes (Byte-Datenfeld) liefern. Da es mit Visual Basic nicht möglich ist, nur den Namen des Arrays an die Methode zu übergeben, muss daher das erste Element eines Arrays übergeben werden. Im folgenden Beispiel ist dsCaptureBuffer als ein DirectSoundCaptureBuffer8-Objekt deklariert worden. Buffer ist ein Array of Bytes und nBytes ist ein Wert vom Typ Long, der die Anzahl der zu lesenden Bytes beinhaltet.
 
ReDim buffer(nBytes)
Call dsCaptureBuffer.ReadBuffer(0, nBytes, buffer(0), 0)
 
Wichtig:
Es gibt auch einige Methoden, die ein Array von einem vordefinierten DirectX 8-Datentyp erwarten, wie z.B. DirectInputDevice8.SendDeviceData. In solch einem Fall muss das Array ohne Angabe des ersten Elements übergeben werden. Im folgenden Beispiel ist formatArray ein Array of DIDEVICEOBJECTDATA.
 
MyDevice.SendDeviceData(lCount, formatArray(), lFlags)
 
Bedeutung und Verwendung einer GUID
GUID steht für Global Unique Identifier (globale eindeutige Identifikation) und wird für das von Microsoft entwickelte COM-Objekt (Component Object Model) benötigt. Jedes neue COM-Objekt, das offiziell publiziert wird, bekommt eine solche GUID, die weltweit einzigartig ist, also nur einmal existiert, und von sonst keinem anderem Objekt benutzt wird. Dadurch ist es möglich jedes Objekt anhand seiner GUID zu identifizieren.
Auch DirectX 8 basiert auf diesem COM-Modell, nur sind diese GUID's meistens in DirectX 8 für Visual Basic nicht sichtbar. Hin und wieder tauchen sie aber doch auf, dann aber nicht als numerische Werte sondern eher als Zeichenketten (Strings).
Mit dem Programm VBGuidGen.exe (\Samples\Multimedia\VBSamples\DXMisc\Bin) der DirectX 8-SDK kann eine neue GUID generiert werden. Das Programm erstellt eine neue eindeutige GUID, die mit dem Copy-Button kopiert wird und nur noch in das Visual Basic Programm eingefügt werden muss. Nicht vergessen, die GUID muss zwischen { } stehen und als String übergeben werden.
Einige DirectX-Methoden liefern einen Datentyp, der eine GUID beinhaltet. In DirectX 8 sind einige GUIDs für verschiedene Eigenschaften vordefiniert, da einige der DirectX 8-Methoden eine solche vordefinierte GUID erwarten. Diese können zwar auch während der Laufzeit mit der DirectX8.CreateNewGuid-Methode generiert und als String verwendet werden. Einfacher jedoch ist die Verwendung einer vordefinierten GUID. Bei der DirectInput8.CreateDevice-Methode z.B. erlaubt sie uns einen Device für ein Eingabegerät zu erstellen.
Hier ist die Verwendung der vordefinierten GUID "GUID_SysKeyboard" einfacher, als die Angabe der aktuellen GUID im String-Format.
Bitmasken verwenden
Einige in DirectX 8 vordefinierte Datentypen, wie z.B. D3DCAPS8, haben Long-Variablen, die Bitmasken liefern bzw. erwarten. In der Regel sollten diesen Variablen Werte im Hexadezimal-Format übergeben werden. Dabei ist zu beachten, dass Visual Basic dazu neigt, Hexadezimalwerte in den kleinsten Typ zu konvertieren. So würde z.B. &HFF von Visual Basic zu einem Integer mit -1 als Wert konvertiert werden. Übergibt man diesen Wert dann DirectX 8, so konvertiert es diesen Wert zu Long und der Wert ist dann &HFFFFFFFF.
Um sicherzugehen, dass Visual Basic die Hexadezimalwerte nicht konvertiert, setzt man daher ein zweites & an das Ende des Wertes.
 
DDSD.ddpfPixelFormat.lRBitMask = &HFF&
 
DirectX 8-Aufzählungen (Enumeration)
In der Regel lesen DirectX 8-Programme die verfügbaren Ressourcen des PCs während der Initialisierungsphase ein. So kann beispielsweise ein Programm unter Verwendung von DirectXGraphics prüfen, welche Display-Modi verfügbar sind, oder es kann mittels DirectInput ermitteln, wie viele verfügbare Achsen und Button ein am PC angeschlossener Joystick hat.
In DirectX 8 für Visual Basic werden Aufzählungen (Enumerations) automatisch behandelt, wenn das Programm ein solches Objekt verwendet. Wird solch ein Objekt erstellt, dann wird automatisch auch eine Aufzählung (Collection) erstellt. Diese Collection existiert so lange, wie das Objekt existiert.
Einige Aufzählungen erhält man durch das DirectX 8-Objekt, wie z.B. die DirectSound8-Devices. Über die DirectX8.GetDSEnum-Methode erhält man eine Aufzählung der verfügbaren Soundkarten und deren GUID's. Mit einer GUID aus dieser Aufzählung kann man dann ein DirectSound8-Objekt erstellen.
Andere Aufzählungen erhält man von den DirectX-Komponenten selbst, so liefert z.B. das DirectInput8-Objekt eine Aufzählung mittels der DirectInput8.GetDIEnumDevices-Methode.
Das folgende Beispiel zeigt wie alle am PC angeschlossenen Eingabegeräte aufgelistet werden. di ist ein DirectInput8-Objekt.
 
Dim diEnum As DirectInputEnumDevices8
Set diEnum = di.GetDIDevices(0, DIEDFL_ATTACHEDONLY)
 
Mit zwei Methoden des DirectInputEnumDevices8-Objekts können nun die angeschlossenen Eingabegeräte aufgelistet werden, um z.B. ein Gerät zu ermitteln, welches die gewünschte Eigenschaft hat. Im folgenden Beispiel wird der Name jedes Gerätes in eine ListBox geschrieben.
 
Dim diDevice As DirectInputDeviceInstance
Dim X As Integer

For X = 1 To diEnum.GetCount
    Set diDevice = diEnum.GetItem(X)
    Call List1.AddItem(diDevice.ProductName)
Next X
 
Zu beachten ist, dass mit DirectX erstellte Aufzählungen immer mit 1 beginnen.
Fehlerbehandlung
In C und C++ wird eine HRESULT-Variable bei jedem Methoden-Aufruf gesetzt. Mit HRESULT kann das Programm entscheiden, ob es die Rückgabewerte einer Methode verarbeitet oder ignoriert. Anders ist es in Visual Basic, verursacht eine Methode einen Fehler, wird meist die Prozedur oder gar das ganze Programm beendet. Daher sollte man eine Fehlerbehandlung programmieren, damit das Programm nicht gleich beendet wird.
Die Fehlernummer wird in Visual Basic im globalen Err-Objekt gesetzt. Fast alle der möglichen Fehler für jede DirectX 8-Methode sind in der DirectX 8-Dokumentation aufgelistet, und die Fehlernummern sind sogar als Konstanten vordefiniert. Man muss sie nur abfangen.
Die DirectX 8-SDK enthält unter "\DirectX8\samples\Multimedia\Misc\bin\DXErr.exe" das Tool "DirectX Error Lookup", mit dem es möglich ist, sich den Klartext der entsprechenden  DirectX 8-Fehlernummer ausgeben zu lassen.
Auch VB-fun.de hält mit dem DirectX Error Code Viewer solch ein nützliches Tool sowohl für DirectX 7- als auch für DirectX 8-Fehlernummern bereit.
Flags bei DirectX8-Methoden
Viele DirectX8-Methoden erwarten als Parameter einen Flag. Ein Flag ist wie ein oder mehrere Schalter zu verstehen und hat einen eindeutigen Wert. Flags werden verwendet um verschiedene Einstellungen festzulegen oder um festzustellen welche Einstellungen ein DirectX 8-Objekt hat. (Manche Flags sind eine Kombination aus anderen Flags).
Glücklicher Weise muss man sich die verschiedene Werte nicht merken, da die DirectX 8-Flags bereits in Auflistungen (Enumerations) vordefiniert sind.
Möchte man z.B. zwei Flags miteinander kombinieren, verwendet man den logischen OR-Operator. Natürlich könnten die Flags auch normal addiert werden, aber das kann zu Fehlern führen, weil einige Flags bereits eine Kombination aus anderen Flags sind.
Nehmen wir z.B. die Methode SetCooperativeLevel des DirectInputDevice8-Objekts, so erwartet diese einen Flag aus der CONST_DISCLFLAGS- Auflistung. Wenn wir nun den Device für Vordergrund und Exklusiv (foreground ; exclusive) haben möchten, dann müssen wir die beiden Flags DISCL_EXCLUSIVE und DISCL_FOREGROUND mit einem OR kombinieren.
 
diDevice.SetCooperativeLevel(hwnd, _
         DISCL_FOREGROUND Or DISCL_EXCLUSIVE)
 
Wie bereits erwähnt, können zwei oder mehr Flags auch normal addiert werden, man sollte sich aber angewöhnen, nur den logischen OR-Operator zu verwenden. Manche Flags sind bereits aus anderen Flags kombiniert und ein normales Addieren würde dann zu einem falschen Ergebnis führen.
Der Flag CF_PURPLE ist z.B. bereits eine Kombination aus CF_RED und CF_BLUE
 
Enum COLORFLAGS
  CF_RED = 1
  CF_BLUE = 2
  CF_PURPLE = 3
  CF_GREEN = 4
End Enum

Dim Color As Integer
Color = CF_RED Or CF_PURPLE
 
Der Wert von Color ist nun 3, da CF_RED bereits in CF_PURPLE enthalten ist (redundant) und nicht mehr hinzuaddiert wird. Bei
 
Color = CF_RED + CF_PURPLE
 
würde eine Addition der Werte zu einem falschen Wert (4 bzw.CF_GREEN ) führen.
Um aus einer Kombination von Flags die einzelnen Flags zu bekommen, wird der logische AND Operator verwendet. Ist ein bestimmter Flag in der Kombination vorhanden, dann liefert AND einen Wert ungleich Null und der Flag ist vorhanden, wurde also gesetzt. Wenn AND Null liefert, ist der Flag nicht gesetzt worden.
Wollen wir z.B. prüfen, ob ein bestimmter Joystick am Computer angeschlossen ist, können wir dies über die Eigenschaft lFlags erfahren. lFlags besteht aus eine Kombination von Flags. Durch das logische AND kann daher geprüft werden ob der Flag DIDC_ATTACHED in der Eigenschaft lFlags enthalten ist.
 
Dim IsAttached As Boolean
IsAttached = diDevCaps.lFlags And DIDC_ATTACHED
 
Ist im Wert von diDevCaps.lFlags der Wert von DIDC_ATTACHED enthalten, dann wird IsAttached auf True gesetzt.
Ein Vergleichen mit =
 
IsAttached = (diDevCaps.lFlags = DIDC_ATTACHED)
 
würde nicht funktionieren, da in diDevCaps.lFlags auch der Wert des Flags DIDC_FORCEFEEDBACK enthalten sein könnte, wenn ein angeschlossener Joystick auch Force Feedback unterstützt. In dem Fall hat lFflags den Wert 257 (1 für DIDC_ATTACHED und 256 für DIDC_FORCEFEEDBACK).
Der IUnknown-Datentyp
Es gibt bei DirectX 8 für Visual Basic einige Methoden die als Rückgabewert oder als Parameter einen Unknown-Datentyp haben. Der Typ dieses Wertes ist undefiniert und steht in VB als IUnknown zur Verfügung (aber nicht als Intellisense, ihr müsst den Datentyp ausschreiben).
Eine Deklarierung als Unknown ist dem Any gleichzusetzen. Wird ein Parameter als Any-Datentyp verlangt, so kann jeder beliebige Datentyp angegeben werden. Bei Unknown ist es ähnlich, nur dass hier jeder beliebige Objekt-Typ angegeben werden kann.
Bei DirectX 8 werden in zwei Fällen Deklarierungen mit Unknown verwendet:
  • Wenn ein Objekt nicht durch eine Klasse deklariert wird. Solche Objekte stellen eurer Anwendung keine Methoden oder Eigenschaften zur Verfügung. Eure Anwendung bekommt eine Referenz von einer Methode, die ihr wiederum einer anderen Methode als Referenz mitgeben könnt. DirectMusicSegment8.GetAudioPathConfig z.B. liefert ein Unknown, d.h. die Methode liefert einen IUnknown Wert als Referenz der nicht durch eine Klasse deklariert wurde. Diese Referenz kann von eurer Anwendung einer anderen Methode als Parameter wieder übergeben werden.
  • Wenn ein Parameter mehr als einen Objekt-Typ akzeptieren muss. Deklarierung eines Parameters als Unknown erlaubt der Methode jeden beliebigen Objekt-Typ zu übernehmen. Zum Beispiel ist der erste Parameter von DirectMusicBand8.Unload als Unknown deklariert. Der Parameter kann daher eine Referenz von DirectMusicAudioPath8 oder DirectMusicPerformance8 übernehmen.

Eine IUnknown-Variable stellt keinen direkten Zugang zu den Methoden oder Eigenschaften des Objektes dessen Referenz es darstellt. Wenn ihr eine Objekt-Referenz als IUnknown habt, dann müsst ihr sie auf eine deklarierte Klasse setzen damit ihr auf die jeweiligen Objekt-Methoden zugreifen könnt.

Das Beispiel zeigt die Verwendung des IUnknown-Datentypes.
 
'dmSeg ist ein DirectMusicSegment8 Objekt
'dmPerf ist ein DirectMusicPerformance8 Objekt

Dim config As IUnknown
Dim audioPath As DirectMusicAudioPath

Set config = dmSeg.GetAudioPathConfig
Set audioPath = dmPerf.CreateAudioPath(config)
 
Der DirectMusicSegment8.GetAudioPathConfig-Rückgabewert ist eine Referenz zu einem Konfigurations-Objekt, das nicht durch eine Klasse deklariert ist. Alles was ihr nun tun müsst, ist diese Objekt-Referenz der anderen Methode wieder zu übergeben, im Beispiel der DirectMusicPerformance8.CreateAudioPath.
Die folgende Verwendung vom IUnknown-Datentyp ist falsch:
 
'objDiDev ist ein DirectInputDevice8 Objekt

Dim unk As IUnknown
Set unk = objDiDev
NumItems = unk.GetDeviceData(diDeviceData,0) 'Falsch!
 
Der Aufruf der DirectInputDevice8.GetDeviceData-Methode wird einen "Methode nicht gefunden"-Fehler auslösen.

Zum Seitenanfang

Startseite | VB-/VBA-Tipps | Projekte | Tutorials | API-Referenz | Komponenten | Bücherecke | Gewinnspiele | VB-/VBA-Forum | DirectX-Forum | VB.Net | .Net-Forum | Foren-Archiv | Chat | Spielplatz | Links | Suchen | Stichwortverzeichnis | Feedback | Impressum

Seite empfehlen Bug-Report
Letzte Aktualisierung: Sonntag, 18. September 2005