Guida alla Programmazione di Giochi con le DirectX di David Joffe
Capitolo 3: Un semplice esempio DirectDraw
3.1 Settaggio delle DirectX sotto Visual C/C++
Probabilmente non svilupperò con le DirectX con Watcom o Borland C/C++ o Delphi o VisualBASIC etc; quindi se volete che includa informazioni simili, vi prego di mandarmi più informazioni che potete su come far compilare i programmi DirectX in questi ambienti + troubleshooting etc.
Per prima cosa, le directories devono essere settate in modo che Visual C/C++ possa trovare gli include files e le librerie di DirectX.
Entrate nel tabbed dialog Tools/Options/Directories.
Selezionate "library directories" dall'elenco drop-down, aggiungete la directory delle librerie DX SDK, es. "d:\dxsdk\sdk\lib"
Selezionate "include directories" dall'elenco drop-down, aggiungete la directory degli header files DX SDK, es. "d:\dxsdk\sdk\inc".
Se state autilizzando alcuni header di utilità delle DX, allora aggiungete anche la directory samples\misc, es. "d:\dxsdk\sdk\samples\misc".
Nota: In Visual C/C++ 4.2, la directory degli header file per le DirectX SDK deve essere posizionata *prima* delle directories degli include di default di VC++, in modo che il compilatore cerchi prima nelle directories di DX SDK. Per quello che posso dire, la ragione di questo sta nel fatto che, con VC++ 4.2, erano state incluse alcune DirectX, ma gli header files sembrano essere sorpassati o piuttosto perché non funzionano.
Per usare DirectDraw dovete dirgli in quale file della libreria si trovano le routines DirectDraw. Stessa cosa per le Direct3D. Andate in Build/Settings/Link e, nel box Object/Library modules, aggiungete ddraw.lib per usare le DirectDraw, e d3drm.lib se volete usare la modalità Direct3D Retained. Separatele con degli spazi.
Per prima cosa, ecco uno screenshot della piccola applicazione di esempio simple che ho messo insieme a questo tutorial.
La routine generale per iniziare una applicazione DirectDraw è la seguente:
3.3 Settaggio delle variabili globali: Globals.h e Globals.cpp
Abbiamo bisogno di alcune variabili globali per la nostra applicazione DirectDraw (non devono essere rigorosamente variabili globali, potete anche incapsularle in una classe per esempio. Questà è solo una decisione presa da me per semplicità). Per prima cosa, abbiamo bisogno di una variabile per accedere all'oggetto DirectDraw. Inoltre, ci servirà una variabile booleana per controllare se siamo o meno in modalità full-screen, chiamata bFullScreen. Quindi ci servono due variabili DirectDrawSurface per la primary surface e per la back surface che formano la nostra struttura double-buffered surface-flipping. Per la modalità windowed, avremo bisogno di un aggetto clipper da collegare alla primary surface per impedire a DirectDraw di disegnare fuori dai bordi della finestra. Se utilizzate una modalità a 256 colori, ci vorrà probabilmente una struttura per memorizzare la palette che stiamo usando. Quindi, ciserve un oggetto HWNDper indicare al clipper quali limiti di quale finestra deve clippare. Infine, ci servirà una variabile booleana per iniziare e terminare l'animazione dell'applicazione DirectDraw, una volta che questa è inizializzata. Create una variabile globale per il compito di accedere all'oggetto DirectDraw e una variabile booleana per controllare se siamo o meno in modalità full-screen.
Queste variabili globali, insieme alle funzioni globali, le ho messe in un
file separato chiamato Globals.cpp che aggiungo al mio progetto in Visual
C/C++. Avrebbero potuto essere tutti membri di una classe, ma ho scelto di renderli
globali per un accesso più semplice tra i vari moduli, per separare concettualmente
la parte riguardante le DX dal resto del codice del programma, e per rendere
semplice da utilizzare queste funzioni in applicazioni non-MFC.
LPDIRECTDRAW pDD; // DirectDraw object
LPDIRECTDRAWSURFACE pDDSPrimary; // DirectDraw primary surface
LPDIRECTDRAWSURFACE pDDSBack; // DirectDraw back surface
LPDIRECTDRAWPALETTE pDDPal; // Palette (coming sometime soonish)
LPDIRECTDRAWCLIPPER pClipper; // Clipper for windowed mode
HWND ddWnd; // Handle of window
BOOL bFullScreen; // are we in fullscreen mode?
BOOL bAnimating; // are we animating?
Ho fatto anche una funzione per inizializzare tutte queste variabili:
void InitDirectXGlobals()
{
pDD = NULL;
pDDSPrimary = NULL;
pDDSBack = NULL;
pDDPal = NULL;
pClipper = NULL;
bFullScreen = FALSE;
bAnimating = FALSE;
}
Qui c'è uno schema generale dei miei files Globals.h e Globals.cpp:
Globals.h
#ifndef _GLOBALS_H_ #define _GLOBALS_H_ include <d3drm.h> extern LPDIRECTDRAW pDD; ... extern void InitDirectXGlobals(); ... #endif
Globals.cpp
#include "stdafx.h" #include <ddraw.h> #include <d3drm.h> #include "Globals.h" LPDIRECTDRAW pDD; ... void InitDirectXGlobals() { pDD = NULL; ... }
3.4 Inizializzazione del sistema DirectDraw
Ora ci serve una routine per inizializzare il sistema directdraw. Il sistema
DirectDraw deve essere inizializzato ogni volta che che passate dalla modalità
full-screen alla modalità windowed (penso :) - datemi un po' di tempo).
La chiamata alla funzione DirectDrawCreate è usata per creare
un oggetto DirectDraw.
BOOL InitDDraw()
{
HRESULT hr;
// Create the DirectDraw object
// The first NULL means use the active display driver
// The last parameter must be NULL
hr = DirectDrawCreate(NULL, &pDD, NULL);
if (FAILED(hr)) {
TRACE("Unable to create DDraw object\n");
return FALSE;
}
// The DirectDraw object initialized successfully
return TRUE;
}
3.5 Settaggio della modalità dello schermo
La funzione SetCooperativeLevel è usata per dire al sistema se
vogliamo utilizzare la modalità full-screen o la modalità windowed.
In modalità full-screen, dobbiamo avere un accesso esclusivo alla periferica
DirectDraw, e quindi settare la modalità dello schermo. Per la modalità
windowed, settiamo il cooperative level a normal.
BOOL SetMode() {
HRESULT hr;
if (bFullScreen) {
// Set the "cooperative level" so we can use full-screen mode
hr = pDD->SetCooperativeLevel(AfxGetMainWnd()->GetSafeHwnd(),
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES);
if (FAILED(hr)) {
pDD->Release();
return FALSE;
}
// Set 640x480x256 full-screen mode
hr = pDD->SetDisplayMode(640, 480, 8);
if (FAILED(hr)) {
TRACE("Error setting display mode: %d\n", int(LOWORD(hr)));
pDD->Release();
return FALSE;
}
} else {
// Set DDSCL_NORMAL to use windowed mode
hr = pDD->SetCooperativeLevel(AfxGetMainWnd()->GetSafeHwnd(),
DDSCL_NORMAL);
}
// Success
return TRUE;
}
OK ... ora che abbiamo fatto questo poco di inizializzazione fuori dal comune, bisogna che creiamo una struttura flipping.
Ad ogni modo, abbiamo bisogno di creare una superficie principale che vedranno tutti, e una superficie "posteriore". Tutto viene disegnato sulla superficie posteriore. Quando abbiamo finito di disegnare bisogna rendere visibile ciò che abbiamo disegnato. In modalità full-screen, bisogna solo chiamare una routine, Flip, che cambierà la superficie posteriore corrente nella superficie primaria e viceversa. In modalità windowed, non bisogna effettivamente effettuare il flip delle superfici - copiamo il contenuto del back buffer nel primary buffer, che è quello che c'è nella finestra. In altre parole, effettuiamo un "blit" della superficie posteriore nella superficie primaria.
Comunque, ecco un pezzo di codice che crea le superfici. Ora il codice ignora
la modalità full-screen e provvede solo alla modalità windowed,
ma cambierà. Inoltre, se ci sono errori in questo codice, considerateli
"esercizi" ... :). Naah, scherzo. se ci sono errori, segnalatemelo.
UINT CreatePrimarySurface()
{
DDSURFACEDESC ddsd; // A structure to describe the surface we want
HRESULT hr; // Holds return values for function calls
// Screw the full-screen mode (for now)
// This clears all fields of the DDSURFACEDESC structure to 0
memset(&ddsd, 0, sizeof(ddsd));
// The first parameter of the structure must contain the
// size of the structure.
ddsd.dwSize = sizeof(ddsd);
// The dwFlags paramater tell DirectDraw which DDSURFACEDESC
// fields will contain valid values
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// Create the primary surface
hr = pDD->CreateSurface(&ddsd, &pDDSPrimary, NULL);
if (FAILED(hr))
{
TRACE("Error: pDD->CreateSurface (primary)\n");
TraceErrorDD(hr);
pDD->Release();
pDD = NULL;
return 1;
}
// Now to create the back buffer
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
// Make our off-screen surface 320x240
ddsd.dwWidth = 320;
ddsd.dwHeight = 240;
// Ignore this: I'm trying stuff still
/*memset(&ddsd.ddpfPixelFormat, 0, sizeof(ddsd.ddpfPixelFormat));
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8;
// ddsd.ddpfPixelFormat.dwRGBBitCount = 8;*/
// Create an offscreen surface
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
hr = pDD->CreateSurface(&ddsd, &pDDSBack, NULL);
if (FAILED(hr)) {
TRACE("Error: CreateSurface (back)\n");
TraceErrorDD(hr);
return 2;
}
// success
return 0;
}
Adesso che abbiamo creato le superfici, abbiamo bisogno di creare un clipper
(se siamo in modalità windowed), e di collegarlo alla superficie primaria.
Questo impedisce a DirectDraw di disegnare fuori dai limiti dell'area della
finestra client.
UINT CreateClipper()
{
HRESULT hr;
// Create the clipper using the DirectDraw object
hr = pDD->CreateClipper(0, &pClipper, NULL);
if (FAILED(hr)) {
TRACE("Error: CreateClipper\n");
TraceErrorDD(hr);
return 1;
}
// Assign your window's HWND to the clipper
ddWnd = AfxGetMainWnd()->GetSafeHwnd();
hr = pClipper->SetHWnd(0, ddWnd);
if (FAILED(hr)) {
TRACE("Error: SetHWnd\n");
TraceErrorDD(hr);
return 2;
}
// Attach the clipper to the primary surface
hr = pDDSPrimary->SetClipper(pClipper);
if (FAILED(hr)) {
TRACE("Error: SetClipper\n");
TraceErrorDD(hr);
return 3;
}
// success
return 0;
}
Ora che abbiamo tutte queste routines di inizializzazione, dobbiamoi chiamarle,
quindi la domanda è: dove chiamarle? In una applicazione MFC, un posto
logico dove chiamarle nella routine InitInstance dell'applicazione.
BOOL CDirectDrawApp::InitInstance()
{
#ifdef _AFXDLL
Enable3dControls();
#else
Enable3dControlsStatic();
#endif
LoadStdProfileSettings(0);
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CDirectDrawDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CDirectDrawView));
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
InitDirectXGlobals();
InitDDraw();
SetMode();
// These will be coming soonish
// TRACE("Calling LoadJascPalette\n");
// LoadJascPalette("inspect.pal", 10, 240);
TRACE("Calling CreatePrimarySurface\n");
CreatePrimarySurface();
TRACE("Calling CreateClipper\n");
CreateClipper();
// Also coming soonish
// TRACE("Calling AttachPalette\n");
// AttachPalette(pDDPal);
// Start the animation
bAnimating = TRUE;
return TRUE;
}
3.9 Ripristino delle superfici perse
Come se tutte queste inizializzazioni non bastassero, dobbiamo anche assicurarci che le nostre superfici DirectDrawnon vadano "perse". La memoria associata alle superfici DirectDraw può venire liberata in alcune circostanze, perché deve condividere le risorse con la GDI di Windows. Quindi ogni volta che renderizziamo, dobbiamo prima controllare se le nostre superfici sono andate perse, ed effettuare un Restore se ce n'è bisogno. Questo viene compiuto dalla funzione IsLost.
// Checks if the memory associated with surfaces // is lost and restores if necessary. // Not sure about fullscreen/windowed; // I'll get back to you people on this :) BOOL CheckSurfaces() { // Check the primary surface if (pDDSPrimary) { if (pDDSPrimary->IsLost() == DDERR_SURFACELOST) { pDDSPrimary->Restore(); return FALSE; } } return TRUE; }
Ora che abbiamo fatto la maggior parte delle inizializzazioni, dobbiamo organizzare un loop per il rendering. E' essenzialmente il loop principale del gioco, la funzione cosiddetta HeartBeat. Quindi la chiameremo semplicemente così.
La funzione HeartBeat va chiamata durante il periodo di inattività (idle-time processing) dei processi delle vostre applicazioni; quindi ci serve di imporre a mano la funzione OnIdle dell'applicazione. Usate ClassWizard o il toolbar wizard per creare un handler per idle-time processing per la vostra main application class. Qui suppongo che sappiate qualcosa di MFC. Mi scuso per questo; questo probabilmente cambierà col passare del tempo, quando aumenteranno le mie conoscenze e quando avrò più tempo per lavorarci su.
Notate che l'handler OnIdle delle vostre applicazioni viene chiamato
anche quando il vostro programma non ha il focus corrente, e noi non vogliamo
che la nostra applicazione faccia qualcosa se non ha il focus. Fidatevi di me
su questo :). Quindi utilizziamo allo scopo bAnimating; lo setteremo
a FALSE quando riceveremo un messaggio WM_ACTIVATE(APP?) con parametro
FALSE. Lo setteremo a TRUE solo dopo aver settato DirectDraw, le superfici,
etc., e saremo pronti per iniziare.
BOOL CDirectDrawApp::OnIdle(LONG lCount)
{
CWinApp::OnIdle(lCount); // Call the previous default handler
if (bAnimating) {
// Our game's heartbeat function
HeartBeat();
// prevent's too much flicker. We'll need a smarter system
// soon, this one is temporary
Sleep(50);
}
// request more idle-time, so that we can render the next loop!
return TRUE;
}
Ora osserviamo la funzione heartbeat. Per il momento, la mia disegna semplicemente
uno stupido blocco in alto a sinistra nella finestra, che cambia colore ad ogni
frame.
BOOL CDirectDrawApp::HeartBeat()
{
// Variables for the blocks color, in RGB format
static r = 0;
static g = 100;
static b = 150;
r++;
g += 3;
b += 2;
if (r > 255) r = 0;
if (g > 255) g = 0;
if (b > 255) b = 0;
// The destination rectangle on my 320x240 off-screen surface
CRect rc(10,30,100,70);
// We draw the rectangle using a blit.
// This structure describes how to do the blit.
DDBLTFX fx;
// Zero out all fields of the blit effects structure
memset(&fx, 0, sizeof(fx));
// The dwSize field must contain the size of the structure
fx.dwSize = sizeof(DDBLTFX);
// Set the color we want to draw the rectangle
fx.dwFillColor = RGB(r,g,b);
// Blit. Note that we blit to the back buffer
HRESULT hr;
hr = pDDSBack->Blt(&rc, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT,
&fx);
if (FAILED(hr)) {
TRACE("Error blitting: ");
TraceErrorDD(hr);
return FALSE;
}
// Call our routine for flipping the surfaces
FlipSurfaces();
// No major errors
return TRUE;
}
Notare il parametro Blt DDBLT_WAIT. Se una superficie è occupata
allora DirectDraw restituirà un errore, senza effettuare il blit. Passare
l'opzione DDBLT_WAIT istruirà DirectDraw ad aspettare finché
la superficie sarà disponibile e quindi effettuare il blit.
Osserviamo adesso la funzione che effettua il flipping della superficie. Questa
volta *farò* prendere in considerazione una modalità full-screen...
mi contraddico, eh? :-).
UINT FlipSurfaces()
{
HRESULT hr;
// source and destination rectangles
RECT rcSrc;
RECT rcDest;
POINT p;
// Make sure no surfaces have been lost
CheckSurfaces();
// if we're windowed do the blit, else just Flip
if (!bFullScreen)
{
// find out where on the primary surface our window lives
p.x = 0; p.y = 0;
::ClientToScreen(ddWnd, &p);
::GetClientRect(ddWnd, &rcDest);
OffsetRect(&rcDest, p.x, p.y);
SetRect(&rcSrc, 0, 0, 320, 240);
hr = pDDSPrimary->Blt(&rcDest, pDDSBack, &rcSrc, DDBLT_WAIT,
NULL);
} else {
hr = pDDSPrimary->Flip(NULL, DDFLIP_WAIT);
}
// success!
return 0;
}
3.13 Controllo degli errori DirectDraw
Esiste una utilissima funzione di debugging per applicazioni DirectX, chiamata
TraceErrorDD:
void TraceErrorDD(HRESULT hErr)
{
switch (hErr)
{
case DDERR_ALREADYINITIALIZED:
TRACE("DDERR_ALREADYINITIALIZED"); break;
case DDERR_CANNOTATTACHSURFACE:
TRACE("DDERR_CANNOTATTACHSURFACE"); break;
case DDERR_CANNOTDETACHSURFACE:
TRACE("DDERR_CANNOTDETACHSURFACE"); break;
case DDERR_CURRENTLYNOTAVAIL:
TRACE("DDERR_CURRENTLYNOTAVAIL"); break;
case DDERR_EXCEPTION:
TRACE("DDERR_EXCEPTION"); break;
case DDERR_GENERIC:
TRACE("DDERR_GENERIC"); break;
case DDERR_HEIGHTALIGN:
TRACE("DDERR_HEIGHTALIGN"); break;
case DDERR_INCOMPATIBLEPRIMARY:
TRACE("DDERR_INCOMPATIBLEPRIMARY"); break;
case DDERR_INVALIDCAPS:
TRACE("DDERR_INVALIDCAPS"); break;
case DDERR_INVALIDCLIPLIST:
TRACE("DDERR_INVALIDCLIPLIST"); break;
case DDERR_INVALIDMODE:
TRACE("DDERR_INVALIDMODE"); break;
case DDERR_INVALIDOBJECT:
TRACE("DDERR_INVALIDOBJECT"); break;
case DDERR_INVALIDPARAMS:
TRACE("DDERR_INVALIDPARAMS"); break;
case DDERR_INVALIDPIXELFORMAT:
TRACE("DDERR_INVALIDPIXELFORMAT"); break;
case DDERR_INVALIDRECT:
TRACE("DDERR_INVALIDRECT"); break;
case DDERR_LOCKEDSURFACES:
TRACE("DDERR_LOCKEDSURFACES"); break;
case DDERR_NO3D:
TRACE("DDERR_NO3D"); break;
case DDERR_NOALPHAHW:
TRACE("DDERR_NOALPHAHW"); break;
case DDERR_NOCLIPLIST:
TRACE("DDERR_NOCLIPLIST"); break;
case DDERR_NOCOLORCONVHW:
TRACE("DDERR_NOCOLORCONVHW"); break;
case DDERR_NOCOOPERATIVELEVELSET:
TRACE("DDERR_NOCOOPERATIVELEVELSET"); break;
case DDERR_NOCOLORKEY:
TRACE("DDERR_NOCOLORKEY"); break;
case DDERR_NOCOLORKEYHW:
TRACE("DDERR_NOCOLORKEYHW"); break;
case DDERR_NODIRECTDRAWSUPPORT:
TRACE("DDERR_NODIRECTDRAWSUPPORT"); break;
case DDERR_NOEXCLUSIVEMODE:
TRACE("DDERR_NOEXCLUSIVEMODE"); break;
case DDERR_NOFLIPHW:
TRACE("DDERR_NOFLIPHW"); break;
case DDERR_NOGDI:
TRACE("DDERR_NOGDI"); break;
case DDERR_NOMIRRORHW:
TRACE("DDERR_NOMIRRORHW"); break;
case DDERR_NOTFOUND:
TRACE("DDERR_NOTFOUND"); break;
case DDERR_NOOVERLAYHW:
TRACE("DDERR_NOOVERLAYHW"); break;
case DDERR_NORASTEROPHW:
TRACE("DDERR_NORASTEROPHW"); break;
case DDERR_NOROTATIONHW:
TRACE("DDERR_NOROTATIONHW"); break;
case DDERR_NOSTRETCHHW:
TRACE("DDERR_NOSTRETCHHW"); break;
case DDERR_NOT4BITCOLOR:
TRACE("DDERR_NOT4BITCOLOR"); break;
case DDERR_NOT4BITCOLORINDEX:
TRACE("DDERR_NOT4BITCOLORINDEX"); break;
case DDERR_NOT8BITCOLOR:
TRACE("DDERR_NOT8BITCOLOR"); break;
case DDERR_NOTEXTUREHW:
TRACE("DDERR_NOTEXTUREHW"); break;
case DDERR_NOVSYNCHW:
TRACE("DDERR_NOVSYNCHW"); break;
case DDERR_NOZBUFFERHW:
TRACE("DDERR_NOZBUFFERHW"); break;
case DDERR_NOZOVERLAYHW:
TRACE("DDERR_NOZOVERLAYHW"); break;
case DDERR_OUTOFCAPS:
TRACE("DDERR_OUTOFCAPS"); break;
case DDERR_OUTOFMEMORY:
TRACE("DDERR_OUTOFMEMORY"); break;
case DDERR_OUTOFVIDEOMEMORY:
TRACE("DDERR_OUTOFVIDEOMEMORY"); break;
case DDERR_OVERLAYCANTCLIP:
TRACE("DDERR_OVERLAYCANTCLIP"); break;
case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
TRACE("DDERR_OVERLAYCOLORKEYONLYONEACTIVE"); break;
case DDERR_PALETTEBUSY:
TRACE("DDERR_PALETTEBUSY"); break;
case DDERR_COLORKEYNOTSET:
TRACE("DDERR_COLORKEYNOTSET"); break;
case DDERR_SURFACEALREADYATTACHED:
TRACE("DDERR_SURFACEALREADYATTACHED"); break;
case DDERR_SURFACEALREADYDEPENDENT:
TRACE("DDERR_SURFACEALREADYDEPENDENT"); break;
case DDERR_SURFACEBUSY:
TRACE("DDERR_SURFACEBUSY"); break;
case DDERR_CANTLOCKSURFACE:
TRACE("DDERR_CANTLOCKSURFACE"); break;
case DDERR_SURFACEISOBSCURED:
TRACE("DDERR_SURFACEISOBSCURED"); break;
case DDERR_SURFACELOST:
TRACE("DDERR_SURFACELOST"); break;
case DDERR_SURFACENOTATTACHED:
TRACE("DDERR_SURFACENOTATTACHED"); break;
case DDERR_TOOBIGHEIGHT:
TRACE("DDERR_TOOBIGHEIGHT"); break;
case DDERR_TOOBIGSIZE:
TRACE("DDERR_TOOBIGSIZE"); break;
case DDERR_TOOBIGWIDTH:
TRACE("DDERR_TOOBIGWIDTH"); break;
case DDERR_UNSUPPORTED:
TRACE("DDERR_UNSUPPORTED"); break;
case DDERR_UNSUPPORTEDFORMAT:
TRACE("DDERR_UNSUPPORTEDFORMAT"); break;
case DDERR_UNSUPPORTEDMASK:
TRACE("DDERR_UNSUPPORTEDMASK"); break;
case DDERR_VERTICALBLANKINPROGRESS:
TRACE("DDERR_VERTICALBLANKINPROGRESS"); break;
case DDERR_WASSTILLDRAWING:
TRACE("DDERR_WASSTILLDRAWING"); break;
case DDERR_XALIGN:
TRACE("DDERR_XALIGN"); break;
case DDERR_INVALIDDIRECTDRAWGUID:
TRACE("DDERR_INVALIDDIRECTDRAWGUID"); break;
case DDERR_DIRECTDRAWALREADYCREATED:
TRACE("DDERR_DIRECTDRAWALREADYCREATED"); break;
case DDERR_NODIRECTDRAWHW:
TRACE("DDERR_NODIRECTDRAWHW"); break;
case DDERR_PRIMARYSURFACEALREADYEXISTS:
TRACE("DDERR_PRIMARYSURFACEALREADYEXISTS"); break;
case DDERR_NOEMULATION:
TRACE("DDERR_NOEMULATION"); break;
case DDERR_REGIONTOOSMALL:
TRACE("DDERR_REGIONTOOSMALL"); break;
case DDERR_CLIPPERISUSINGHWND:
TRACE("DDERR_CLIPPERISUSINGHWND"); break;
case DDERR_NOCLIPPERATTACHED:
TRACE("DDERR_NOCLIPPERATTACHED"); break;
case DDERR_NOHWND:
TRACE("DDERR_NOHWND"); break;
case DDERR_HWNDSUBCLASSED:
TRACE("DDERR_HWNDSUBCLASSED"); break;
case DDERR_HWNDALREADYSET:
TRACE("DDERR_HWNDALREADYSET"); break;
case DDERR_NOPALETTEATTACHED:
TRACE("DDERR_NOPALETTEATTACHED"); break;
case DDERR_NOPALETTEHW:
TRACE("DDERR_NOPALETTEHW"); break;
case DDERR_BLTFASTCANTCLIP:
TRACE("DDERR_BLTFASTCANTCLIP"); break;
case DDERR_NOBLTHW:
TRACE("DDERR_NOBLTHW"); break;
case DDERR_NODDROPSHW:
TRACE("DDERR_NODDROPSHW"); break;
case DDERR_OVERLAYNOTVISIBLE:
TRACE("DDERR_OVERLAYNOTVISIBLE"); break;
case DDERR_NOOVERLAYDEST:
TRACE("DDERR_NOOVERLAYDEST"); break;
case DDERR_INVALIDPOSITION:
TRACE("DDERR_INVALIDPOSITION"); break;
case DDERR_NOTAOVERLAYSURFACE:
TRACE("DDERR_NOTAOVERLAYSURFACE"); break;
case DDERR_EXCLUSIVEMODEALREADYSET:
TRACE("DDERR_EXCLUSIVEMODEALREADYSET"); break;
case DDERR_NOTFLIPPABLE:
TRACE("DDERR_NOTFLIPPABLE"); break;
case DDERR_CANTDUPLICATE:
TRACE("DDERR_CANTDUPLICATE"); break;
case DDERR_NOTLOCKED:
TRACE("DDERR_NOTLOCKED"); break;
case DDERR_CANTCREATEDC:
TRACE("DDERR_CANTCREATEDC"); break;
case DDERR_NODC:
TRACE("DDERR_NODC"); break;
case DDERR_WRONGMODE:
TRACE("DDERR_WRONGMODE"); break;
case DDERR_IMPLICITLYCREATED:
TRACE("DDERR_IMPLICITLYCREATED"); break;
case DDERR_NOTPALETTIZED:
TRACE("DDERR_NOTPALETTIZED"); break;
case DDERR_UNSUPPORTEDMODE:
TRACE("DDERR_UNSUPPORTEDMODE"); break;
case DDERR_NOMIPMAPHW:
TRACE("DDERR_NOMIPMAPHW"); break;
case DDERR_INVALIDSURFACETYPE:
TRACE("DDERR_INVALIDSURFACETYPE"); break;
case DDERR_DCALREADYCREATED:
TRACE("DDERR_DCALREADYCREATED"); break;
case DDERR_CANTPAGELOCK:
TRACE("DDERR_CANTPAGELOCK"); break;
case DDERR_CANTPAGEUNLOCK:
TRACE("DDERR_CANTPAGEUNLOCK"); break;
case DDERR_NOTPAGELOCKED:
TRACE("DDERR_NOTPAGELOCKED"); break;
case DDERR_NOTINITIALIZED:
TRACE("DDERR_NOTINITIALIZED"); break;
default:
TRACE("Unknown Error"); break;
}
TRACE("\n");
}
A breve.
Articolo aggiornato il: 19 Giugno 1998
Articolo di David Joffe
http://www.geocities.com/SoHo/Lofts/2018/
---
Traduzione: Papero - IPG 1999
Eng?Ita! Team
http://www.ItaProGaming.com