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
The following example demonstrates setting the cooperative level and switching the display mode. Listing 4-3: Setting the display mode to full screen
    var

      Form1: TForm1;

      FDirectDraw: IDirectDraw4;

    implementation

    procedure TForm1.FormCreate(Sender: TObject);

    begin

      {initialize form properties.  note that the FormStyle property must be

       set to fsStayOnTop}

      BorderStyle := bsNone;

      BorderIcons := [];

      FormStyle   := fsStayOnTop;

    end;

    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;

    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);

    end;
| Note: You’ll notice that the DirectDraw initialization code has been moved to the form’s OnActivate event. We’ve found this is a more appropriate place to put initialization code, and the examples throughout the rest of the book will expound upon the code placed in this method.
The result of this example is a bit surprising. The form itself was still visible, albeit in a full-screen mode, and the mouse cursor was still able to manipulate objects on the form. This is possible because the GDI is still outputting graphical images, and by default the memory area to which the GDI is rendering is still visible when the DirectDraw application sets its display mode. This can be useful when a DirectDraw application needs to start up and display an interface to the user that is easily put together using regular Delphi controls. Page Flipping At this point, we can instantiate DirectDraw and adjust the display hardware’s display mode, but not much else. We still can’t draw anything to the screen, making any sort of animation very difficult. We need to modify our DirectDraw code so it supports the page flipping architecture discussed earlier. In order to accomplish this, we must first create a primary surface and an attached backbuffer surface. Creating Surfaces We will create the primary and backbuffer surfaces simultaneously, creating what is known as a complex surface. A complex surface is one surface with a series of separate surfaces that are implicitly attached to it. These surfaces are arranged in a linear fashion. Typically, page flipping applications create only two surfaces (the primary and one backbuffer). However, some applications may need three or more.
| Note: The primary surface and all backbuffers must reside in video memory. Thus, the number of backbuffers that can be created is dependent upon the size of the surfaces, the color depth, and the available display memory.
The primary surface is always visible to the user. Animation is accomplished by drawing any graphical output to the backbuffer surface, which is offscreen. When the next frame of animation needs to be displayed, the backbuffer surface memory and the primary surface memory change places (or flip). Only the memory referenced by these two objects change; no other attributes or other attached objects are affected. Your BackBuffer object will always point to the backbuffer surface, and your PrimarySurface object will always point to the primary surface. This is illustrated below. Figure 4-4: Page flipping the primary and backbuffer surfaces We can create the primary and backbuffer surfaces by calling the IDirectDraw4 method CreateSurface. The CreateSurface method is defined as:
    function CreateSurface(

    var lpDDSurfaceDesc: TDDSurfaceDesc2;     // a surface description structure

    var lplpDDSurface: IDirectDrawSurface4;   // the IDirectDrawSurface4 object

    pUnkOuter: IUnknown                       // unused, set to nil

    ): HResult;                               // returns a DirectX error code
The first parameter is a data structure that defines the type of surface we wish to create. The second parameter is a pointer to the IDirectDrawSurface4 object that is instantiated by the function. The last parameter is used for COM aggregation and should be set to nil. The TDDSurfaceDesc2 structure is a very complex data structure as we examined above, but for the purposes of this function, we are concerned only with a few members. To begin, we should initialize all members of the surface by calling FillChar(DDSurface, SizeOf(TDDSurfaceDesc2), 0). We need to indicate that we are interested in the capabilities and buffer count members of this structure, so we need to set its dwFlags member to DDSD_CAPS or DDSD_ BACKBUFFERCOUNT (by ORing the values, we combine them). We then must set its ddsCaps.dwCaps member to DDSCAPS_COMPLEX or DDSCAPS_FLIP or DDSCAPS_PRIMARYSURFACE. The DDSCAPS_COMPLEX flag indicates we are creating a complex surface with implicitly attached surfaces, DDSCAPS_FLIP indicates this will be a flipping structure, and DDSCAPS_PRIMARYSURFACE indicates that the root surface in the flipping structure will be the primary surface. We must also set the dwBackBufferCount to indicate how many backbuffers we will need. In our case, we can set this to one. Finally, we must set the dwSize member to SizeOf(TDDSurfaceDesc2).
| Caution: DirectX methods use lots and lots of very complex data structures. These data structures may vary from version to version, and some methods may use only specific members of any particular structure. It is imperative that any data structure with a member denoting its size must have this member initialized by calling SizeOf. Failing to perform these two requirements can lead to failed method calls.
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.