Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
You do not have to indicate a memory location for surfaces. By default, surfaces will be created in video memory. When video memory is depleted, or a surface is too big tofit into what’s left, it is automatically created in system memory. However, if a location is specified in the CreateSurface call and there is not enough memory, it will fail. #### Loading and Displaying the Bitmap Actually loading the bitmap is quite easy. We simply create a TBitmap object and use its LoadFromFile method to pull the bitmap into memory. Of course, we must still somehow copy the bitmap into our off-screen surface. This is where the previous information about GDI comes in. Using GDI, we can retrieve a device context for our off-screen surface and use the GDI BitBlt function to copy the bitmap into the surface itself. Alternatively, we can create another TCanvas object, assign the surface’s device context to the TCanvas’s handle, and use the TCanvas.Draw method to copy the bitmap into the surface. With that accomplished, we can release the surface’s device context and destroy the TBitmap object. This is illustrated in Listing 4-5. #### Blitting Surfaces OK, now that the bitmap has been loaded into our off-screen surface, which should be located in display memory if there was enough room, we need to copy it from the off-screen surface onto our primary surface for display. Usually we would copy it into the backbuffer surface as part of our animation rendering engine, but for this example, we will simply copy it directly to the primary surface. To copy one portion of a surface into another surface, we use the IDirectDrawSurface4’s BltFast method. The BltFast method is defined as:
    function BltFast(

    dwX: DWORD;                           // the destination horizontal coordinate

    dwY: DWORD;                           // the destination vertical coordinate

    lpDDSrcSurface: IDirectDrawSurface4;  // the source surface

    var lpSrcRect: TRect;                 // the rectangular area on the source

    dwTrans: DWORD                        // transfer flags

    ): HResult;                           // returns a DirectX error code
The first two parameters determine the horizontal and vertical coordinates where the source surface area will be copied onto the destination surface. The third parameter is a pointer to the source surface, and the fourth parameter defines the rectangular area in the source surface that is to be copied onto the destination surface. The last parameter contains a series of flags that control certain aspects about the transfer. In particular, the DDBLTFAST_WAIT flag can be specified to indicate that the function should not return until the copying has been accomplished. Other flags indicate transparency options, but these will be covered in the chapter on sprite techniques. If the resulting bitmap looks somewhat corrupted, don’t worry. Our current example makes no use of palettes, and thus the resulting appearance of the bitmap will be at the mercy of the current contents of the system palette. We will examine palettes at length in the next chapter. Listing 4-5: Loading and displaying a bitmap
    var

      Form1: TForm1;

      FDirectDraw: IDirectDraw4;

      FPrimarySurface,

      FBitmap: IDirectDrawSurface4;

    Implementation

    procedure TForm1.FormActivate(Sender: TObject);

    var

      {we can only get a DirectDraw4 interface from the DirectDraw interface, so we

       need a temporary interface}

      TempDirectDraw: IDirectDraw;

      {structures required for various methods}

      DDSurface: TDDSurfaceDesc2;

      {these variables are used in GDI rendering}

      TempCanvas: TCanvas;

      SrfcDC: HDC;

      {the bitmap object}

      TempBitmap: TBitmap;

      {defines the area to be copied}

      SrcRect: TRect;

    begin

      {create a temporary DirectDraw object. this is used to create the

       desired DirectDraw4 object}

      DirectDrawCreate(nil, TempDirectDraw, nil);

      try

        {we can only get a DirectDraw4 interface through the QueryInterface

         method of the DirectDraw object}

        TempDirectDraw.QueryInterface(IID_IDirectDraw4, FDirectDraw);

      finally

        {now that we have the desired DirectDraw object, the temporary DirectDraw

         object is no longer needed}

        TempDirectDraw := nil;

      end;

      {set the cooperative level}

      FDirectDraw.SetCooperativeLevel(Handle, DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE);

      {set the display resolution and color depth}

      FDirectDraw.SetDisplayMode(640, 480, 8, 0, 0);

      {initialize the DDSurface structure to indicate that we will be creating a

       primary surface}

      FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0);

      DDSurface.dwSize  := SizeOf(TDDSurfaceDesc2);

      DDSurface.dwFlags := DDSD_CAPS;

      DDSurface.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;

      {create the primary surface object}

      FDirectDraw.CreateSurface(DDSurface, FPrimarySurface, nil);

      {create a temporary canvas object and retrieve an HDC for the primary

       surface}

      TempCanvas := TCanvas.Create;

      FPrimarySurface.GetDC(SrfcDC);

      try

        {set the canvas’s handle to the surface’s DC}

        TempCanvas.Handle := SrfcDC;

        {clear the surface to black}

        TempCanvas.Brush.Color := clBlack;

        TempCanvas.FillRect(Rect(0, 0, 640, 480));

      finally

        {don’t forget to release the DC}

        TempCanvas.Handle := 0;

        FPrimarySurface.ReleaseDC(SrfcDC);

      end;

      {create the temporary bitmap}

      TempBitmap := TBitmap.Create;

      {load the bitmap}

      TempBitmap.LoadFromFile(ExtractFilePath(ParamStr(0))+’Athena.bmp’);

      {initialize the attributes for the surface}

      FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0);

      DDSurface.dwSize   := SizeOf(TDDSurfaceDesc2);

      DDSurface.dwFlags  := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;

      DDSurface.dwWidth  := TempBitmap.Width;

      DDSurface.dwHeight := TempBitmap.Height;

      DDSurface.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;

      {create the desired DirectDraw surface object}

      FDirectDraw.CreateSurface(DDSurface, FBitmap, nil);

      {retrieve a DC for the bitmap surface}

      FBitmap.GetDC(SrfcDC);

      try

        TempCanvas.Handle := SrfcDC;

        {draw the bitmap onto the surface using GDI functions}

        TempCanvas.Draw(0, 0, TempBitmap);

      finally

        {cleanup}

        TempCanvas.Handle := 0;

        FBitmap.ReleaseDC(SrfcDC);

        TempCanvas.Free;

      end;

      {record the size of the surface (same as the bitmap), as this will be needed

       when we copy the surface into the primary surface}

      SrcRect := Rect(0, 0, TempBitmap.Width, TempBitmap.Height);

      {destroy the bitmap object}

      TempBitmap.Free;

      {blit the off-screen surface onto the primary surface, thus displaying

       the bitmap}

      FPrimarySurface.BltFast(50, 50, FBitmap, SrcRect, DDBLTFAST_WAIT);

    end;

    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;

      Shift: TShiftState);

    begin

      if Key = VK_ESCAPE then

        Close;

    end;
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.