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 first parameter is the address of the function that is called for each enumerated device. The second parameter is a pointer to an application-defined value, such as a pointer to a TList or perhaps just a variable, and can be set to nil if not needed. The last parameter is a series of flags that control the scope of the enumeration. The callback function itself is defined as:
    function TDDEnumCallbackEx(

    lpGUID: PGUID;                     // a pointer to the device GUID

    lpDriverDescription: PAnsiChar;    // the device description

    lpDriverName: PAnsiChar;           // the device name

    lpContext: Pointer;                // the application-specific value

    Monitor: HMonitor                  // a handle to the monitor

    ): BOOL; stdcall;                  // returns TRUE or FALSE
The first three parameters of this function are the most interesting. The lpGUID parameter will contain the GUID for the specific device. This GUID must be stored, as it must be used later for creating the DirectDraw object. The lpDriverDescription and lpDriverName parameters contain the textual description and name of the enumerated device. These can be presented to the user in a list of devices, allowing them to choose the desired display object. The lpContext parameter simply contains the pointer passed to the initial DirectDrawEnumerateEx function. The last parameter will be zero in most cases, and can be ignored. The callback function must return a value of TRUE to continue the enumeration; returning FALSE signals the function to stop enumerating devices. The following example demonstrates enumerating all available display devices. Listing 4-1: Enumerating display devices
    implementation

    uses

      DDraw;

    function EnumDevices(lpGUID: PGUID; lpDriverDescription: PAnsiChar;

          lpDriverName: PAnsiChar; lpContext: Pointer;

          Monitor: HMonitor): BOOL; stdcall;

    begin

      {add the name and description of the enumerated device. here, we would

       need to store the GUID for the device so it would be available when

       the user selected the desired display device}

      TStringList(lpContext).Add(lpDriverName+‘ - ’+lpDriverDescription);

      {continue enumeration}

      Result := TRUE;

    end;

    procedure TForm1.FormCreate(Sender: TObject);

    begin

      {enumerate all attached display devices}

      DirectDrawEnumerateEx(EnumDevices, lbxDevices.Items, 0);

    end;
Figure 4-2: The list of attached display devices Creating the DirectDraw Object The first truly required step in initializing a DirectDraw application is to create the DirectDraw object itself. To create the DirectDraw object, call the DirectDrawCreate function, which is defined as:
    function DirectDrawCreate(

    lpGUID: PGUID;                     // the GUID of the DirectDraw device

    out lplpDD: IDirectDraw;           // the IDirectDraw object to be instantiated

    pUnkOuter: IUnknown                // unused, set to nil

    ): HResult; stdcall;               // returns a DirectX error code
The first parameter takes the GUID of the selected device. It can be set to nil to create a DirectDraw object associated with the primary display device, or it can be set to a GUID as retrieved from device enumeration above. Additionally, it can be set to DDCREATE_HARDWAREONLY or DDCREATE_EMULATIONONLY to only use the HAL or HEL, respectively. This allows the developer to perform testing and debugging against emulated or hardware accelerated features. The second parameter takes a pointer to the IDirectDraw object. When this function returns, this object will be instantiated. The last parameter is used for COM aggregation, and must be set to nil as it is currently unsupported.
| Caution: It is possible to create multiple DirectDraw objects, but this is unadvisable. Each DirectDraw object is independent of the others, and surfaces and other child objects cannot be shared between them.
Now, this function will only return an instantiated IDirectDraw object, but since we are concerned with DirectX 6 functionality, we need to get an instantiated IDirectDraw4 object. Thus, we should create a temporary IDirectDraw object, and once this is instantiated, we can use the QueryInterface method of the object to retrieve an instantiated IDirectDraw4 object. The temporary object can then be released by setting it to nil. We’ll illustrate the creation of an IDirectDraw4 object below.
| Note: Delphi’s AS operator can be used to accomplish the same thing. However, use of the QueryInterface method is a little less abstract.
Enumerating the Supported Display Modes It is typically much harder to create an application that supports multiple display modes. As discussed in the previous chapter, changing display modes modifies the size of graphics as they are displayed on screen, and changes the amount of screen area that must be filled with graphics. This puts an additional requirement on the programmer to determine how graphics will be displayed in different modes (if they are to be scaled, stretched, etc.), and may put additional requirements on artists if they must develop additional graphics to support different resolutions and color depths. However, allowing the user to choose which display mode works best on their system is a good practice, as the user can then tune the game to achieve acceptable speeds. Even if your game will support only one graphic mode, it is useful to determine if the machine supports this mode. Our examples will be concerned with only one specific display mode in order to simplify the code, but we still need to enumerate the available display modes to ensure that the machine can handle the application. Enumerating display modes is similar to enumerating display devices. After the IDirectDraw4 object is created, we can call its EnumDisplayModes method to enumerate all display resolutions and color depths supported by the display driver. The EnumDisplayModes method is defined as:
    function EnumDisplayModes(

    dwFlags: DWORD;                              // scope flags

    lpDDSurfaceDesc: PDDSurfaceDesc2;            // a surface description structure

    lpContext: Pointer;                          // an application-defined value

    lpEnumModesCallback: TDDEnumModesCallback2   // the callback function

    ): HResult;                                  // returns a DirectX error code
The first parameter is a series of flags that determine how the display modes are enumerated, and can be set to zero. The second parameter is a pointer to a TDDSurfaceDesc2 structure that contains information defining the types of display modes to be enumerated. We can use this to enumerate only specific types of display modes, such as all 800 x 600 modes or all palettized display modes. Setting this parameter to nil will enumerate all supported display modes. The third parameter is a pointer to an application-defined value, and the last parameter is a pointer to the callback function itself. The callback function is defined as:
    function TDDEnumModesCallback2(

    const lpDDSurfaceDesc: TDDSurfaceDesc2;      // a surface description record

    lpContext: Pointer                           // the application-defined value

    ): HResult;                                  // returns a DirectX error code
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.