This chapter is geared to people who understand the code presented in the windows intro.
We are going to make our first DirectX application in this chapter. There is a lot to cover and I will probably miss important information so please send your comments and questions to me.
The first version of DirectX was called the game SDK. Before the game SDK developers were writing games to be run in DOS mode. Windows 95 was made with the hope that programmer's wouldn't have to directly access the hardware, instead they would have windows access the hardware for them. This was far slower than the direct access that DOS had allowed. Games with fancy animation and sound would run slowly on even the fastest of machines. The game SDK was created so that programmers could access hardware more directly and they could use hardware emulation.
I'm writing this chapter on a 150 MHZ Gateway 2000 Solo with 16 MB of RAM. Like most laptops, mine uses a rare video card. The video card does not support several types of emulation. The desktop I use at work is a 100 MHZ Compaq with 16 MB RAM. The two computers have no parts that could be inter-changed. When a game accesses hardware directly it either assumes you have a specific type of computer or spends time detecting your computer's components. If your hardware doesn't support all of the games features the game probably won't even run! Games that were made before the game SDK would only work on 60% of the computers!
As soon as the MS Office people heard about the Game SDK they wanted to know how to use it for their animation and charts. That was when it was realized that the Game SDK wasn't just for games so they named the next version DirectX 2.0. My company makes Medical software and we utilize DirectX for some of our imaging routines.
When you install DirectX on your computer the setup program identifies and remembers what hardware you have. Then when an application makes a DirectX call it checks to see if your hardware will support the call. If your hardware will not support the call DirectX will emulate the hardware.
DirectX can be used by most programming languages but usually DirectX applications are made in C or C++. To use DirectX in a C++ program you must have the DirectX SDK that comes with headers for you to include. The SDK is available for free at Microsoft's web site. DirectX is backwards compatible so code written for the Game SDK can be run in all versions of DirectX.
DirectX
can be a real pain to use your first time, so I'll try to take
you slowly through the process. When you make a DirectX
program you want to make it as an empty Win32 application:
After creating the project immediately goto the Tools menu and
click on options. Then goto the Directories tab. You
will now want to add the directory where your DirectX library
is. In my case the Directory is C:\dxsdk\sdk\lib .
Make sure it is listed on top. When you compile a program
it looks for your headers in the directories listed. It
searches the directories from the first at the top to the last at
the bottom. It uses the first header with the same name it
comes across.
You'll now goto the project menu and then select settings.
On the C/C++ tab take out the _MBCS in the preprocessor
definitions.
On the links tab the object/library modules should be as follows:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
ddraw.lib
The LINK project options
should have the following:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
ddraw.lib /nologo /subsystem:windows
The MIDL project options
should be the following:
/nologo /D "NDEBUG" /mktyplib203 /o "NUL"
/win32
The sizeof ( ) function, to find the memory size of something use the sizeof ( ) function.
In our first DirectX program we will use Direct Draw. Direct Draw is for drawing none 3D objects to the screen. Direct Draw utilizes surfaces. Surfaces are pictures made to fit your screen. You can have several of these surfaces. The more surfaces you have the more memory you will be using. The primary surface is the surface that is ready to go to the video card. If you programmed Directly to the video card tearing can occur. Tearing is when you have an animation but part of it hasn't loaded so the image on the screen looks torn.
To blit or not to blit. Sending an image to the screen is called a blit. To avoid tearing, you will want to blit when your surface is ready. If your surface is still loading wait, until it's finished.
The Blt( ) function draws to a surface. The BltFast draws on top of a surface and will omit colors from your bitmap.
DirectDrawCreate( NULL, &pointer, NULL ) is used to create the Direct Draw object. The & operator passes the type passed, instead of the pointer.
lpDD->SetCooperativeLevel( hwnd, Attribute1 | Attribute2 ) is used to decide if you will share the DirectX objects with other programs. If you pass DDSCL_EXCLUSIVE then your program asks windows for exclusive rights to the objects. If windows says "no, your not worthy," you should either try for another mode or close the application.
lpDD->SetDisplayMode( 640, 480, 32 ) Sets the screen size and palette. The first number is the number of pixels across, the second number is the number of pixels down and the last number is the number of bits for the palette. If their video card can't support that mode the function will return FALSE. Then you can try another mode like 640 X 480 X 24.
Virtual key codes are
used to say what keys are pressed. Here are all the virtual
key codes that I know of:
CHAR_UNDEFINED
A flag for KEY_PRESSED and KEY_RELEASED events, which do not map
to a valid Unicode character.
KEY_EVENT_BASE
The base identifier for all UIKeyEvent events.
KEY_PRESSED
The key pressed event type.
KEY_RELEASED
The key released event type.
KEY_TYPED
The key typed event type, which is generated by a combination of
a key press followed by a key release.
VK_0
VK_0 through VK_9 are the same as ASCII "0" through
"9" (0x30 - 0x39).
VK_1
A virtual key code for the ASCII "1" key.
VK_2
A virtual key code for the ASCII "2" key.
VK_3
A virtual key code for the ASCII "3" key.
VK_4
A virtual key code for the ASCII "4" key.
VK_5
A virtual key code for the ASCII "5" key.
VK_6
A virtual key code for the ASCII "6" key.
VK_7
A virtual key code for the ASCII "7" key.
VK_8
A virtual key code for the ASCII "8" key.
VK_9
A virtual key code for the ASCII "9" key.
VK_A
VK_A through VK_Z are the same as ASCII "A" through
"Z" (0x41 - 0x5A).
VK_ACCEPT
For Asian keyboards.
VK_ADD
A virtual key code for the numeric keypad PLUS SIGN (+) key.
VK_ALT
A virtual key code for the ALT key.
VK_B
A virtual key code for the ASCII "B" key.
VK_BACK_QUOTE
A virtual key code for the apostrophe (`) key.
VK_BACK_SLASH
A virtual key code for the BACKSLASH (\) key.
VK_BACK_SPACE
A virtual key code for the BACKSPACE key.
VK_C
A virtual key code for the ASCII "C" key.
VK_CANCEL
A virtual key code for the CANCEL key.
VK_CAPS_LOCK
A virtual key code for the CAPS LOCK key.
VK_CLEAR
A virtual key code for the CLEAR key.
VK_CLOSE_BRACKET
A virtual key code for the CLOSE BRACKET (]) key.
VK_COMMA
A virtual key code for the COMMA (,) key.
VK_CONTROL
A virtual key code for the CTRL key.
VK_CONVERT
For Asian keyboards.
VK_D
A virtual key code for the ASCII "D" key.
VK_DECIMAL
A virtual key code for the numeric keypad DECIMAL POINT (.) key.
VK_DELETE
A virtual key code for the DELETE key.
VK_DIVIDE
A virtual key code for the numeric keypad DIVISION (/) key.
VK_DOWN
A virtual key code for the DOWN ARROW key.
VK_E
A virtual key code for the ASCII "E" key.
VK_END
A virtual key code for the END key.
VK_ENTER
A virtual key code for the ENTER key.
VK_EQUALS
A virtual key code for the EQUAL SIGN (=) key.
VK_ESCAPE
A virtual key code for the ESC key.
VK_F
A virtual key code for the ASCII "F" key.
VK_F1
A virtual key code for the F1 key.
VK_F10
A virtual key code for the F10 key.
VK_F11
A virtual key code for the F11 key.
VK_F12
A virtual key code for the F12 key.
VK_F2
A virtual key code for the F2 key.
VK_F3
A virtual key code for the F3 key.
VK_F4
A virtual key code for the F4 key.
VK_F5
A virtual key code for the F5 key.
VK_F6
A virtual key code for the F6 key.
VK_F7
A virtual key code for the F7 key.
VK_F8
A virtual key code for the F8 key.
VK_F9
A virtual key code for the F9 key.
VK_FINAL
For Asian keyboards.
VK_G
A virtual key code for the ASCII "G" key.
VK_H
A virtual key code for the ASCII "H" key.
VK_HELP
A virtual key code for the HELP key.
VK_HOME
A virtual key code for the HOME key.
VK_I
A virtual key code for the ASCII "I" key.
VK_INSERT
A virtual key code for the INSERT key.
VK_J
A virtual key code for the ASCII "J" key.
VK_K
A virtual key code for the ASCII "K" key.
VK_KANA
For Asian keyboards.
VK_KANJI
For Asian keyboards.
VK_L
A virtual key code for the ASCII "L" key.
VK_LEFT
A virtual key code for the LEFT ARROW key.
VK_M
A virtual key code for the ASCII "M" key.
VK_META
A virtual key code for the Application key (found on Microsoft®
Windows® 95 keyboards).
VK_MODECHANGE
For Asian keyboards.
VK_MULTIPLY
A virtual key code for the numeric keypad MULTIPLICATION (*) key.
VK_N
A virtual key code for the ASCII "N" key.
VK_NONCONVERT
For Asian keyboards.
VK_NUM_LOCK
A virtual key code for the NUM LOCK key.
VK_NUMPAD0
A virtual key code for the numeric keypad "0" key.
VK_NUMPAD1
A virtual key code for the numeric keypad "1" key.
VK_NUMPAD2
A virtual key code for the numeric keypad "2" key.
VK_NUMPAD3
A virtual key code for the numeric keypad "3" key.
VK_NUMPAD4
A virtual key code for the numeric keypad "4" key.
VK_NUMPAD5
A virtual key code for the numeric keypad "5" key.
VK_NUMPAD6
A virtual key code for the numeric keypad "6" key.
VK_NUMPAD7
A virtual key code for the numeric keypad "7" key.
VK_NUMPAD8
A virtual key code for the numeric keypad "8" key.
VK_NUMPAD9
A virtual key code for the numeric keypad "9" key.
VK_O
A virtual key code for the ASCII "O" key.
VK_OPEN_BRACKET
A virtual key code for the OPEN BRACKET ([) key.
VK_P
A virtual key code for the ASCII "P" key.
VK_PAGE_DOWN
A virtual key code for the PAGE DOWN key.
VK_PAGE_UP
A virtual key code for the PAGE UP key.
VK_PAUSE
A virtual key code for the PAUSE (BREAK) key.
VK_PERIOD
A virtual key code for the PERIOD (.) key.
VK_PRINTSCREEN
A virtual key code for the PRINT SCREEN key.
VK_Q
A virtual key code for the ASCII "Q" key.
VK_QUOTE
A virtual key code for the QUOTATION MARK key.
VK_R
A virtual key code for the ASCII "R" key.
VK_RIGHT
A virtual key code for the RIGHT ARROW key.
VK_S
A virtual key code for the ASCII "S" key.
VK_SCROLL_LOCK
A virtual key code for the SCROLL LOCK key.
VK_SEMICOLON
A virtual key code for the SEMICOLON (;) key.
VK_SEPARATER
VK_SHIFT
A virtual key code for the SHIFT key.
VK_SLASH
A virtual key code for the forward slash (/) key.
VK_SPACE
A virtual key code for the SPACEBAR key.
VK_SUBTRACT
A virtual key code for the numeric keypad MINUS SIGN (-) key.
VK_T
A virtual key code for the ASCII "T" key.
VK_TAB
A virtual key code for the TAB key.
VK_U
A virtual key code for the ASCII "U" key.
VK_UNDEFINED
KEY_TYPED events do not have a defined key code.
VK_UP
A virtual key code for the UP ARROW key.
VK_V
A virtual key code for the ASCII "V" key.
VK_W
A virtual key code for the ASCII "W" key.
VK_X
A virtual key code for the ASCII "X" key.
VK_Y
A virtual key code for the ASCII "Y" key.
VK_Z
A virtual key code for the ASCII "Z" key.
If you are debugging your application you can send messages to your debug screen or file by using the OutputDebugString( "Text and escape sequences. \n" ).
Now we
are ready for our first DirectX program:
< Files >
// Main.cpp
// Written by Forest J. Handford
// Copyright (c) 1998
/////////////////////////////////
#define NAME "Main"
#define TITLE "DirectDraw Blitting"
#define
WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h> // For windows messages and API's
#include <ddraw.h> // Direct Draw header
LPDIRECTDRAW
lpDD;
// DirectDraw object
LPDIRECTDRAWSURFACE
lpDDSPrimary; // DirectDraw
primary surface
LPDIRECTDRAWSURFACE
lpDDSOffOne; //
DirectDraw offscreen surface
LPDIRECTDRAWSURFACE
lpDDSOffTwo; //
DirectDraw offscreen surface
LPDIRECTDRAWSURFACE
lpDDSOffThree; // DirectDraw
offscreen surface
bool
DestKey = FALSE; // Destination key capability
DWORD
dwGreen;
// Pure green
DWORD
dwBlue;
// Pure blue
// This is a usefull
function to load pictures
bool LoadImage( LPDIRECTDRAWSURFACE lpDDS, LPSTR szImage )
{
HBITMAP
hbm; //The bitmap
HDC
hdcImage= NULL; //The Device Context Image
HDC
hdcSurf = NULL; //The Device Context Surface
bool
bReturn = FALSE; //The return value
DDSURFACEDESC
ddsd; //DirectDraw's surface description
ZeroMemory( &ddsd, sizeof( ddsd ) ); // Fills a block of
memory with zeros
ddsd.dwSize = sizeof( ddsd );
// Store the memories size
//This
notation allows for failure and can force the program to end
if ( FAILED( lpDDS->GetSurfaceDesc(
&ddsd ) ) )
{
goto Exit;
}
// If the pixel format isn't some flavor of RGB, we can't handle
it.
if ( ( ddsd.ddpfPixelFormat.dwFlags !=
DDPF_RGB ) ||
(
ddsd.ddpfPixelFormat.dwRGBBitCount < 16 ) )
{
// Send a string to a debug window/screen
OutputDebugString(
"Non-palettized RGB mode required.\n" );
goto Exit;
}
// Try loading the image.
hbm = ( HBITMAP )LoadImage( NULL, szImage,
IMAGE_BITMAP, ddsd.dwWidth,
ddsd.dwHeight, LR_LOADFROMFILE | LR_CREATEDIBSECTION );
// Safety
precaution
if ( hbm == NULL )
{
OutputDebugString(
" Couldn't find the resource.\n" );
goto Exit;
}
// Create a Device Context(DC) and select the image into it.
hdcImage = CreateCompatibleDC( NULL );
SelectObject( hdcImage, hbm );
// Get a DC for the surface.
if ( FAILED( lpDDS->GetDC( &hdcSurf
) ) )
{
OutputDebugString(
"Couldn't get a DC.\n" );
goto Exit;
}
// The BitBlt will perform format
conversion as necessary.
if ( BitBlt( hdcSurf, 0, 0, ddsd.dwWidth,
ddsd.dwHeight,
hdcImage, 0, 0,
SRCCOPY ) == FALSE )
{
OutputDebugString(
"Blt failed.\n" );
goto Exit;
}
// Success.
bReturn = TRUE;
Exit:
// Clean up everything.
if ( hdcSurf )
lpDDS->ReleaseDC( hdcSurf );
if ( hdcImage )
DeleteDC( hdcImage
);
if( hbm )
DeleteObject( hbm
);
return bReturn; // return TRUE or FALSE
}
// This returns some
control back to Windows
static void ReleaseObjects( void )
{
if ( lpDD != NULL )
{
if ( lpDDSPrimary
!= NULL )
{
if ( lpDDSOffOne != NULL )
{
lpDDSOffOne->Release();
lpDDSOffOne = NULL;
}
if ( lpDDSOffTwo != NULL )
{
lpDDSOffTwo->Release();
lpDDSOffTwo = NULL;
}
if ( lpDDSOffThree != NULL )
{
lpDDSOffThree->Release();
lpDDSOffThree = NULL;
}
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
lpDD->Release();
lpDD = NULL;
}
}
// This will close
the program if an error occurs
bool Fail( HWND hwnd, char *szMsg )
{
ReleaseObjects();
OutputDebugString( szMsg );
DestroyWindow( hwnd );
return FALSE;
}
long FAR PASCAL
WindowProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
DDBLTFX
ddbltfx; // For blit effects.
DDCOLORKEY
ddckey; // For SetColorKey.
RECT
rcRect; // For shrinking.
// decode the
users input
switch ( message )
{
case WM_SETCURSOR:
SetCursor( NULL ); // Turn off the mouse cursor.
return TRUE;
case WM_KEYDOWN:
switch ( wParam )
{
// End program if user hit's escape
case VK_ESCAPE:
PostMessage( hWnd, WM_CLOSE, 0, 0 );
break;
// This draws our three pictures
case VK_F1:
OutputDebugString( "No color keying...\n" );
// Blit the background with stretching.
lpDDSPrimary->Blt( NULL, lpDDSOffThree, NULL,
DDBLT_WAIT, NULL );
// Blit our sprites without color keys.
lpDDSPrimary->BltFast( 300, 200, lpDDSOffOne, NULL,
DDBLTFAST_WAIT |
DDBLTFAST_SRCCOLORKEY );
lpDDSPrimary->BltFast( 350, 250, lpDDSOffTwo, NULL,
DDBLTFAST_WAIT |
DDBLTFAST_SRCCOLORKEY );
break;
case VK_F2:
OutputDebugString( "Source color keying...\n" );
// Blit the background with stretching.
lpDDSPrimary->Blt( NULL, lpDDSOffThree, NULL,
DDBLT_WAIT, NULL );
// Blit our sprites with source color keys.
lpDDSPrimary->BltFast( 300, 200, lpDDSOffOne, NULL,
DDBLTFAST_WAIT |
DDBLTFAST_SRCCOLORKEY );
lpDDSPrimary->BltFast( 350, 250, lpDDSOffTwo, NULL,
DDBLTFAST_WAIT |
DDBLTFAST_SRCCOLORKEY );
case VK_F3:
if ( ~DestKey )
{
OutputDebugString(
"No destination color keying...\n" );
break;
}
OutputDebugString( "Destination color keying...\n" );
// Destination keying is supported, so let's set
// the primary's key.
ddckey.dwColorSpaceLowValue = dwGreen;
ddckey.dwColorSpaceHighValue = dwGreen;
lpDDSPrimary->SetColorKey( DDCKEY_DESTBLT,
&ddckey );
// Use a color fill blit to fill the primary surface with
// the color key.
ZeroMemory( &ddbltfx, sizeof( ddbltfx ) );
ddbltfx.dwSize = sizeof( ddbltfx );
ddbltfx.dwFillColor = dwGreen;
lpDDSPrimary->Blt( NULL, NULL, NULL,
DDBLT_COLORFILL |
DDBLT_WAIT, &ddbltfx );
// Now blit everything in reverse order.
lpDDSPrimary->BltFast( 350, 250, lpDDSOffTwo, NULL,
DDBLTFAST_WAIT |
DDBLTFAST_DESTCOLORKEY );
lpDDSPrimary->BltFast( 300, 200, lpDDSOffOne, NULL,
DDBLTFAST_WAIT |
DDBLTFAST_DESTCOLORKEY );
lpDDSPrimary->Blt( NULL, lpDDSOffThree, NULL,
DDBLT_WAIT | DDBLT_KEYDEST,
NULL );
break;
case VK_F4:
OutputDebugString( "Color fill...\n" );
ZeroMemory( &ddbltfx, sizeof( ddbltfx ) );
ddbltfx.dwSize = sizeof( ddbltfx );
// Fill the surface with blue.
ddbltfx.dwFillColor = dwBlue;
lpDDSPrimary->Blt( NULL, NULL, NULL,
DDBLT_COLORFILL |
DDBLT_WAIT, &ddbltfx );
break;
case VK_F5:
OutputDebugString( "Mirroring about both axis...\n" );
ZeroMemory( &ddbltfx, sizeof( ddbltfx ) );
ddbltfx.dwSize = sizeof( ddbltfx );
ddbltfx.dwDDFX = DDBLTFX_MIRRORLEFTRIGHT |
DDBLTFX_MIRRORUPDOWN;
// Mirror the lake on both axis.
lpDDSPrimary->Blt( NULL, lpDDSOffThree, NULL,
DDBLT_DDFX |DDBLT_WAIT,
&ddbltfx );
break;
case VK_F6:
OutputDebugString( "Shrinking...\n" );
rcRect.left = 0;
rcRect.top = 0;
rcRect.right = 200;
rcRect.bottom = 100;
// Blit the lake with shrinking.
lpDDSPrimary->Blt( &rcRect, lpDDSOffThree, NULL,
DDBLT_WAIT, NULL );
break;
}
break;
case
WM_DESTROY:
ReleaseObjects();
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}
// initialize our
program
static bool doInit( HINSTANCE hInstance, int nCmdShow )
{
HWND
hwnd; // The window
WNDCLASS
wc; // The window class
DDSURFACEDESC ddsd; // The
Direct Draw description
DDCAPS
ddcaps; // This holds info about the users hardware
DDPIXELFORMAT ddpf; // This
holds the pixel format
// Set up and register window class.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance,
IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW
);
wc.hbrBackground = NULL;
wc.lpszMenuName = NAME;
wc.lpszClassName = NAME;
RegisterClass( &wc );
// Create a fullscreen window.
hwnd = CreateWindowEx(
WS_EX_TOPMOST,
NAME,
TITLE,
WS_POPUP,
0, 0,
GetSystemMetrics(
SM_CXSCREEN ),
GetSystemMetrics(
SM_CYSCREEN ),
NULL,
NULL,
hInstance,
NULL );
// Test that
we have a window
if ( !hwnd )
{
return FALSE;
}
// Show our
window
ShowWindow( hwnd, nCmdShow );
UpdateWindow( hwnd );
// Create the DirectDraw object -- we just need an IDirectDraw
// interface so we won't bother to query
an IDirectDraw2.
if ( FAILED( DirectDrawCreate( NULL,
&lpDD, NULL ) ) )
{
return Fail( hwnd, "Couldn't create DirectDraw
object.\n" );
}
// Get
exclusive mode.
if ( FAILED( lpDD->SetCooperativeLevel(
hwnd,
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) ) )
{
return Fail( hwnd, "Couldn't set cooperative
level.\n" );
}
// Set the display mode. An RGB mode is required for this sample.
// Try 32 first; if not 32, then 24; if
not 24, then 16.
if ( FAILED( lpDD->SetDisplayMode( 640, 480, 32 ) )
)
{
if ( FAILED(
lpDD->SetDisplayMode( 640, 480, 24 ) ) )
{
if ( FAILED( lpDD->SetDisplayMode( 640, 480,
16 ) ) )
{
return
Fail( hwnd, "Couldn't set display mode.\n" );
}
}
}
// Check for destination color keying cap bit.
ddcaps.dwSize = sizeof( ddcaps );
if ( FAILED( lpDD->GetCaps(
&ddcaps, NULL ) ) )
{
return Fail( hwnd,
"Couldn't get caps.\n" );
}
if ( ddcaps.dwCKeyCaps |
DDCKEYCAPS_DESTBLT )
{
DestKey = TRUE;
}
// Create the
primary surface.
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps =
DDSCAPS_PRIMARYSURFACE;
// try to create a surface
if ( FAILED( lpDD->CreateSurface( &ddsd,
&lpDDSPrimary, NULL ) ) )
{
return Fail( hwnd, "Couldn't create primary
surface.\n" );
}
// Get the pixel format of the primary and
// use it to create values for pure green
and pure blue.
ddpf.dwSize = sizeof( ddpf );
// try to get
the pixel format
if ( FAILED( lpDDSPrimary->GetPixelFormat( &ddpf
) ) )
{
return Fail( hwnd, "Couldn't get the pixel
format.\n" );
}
dwGreen = ddpf.dwGBitMask;
dwBlue = ddpf.dwBBitMask;
// Create the first off-screen surface.
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |
DDSD_WIDTH | DDSD_CKSRCBLT;
ddsd.ddsCaps.dwCaps =
DDSCAPS_OFFSCREENPLAIN;
ddsd.dwHeight = 100;
ddsd.dwWidth = 100;
// Set the source color key to green.
ddsd.ddckCKSrcBlt.dwColorSpaceLowValue =
dwGreen;
ddsd.ddckCKSrcBlt.dwColorSpaceHighValue =
dwGreen;
if ( FAILED( lpDD->CreateSurface( &ddsd, &lpDDSOffOne,
NULL ) ) )
{
return Fail( hwnd, "Couldn't create off-screen
one.\n" );
}
// Create the second offscreen surface using the surface
// description already set up for the
first surface.
if ( FAILED( lpDD->CreateSurface(
&ddsd, &lpDDSOffTwo, NULL ) ) )
{
return Fail( hwnd, "Couldn't create offscreen
two.\n" );
}
// Create the third offscreen surface.
ddsd.dwHeight = 256;
ddsd.dwWidth = 256;
if ( FAILED( lpDD->CreateSurface(
&ddsd, &lpDDSOffThree, NULL ) ) )
{
return Fail( hwnd, "Couldn't create offscreen
three.\n" );
}
// Load our images.
if ( !LoadImage( lpDDSOffOne,
"redcirq.bmp" ) )
{
return Fail( hwnd,
"Couldn't load offscreen one.\n" );
}
if ( !LoadImage( lpDDSOffTwo, "bluesq.bmp" ) )
{
return Fail( hwnd,
"Couldn't load offscreen two.\n" );
}
if ( !LoadImage( lpDDSOffThree, "lake.bmp" ) )
{
return Fail( hwnd,
"Couldn't load offscreen three.\n" );
}
return TRUE;
}
// Our main
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE
hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; //
Windows message
lpCmdLine = lpCmdLine;
hPrevInstance = hPrevInstance;
if ( !doInit( hInstance, nCmdShow ) )
{
return FALSE;
}
// when we
have messages gat and translate them
while ( GetMessage( &msg, NULL, 0, 0 )
)
{
TranslateMessage(
&msg );
DispatchMessage(
&msg );
}
return msg.wParam;
}
DirectX Intro - I think that we have done enough for this chapter. In the next chapter you'll learn more about Direct Draw.