|
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.
|
|
|
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.
|
|
|
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.
|
|
|
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).
|
|
|
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.
|
|