Using DirectDraw 7

 

To draw, first you must create a surface to draw on.

 

Surfaces

·       a surface can be any size

o      primary is same as the current screen resolution

o      you must have a primary surface

·       can be in video or system memory

·       all surfaces have the same bit depth & color space

 

Create a primary surface

    CreateSurface(<surfaceDesc ptr>, <surface ptr>, NULL);

 

Surface descriptor

   typedef struct _DDSURFACEDESC2

   { DWORD dwSize;     // structure size, you must set

      DWORD dwFlags;   //valid field flags

      DWORD dwHeight; // surface height in pixels

      DWORD dwWidth;  // surface width

      union

      { LONG     lPitch;              // # bytes per row

         DWORD dwLinearSize; //unused

      }

      DWORD dwBackBufferCount; // # of backBuffers

     

      lpVoid lpSurface; // ptr to surface memory

      DDCOLORKEY ddckCKDestBlt;   // dest color key

      DDCOLORKEY ddckCKSrctBlt;   // source color key     

      DDSCAPS ddsCaps; // capabilities structure

   } DDSURFACEDESC;

 

sets which fiels are valid

dwFlag Value

Meaning

DDSD_ALL

all members valid

DDSD_ALPHABITDEPTH

 

DDSD_BACKBUFFERCOUNT

 

DDSD_CAPS

 

DDSD_CKDESTBLT

 

DDSD_CKDESTOVERLAY

 

DDSD_CKSRCBLT

 

DDSD_CKSRCOVERLAY

 

DDSD_HEIGHT

 

DDSD_LINEARSIZE

 

DDSD_LPSURFACE

 

DDSD_LPSURFACE

 

DDSD_MIPMAPCOUNT

 

DDSD_PITCH

 

DDSD_PIXELFORMAT

 

DDSD_REFRESHRATE

 

DDSD_WIDTH

 

DDSD_ZBUFFERBITDEPTH

 

 


 

typedef struct _DDSCAPS

{ DWORD wdCaps; // surface capabilities

} DDSCAPS, FAR* LPDDSCAPS;

 

DDSCAPS value

Meaning

DDSCAPS_BACKBUFFER

backbuff in flip chain

DDSCAPS_COMPLEX

part of multi surface

DDSCAPS_FLIP

flippable surface

DDSCAPS_FRONTBUFFER

first (front) buff in flappable

DDSCAPS_MODEX

modeX = 320X200/240

DDSCAPS_OFFSCREENPLAIN

sprite, bitmap or other offscreen

DDSCAPS_OWNDC

will hold DC for a long time

DDSCAPS_PRIMARYSURFACE

primary surface

DDSCAPS_STANDARDVGAMODE

VGA mode surface

DDSCAPS_SYSTEMMEMORY

allocated in sys memory

 

Drawing a pixel at (x,y)

// plot a pixel on a screen

ddsd.lpSurface[x + y*dds.lpPitch] = color; // color index or RGB

 

Example of use:

// DEMO6_1.CPP basic DirectDraw initialization demo

// INCLUDES ///////////////////////////////////////////////

 

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#define INITGUID // make sure directX guids are included

 

#include <windows.h>   // include important windows stuff

#include <windowsx.h>

#include <mmsystem.h>

#include <iostream.h> // include important C/C++ stuff

#include <conio.h>

#include <stdlib.h>

#include <malloc.h>

#include <memory.h>

#include <string.h>

#include <stdarg.h>

#include <stdio.h>

#include <math.h>

#include <io.h>

#include <fcntl.h>

 

#include <ddraw.h> // include directdraw

 

// DEFINES ////////////////////////////////////////////////

 

// defines for windows

#define WINDOW_CLASS_NAME "WINCLASS1"

 

// default screen size

#define SCREEN_WIDTH    640  // size of screen

#define SCREEN_HEIGHT   480

#define SCREEN_BPP      8    // bits per pixel

#define MAX_COLORS      256  // maximum colors

 

// TYPES //////////////////////////////////////////////////////

 

// basic unsigned types

typedef unsigned short USHORT;

typedef unsigned short WORD;

typedef unsigned char  UCHAR;

typedef unsigned char  BYTE;

 

// MACROS /////////////////////////////////////////////////

 

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

 

// initializes a direct draw struct

#define DD_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }

 

// GLOBALS ////////////////////////////////////////////////

HWND      main_window_handle = NULL; // globally track main window

HINSTANCE hinstance_app      = NULL; // globally track hinstance

 

// directdraw stuff

 

LPDIRECTDRAW7         lpdd         = NULL;   // dd object

LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface

LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface

LPDIRECTDRAWPALETTE   lpddpal      = NULL;   // a pointer to the created dd palette

LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   // dd clipper

PALETTEENTRY          palette[256];          // color palette

PALETTEENTRY          save_palette[256];     // used to save palettes

DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct

DDBLTFX               ddbltfx;               // used to fill

DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct

HRESULT               ddrval;                // result back from dd calls

DWORD                 start_clock_count = 0; // used for timing

 

// these defined the general clipping rectangle

int min_clip_x = 0,                          // clipping rectangle

    max_clip_x = SCREEN_WIDTH-1,

    min_clip_y = 0,

    max_clip_y = SCREEN_HEIGHT-1;

 

// these are overwritten globally by DD_Init()

int screen_width  = SCREEN_WIDTH,            // width of screen

    screen_height = SCREEN_HEIGHT,           // height of screen

    screen_bpp    = SCREEN_BPP;              // bits per pixel

 

 

char buffer[80];                     // general printing buffer

 

// FUNCTIONS //////////////////////////////////////////////

LRESULT CALLBACK WindowProc(HWND hwnd,

                                        UINT msg,

                            WPARAM wparam,

                            LPARAM lparam)

{

// this is the main message handler of the system

PAINTSTRUCT       ps;         // used in WM_PAINT

HDC                     hdc;  // handle to a device context

char buffer[80];        // used to print strings

 

// what is the message

switch(msg)

      {    

      case WM_CREATE:

        {

            // do initialization stuff here

        // return success

            return(0);

            } break;

  

      case WM_PAINT:

            {

            // simply validate the window

          hdc = BeginPaint(hwnd,&ps);    

       

        // end painting

        EndPaint(hwnd,&ps);

 

        // return success

            return(0);

            } break;

 

      case WM_DESTROY:

            {

 

            // kill the application, this sends a WM_QUIT message

            PostQuitMessage(0);

 

        // return success

            return(0);

            } break;

 

      default:break;

 

    } // end switch

 

// process any messages that we didn't take care of

return (DefWindowProc(hwnd, msg, wparam, lparam));

 

} // end WinProc

 

///////////////////////////////////////////////////////////

 

int Game_Main(void *parms = NULL, int num_parms = 0)

{

// this is the main loop of the game, do all your processing

// here

 

// for now test if user is hitting ESC and send WM_CLOSE

if (KEYDOWN(VK_ESCAPE))

   SendMessage(main_window_handle,WM_CLOSE,0,0);

 

// return success or failure or your own return code here

return(1);

 

} // end Game_Main

 

////////////////////////////////////////////////////////////

 

int Game_Init(void *parms = NULL, int num_parms = 0)

{

// this is called once after the initial window is created and

// before the main event loop is entered, do all your initialization

// here

 

// create IDirectDraw interface 7.0 object and test for error

if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))

   return(0);

 

// set cooperation to normal since this will be a windowed app

lpdd->SetCooperativeLevel(main_window_handle, DDSCL_NORMAL);

 

// return success or failure or your own return code here

return(1);

 

} // end Game_Init

 

/////////////////////////////////////////////////////////////

 

int Game_Shutdown(void *parms = NULL, int num_parms = 0)

{

// this is called after the game is exited and the main event

// loop while is exited, do all you cleanup and shutdown here

 

// simply blow away the IDirectDraw4 interface

if (lpdd)

   {

   lpdd->Release();

   lpdd = NULL;

   } // end if

 

// return success or failure or your own return code here

return(1);

 

} // end Game_Shutdown

 

// WINMAIN ////////////////////////////////////////////////

int WINAPI WinMain(     HINSTANCE hinstance,

                              HINSTANCE hprevinstance,

                              LPSTR lpcmdline,

                              int ncmdshow)

{

 

WNDCLASSEX winclass; // this will hold the class we create

HWND     hwnd;    // generic window handle

MSG            msg;           // generic message

HDC        hdc;      // graphics device context

 

// first fill in the window class stucture

winclass.cbSize         = sizeof(WNDCLASSEX);

winclass.style                = CS_DBLCLKS | CS_OWNDC |

                          CS_HREDRAW | CS_VREDRAW;

winclass.lpfnWndProc    = WindowProc;

winclass.cbClsExtra           = 0;

winclass.cbWndExtra           = 0;

winclass.hInstance            = hinstance;

winclass.hIcon                = LoadIcon(NULL, IDI_APPLICATION);

winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);

winclass.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);

winclass.lpszMenuName   = NULL;

winclass.lpszClassName  = WINDOW_CLASS_NAME;

winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

 

// save hinstance in global

hinstance_app = hinstance;

 

// register the window class

if (!RegisterClassEx(&winclass))

      return(0);

 

// create the window

if (!(hwnd = CreateWindowEx(NULL,                  // extended style

      WINDOW_CLASS_NAME,     // class

      "DirectDraw Initialization Demo", // title

      WS_OVERLAPPEDWINDOW | WS_VISIBLE,

      0,0,    // initial x,y

      400,300,  // initial width, height

      NULL,   // handle to parent

      NULL,   // handle to menu

      hinstance,// instance of this application

      NULL)))     // extra creation parms

return(0);

 

// save main window handle

main_window_handle = hwnd;

 

// initialize game here

Game_Init();

 

// enter main event loop

while(TRUE)

      {

    // test if there is a message in queue, if so get it

      if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))

         {

         // test if this is a quit

       if (msg.message == WM_QUIT)

           break;

     

         // translate any accelerator keys

         TranslateMessage(&msg);

 

         // send the message to the window proc

         DispatchMessage(&msg);

         } // end if

   

       // main game processing goes here

       Game_Main();

      

      } // end while

 

// closedown game here

Game_Shutdown();

 

// return to Windows like this

return(msg.wParam);

 

} // end WinMain

 

///////////////////////////////////////////////////////////