Wie blitte ich ein Bild auf die primäre Surface?
(von Jens Konerow)
Was ist überhaupt eine Surface?
Eine Surface kann man sich als ein Blatt Papier vorstellen, auf dem dann das
Bild gezeichnet wird. Die Surface ist ein zusammenhängender Speicherbereich.
Dieser kann im Videospeicher liegen oder im Systemspeicher. Der Systemspeicher
ist aber wesentlich langsamer als der Videospeicher.
Es werden 5 Surface-Typen unterschieden. Wir wollen jetzt allerdings nur auf
2 eingehen.
Die eine ist die primäre Surface und die zweite ist die Offscreen-Surface.
Der Anwender sieht aber nur die primäre Surface. Das Bild wird erst auf
der Offscreen-Surface, auch BackBuffer genannt, aufgebaut; wenn es dann vollständig
ist, dann wird es auf einen Schlag auf die primäre Surface kopiert. Durch
dieses Verfahren wird sichergestellt, das der Anwender vom Aufbau des Bildes
nichts mitbekommt und kein flackerndes Bild sieht.
Wie erstelle ich eine Surface?
Wir erstellen ein Standard-EXE-Projekt und ordnen auf dem Formular eine Picture-Box
an, auf der das Bild später zu sehen sein wird. Dann müssen wir die
DirectX-API in unser VB-Projekt einbinden. Das machen wie, indem wir unter Projekt
--> Verweise in der Liste DirectX7 for Visual Basic Library ankreuzen und
dann auf OK klicken. Jetzt müssen wir erst ein DirectX-Objekt erstellen
und anschließend werden wir die Variable für das DirectDraw-Objekt
deklarieren. Das sieht dann wie folgt aus:
Dim objDX As New DirectX7
Dim objDD As DirectDraw7
Jetzt wollen wir die Variablen für die Surface und die Variablen vom Typ
DDSURFACEDESC2 deklarieren. DDSURFACEDESC2 enthält die Beschreibung einer
DirectDrawSurface. Ok, als erstes deklarieren wir die Variablen für die
Surface:
Dim objPrimSurf As DirectDrawSurface7
Dim objBackSurf As DirectDrawSurface7
Nun kommen die Variablen vom Typ DDSURFACEDESC2 an die Reihe:
Dim ddsdPrimSurf As DDSURFACEDESC2
Dim ddsdBackSurf As DDSURFACEDESC2
Das waren die Deklarationen! Nun werden wir die Variablen initialisieren, sprich:
wir werden die Objekte erstellen. Als erstes werde ich den Zugriff auf die Grafikkarte
erzeugen:
Set objDD = objDX.DirectDrawCreate("")
Wurde der String leer gelassen, wird der primäre Display-Device genutzt.
Nun legen wir fest, dass wir einen Fenster-Anwendung haben wollen:
Call objDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
Me.hWnd gibt uns das Handle des aktiven Form-Objekts und DDSCL_NORMAL gibt
an, dass wir eine normale Anwendung möchten. Nun wollen wir die Beschreibungen
der primären Surface festlegen:
ddsdPrimSurf.lFlags = DDSD_CAPS
ddsdPrimSurf.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE
Nun wird die primäre Surface erstellt:
Set objPrimSurf = DD.CreateSurface(ddsdPrimSurf)
DDSD_CAPS gibt uns den Zugriff auf die ddsCaps-Datenstruktur frei und DDSCAPS_PRIMARYSURFACE
legt fest, dass das eine primäre Surface sein soll.
Mit Set objPrimSurf = DD.CreateSurface(ddsdPrimSurf) wird die primäre Surface
erstellt. Jetzt kommen wir zur der zweiten Surface, die Offscreen-Surface. Von
dieser wird das Bild dann auf die primäre Surface geblittet (kopiert).
Wir gehen erstmal genauso vor, wie oben beschrieben:
ddsdBackSurf.lFlags = DDSD_CAPS
ddsdBackSurf.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
Set objBackSurf = DD.CreateSurfaceFromFile(App.Path & _
"\Iron.bmp", dsdBackSurf))
DDSD_CAPS gibt uns den Zugriff auf die ddsCaps-Datenstruktur frei und DDSCAPS_PRIMARYSURFACE
legt fest, dass das eine primäre Surface sein soll.
Der einzige Unterschied ist hier, das wir anstatt der CreateSurface-Methode
die CreateSurfaceFromFile-Methode nehmen. Hiermit laden wir das angegebene Bild
gleich in die Offscreen-Surface. Jetzt sehen wir das Bild aber noch nicht auf
unseren Bildschirm! Dazu müssen wir das Bild erst noch auf die primäre
Surface blitten. Zuerst legen wir aber die RECT-Variablen fest und füllen
diese mit Daten:
Dim rPrimSurf As RECT
Dim rBackSurf As RECT
Call objDX.GetWindowRect(Picture1.hWnd, rPrimSurf)
rBackSurf.Bottom = ddsdBackSurf.lHeight
rBackSurf.Right = ddsdBackSurf.lWidth
Jetzt stellt sich die Frage, wozu wir dieses benötigen. Zum Blitten benötigen
wir eine Angabe zu der Quelle und zum Ziel, sprich: wir müssen den Bereich
definieren, von wo die Daten kommen und wo sie hin sollen. Das Ziel ist ja unsere
Picture-Box.
Um die Größe dieser Picture-Box zu ermitteln, verwenden wir die GetWindowRect-Methode.
Diese Methode schreibt uns die Daten (auf die das Handle verweist) in die rPrimSurf-Variable.
Die Größe der Offscreen-Surface können wir ganz leicht ermitteln,
da wir die Surface durch die CreateSurfaceFromFile-Methode schon mit Daten gefüllt
haben.
Zum Schluss blitten wir das Bild auf die primäre Surface:
Call objPrimSurf.blt(rPrimSurf, objBackSurf, _
rBackSurf,DDBLT_WAIT)
Ich denke, was rPrimSurf und rBackSurf in dieser Blit-Funktion bedeutet, brauche
ich nicht weiter erklären. Zwischen den beiden Variablen vom Typ RECT wird
die Surface angegeben, von der das Bild auf die primäre Surface geblittet
werden soll, und DDBLT_WAIT gibt lediglich an, dass DirectDraw auf die Fertigstellung
des Blitvorgangs warten soll.
Download TutorialBlitten.zip
Das wars! Ich hoffe, ich habe alles einleuchtend erklärt. Wenn ihr Fragen,
Hinweise oder Kritik habt, dann schreibt mir an: JensK@vbpc.de