Amazon Honor System Click Here to Pay Learn More

by Forest J. Handford

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.

HOME       NEXT CHAPTER

Amazon Honor System Click Here to Pay Learn More