Problem with Offscreen...

F

Fab'

Hello!
Excuse me for my english level because I'm french!
This message is post to : microsoft.public.vb.winapi.graphics,
microsoft.public.vb.general.discussion, microsoft.public.project.vba
My computer confuguration : WinMe, Excel 2000.
I play with the api's gdi to try to create a game engine, I'm a fool, I
know but I want to try this fool project!
A part of the code is in the end on this message.
I create a VBAProject with a form intitulate "G_Screen".
The game displays in this form.
I have a background and a sprite (with differents frames to animate)
which are load in memory.
I use the api "SetTimer" to do a cycle sub to display the animation sprite.
I use a double buffering, but it's strange because I have to paint twice
from offscreen'dc to form'dc if I want to displays the animation. If I
try to draw in once time I see only the sprite but with no transparence!
Help me please!
Thanks!

'------------------------------------
The code of form initialize
'Acquisition des contextes de périphérique graphique
hWndform = GetActiveWindow()
hDCform = GetDC(hWndform)
'Création d'un Offscreen compatible avec la form
hDCOffscreen = CreateCompatibleDC(0&)
hDCOffscreenBmp = CreateCompatibleBitmap(hOffscreenDC, 0, 0)
Call SelectObject(hDCOffscreen, hDCOffscreenBmp)
'Chargement en mémoire du background
hBackgnd = LoadImage(0&, CheminInstall + "Background_sonic.bmp", 0, 0,
0, &H10)
'Chargement en mémoire du sprite
With Sonic
hSprite = LoadImage(0&, CheminInstall + "Sonic_run.bmp", 0, 0, 0, &H10)
End With
Call SetTimer(hWndform, 0, ImagDelai, AddressOf G_Timer)

'------------------------------------
The code of timer procedure :
Sub G_Timer(ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As
Long, ByVal lpTimerFunc As Long)
DoEvents
'Acquisition des contextes de périphérique graphique
'Hwndform = GetActiveWindow()
'Hdcform = GetDC(Hwndform)
'dessin sur l'offscreen du background
Call SelectObject(hOffscreenDC, hBackgnd)
Call BitBlt(hOffscreenDC, 0, 0, 640, 480, hBackgnd, 0, 0, SRCCOPY)
'dessin de l'offscreen du background sur la form
Call BitBlt(Hdcform, 0, 0, G_Screen.Width * 1.33, G_Screen.Height *
1.33, hOffscreenDC, 0, 0, SRCCOPY)
'dessin sur l'offscreen du fantôme avec transparence
Sonic_f = GetPosFrameX(Sonic, False)
Call SelectObject(hOffscreenDC, hSprite)
Call TransparentBlt(hOffscreenDC, 0, 0, 36 * 1.5, 39 * 1.5, hSprite,
Sonic_f, 0, 36, 39, vbWhite)
'dessin de l'offscreen du fantôme sur la form
Call TransparentBlt(Hdcform, t, 100, 36 * 1.5, 39 * 1.5, hOffscreenDC,
Sonic_f, 0, 36, 39, vbWhite)
Call ReleaseDC(Hwndform, Hdcform)
End Sub
 
J

Jan De Messemaeker

Bonjour,

Ceci est le groupe dediscussion au sujet du VBA pour le produit Microsoft
Project.
Sorry, but this is the NG devoted to VBA for Microsoft Project.

Bien à vous, Regards,
 
M

Mike D Sutton

Comments inline
Excuse me for my english level because I'm french!
This message is post to : microsoft.public.vb.winapi.graphics,
microsoft.public.vb.general.discussion, microsoft.public.project.vba
My computer confuguration : WinMe, Excel 2000.
I play with the api's gdi to try to create a game engine, I'm a fool, I
know but I want to try this fool project!
A part of the code is in the end on this message.
I create a VBAProject with a form intitulate "G_Screen".
The game displays in this form.
I have a background and a sprite (with differents frames to animate)
which are load in memory.
I use the api "SetTimer" to do a cycle sub to display the animation sprite.
I use a double buffering, but it's strange because I have to paint twice
from offscreen'dc to form'dc if I want to displays the animation. If I
try to draw in once time I see only the sprite but with no transparence!
hDCOffscreenBmp = CreateCompatibleBitmap(hOffscreenDC, 0, 0)

You're creating your back-buffer Bitmap here with a height and width of 0 so you're returned a 1*1*1 Bitmap which is next to no use
for what you want, instead pass in the width and height of your desired back-buffer here, most likely the same size as your draw
area (form.)
Call SelectObject(hDCOffscreen, hDCOffscreenBmp)

When you select a GDI object into a DC, you must retain the handle you're passed back in order to re-select it into the DC before
it's destroyed i.e:

'***
Dim hOldBMP As Long

hOldBMP = SelectObject(hDCOffscreen, hDCOffscreenBmp)

....

Call SelectObject(hDCOffscreen, hOldBMP)
Call DeleteObject(hDCOffscreenBmp)
Call DeleteDC(hDCOffscreen)
'***
hSprite = LoadImage(0&, CheminInstall + "Sonic_run.bmp", 0, 0, 0, &H10)

The first parameter of your LoadImage() calls should really be your application instance; App.instance in VB.
Also, rather than using cryptic numeric parameters such as &H10, use the constants as it makes for far more readable code (and saves
us having to go look up the value when you post your code to the groups!)

'***
Private Const IMAGE_BITMAP As Long = 0
Private Const LR_LOADFROMFILE As Long = &H10
'***
The code of timer procedure :
Sub G_Timer(ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As
Long, ByVal lpTimerFunc As Long)

You're using some strange parameter names for this callback which again make the code more difficult to follow, try these instead:

'***
Private Sub G_Timer(ByVal hWnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
'***

This function signature was taken from the MSDN page for the TimerProc() function:
http://msdn.microsoft.com/library/e...s/TimerReference/TimerFunctions/TimerProc.asp
Call SelectObject(hOffscreenDC, hBackgnd)

Again when you select the GDI object into the DC, retain the returned handle and re-select it before destroying either the DC or GDI
object.
Call SelectObject(hOffscreenDC, hSprite)

Same again..
Call TransparentBlt(hOffscreenDC, 0, 0, 36 * 1.5, 39 * 1.5, hSprite,
Sonic_f, 0, 36, 39, vbWhite)

Be warned that TransparentBlt() has a known resource leak on older OS', you may want to grab a copy of the ChromaBlt() library off
my page which can be used as a direct replacement for the call and contains no such leak.
Also, remember to call KillTimer() before your application quits - It may be an idea to encapsulate your game logic into a single
class that instantiates the timer when it's created, and kills it when it's terminated.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: (e-mail address removed)
WWW: Http://EDais.mvps.org/
 
C

christophe-pasde

Hello,

Post it in microsoft.public.fr.vb if there's something you don't
understand , but Mike was very clear and give you all the basic rules to
work with GDI.

Christophe


Mike D Sutton a écrit :
 
Top