DirectX and Delphi 5

By: Charles Calvert

Abstract: Updating Delphi 3 and 4 Projects to Use Delphi 5. The emphasis is on the DirectX header translations.

Delphi 5 does not accept many of the old DirectX header file translations that worked with Delphi 4

DirectX in Delphi 5

Copyright ) 1999 by Charlie Calvert

Delphi 5 does not accept many of the old DirectX header file translations that worked with Delphi 4. In particular, you are likely to get the error:

Type IDirectDrawSurface needs finalization  not allowed in variant record

This article is designed to explain what that error means, and what you can do about it. In the process, you will also learn how to use the new JEDI translations of the DirectX headers. The text should be of interest to all readers of the DirectX sections of my Unleashed books, and to others who have a general interest in DirectX program.

Numerous DirectX and several Direct3D retained mode examples are available from hyperlinks found at the bottom of this article. These are updates of the examples in Delphi 4 Unleashed.

This error occurs because the Delphi team has made it illegal to include COM objects in variant records. For instance, the following record is now illegal:

TDDFake = record

dwSize: DWORD;

dwDDFX: DWORD;

case Integer of

0: (

dwZDestConst: DWORD;

dwZSrcConstBitDepth: DWORD;

);

1: (

lpDDSZBufferDest: IDirectDrawSurface; // This is the bad line

UNIONFILLER1b: DWORD;

);

2: (

UNIONFILLER2a: DWORD;

UNIONFILLER2b: DWORD;

);

end;

The problem is that an IDirectDrawSurface is a COM object. Delphi performs special memory management techniques on COM objects. In particular, it will automatically destroy them when they go out of scope.

It happens that variant records are complex structures to manage. In particular, the first item in the variant part of this record can be either a DWORD or an IDirectDrawSurface depending on the whim of an individual developer. As a result, Delphi cant be sure when it needs to free a COM object in a variant record and when it should leave it alone. In other words, it cant know ahead of time whether the developer wants to work with a DWord, or an IDirectDrawSurface. The only reasonable solution to this problem is to simply make it illegal to include COM objects in variant records. Indeed, this type of declaration should always have been illegal, and it was a mistake to have allowed it to compile in Delphi 4.

One solution to this problem is to simply re-declare lpDDSZBufferDest as a pointer:

lpDDSZBufferDest: Pointer;

You can now typecast lpDDSZBufferDest as an IDirectDrawSurface whenever you need to access it. The code will compile, and all works as planned. However, you might want to explicitly free the memory when you are through with it, rather than having Delphi free it automatically.

By this time you should understand why the DirectX Pascal files you might have used with Delphi 4 do not work in Delphi 5. The next step is to introduce you to a new set of DirectX files that do work with Delphi 5.

Working with the New DirectX Header Translations.

Microsoft creates C++ header files as the primary means for developers to access the DirectX API. Delphi programmers need Pascal translations of these header files in order to program in DirectX.

Erik Unger and the JEDI project (www.delphi-jedi.org) provide one of the most commonly used translations of these header files. Erik is a very talented and hard working programmer, who keeps up to date with the latest changes in the SDK. You can get his translations from the following URL:

http://www.delphi-jedi.org/DelphiGraphics/index.htm

In the past, he translated the numerous DirectX files into one big Delphi file. In recent times he has switched to one of two ways of organizing the files he translates into Pascal. In the first scheme, he provides a one to one mapping of the DirectX header files to Pascal files. In this scheme, DDraw.h gets translated into Pascal as DDraw.pas, D3D.h becomes D3D.pas, DInput.h becomes DInput.pas, and so on.

In a newer scheme, he is grouping the major sets of DirectX files as follows:

DirectDraw.pas = DDraw.h + DVP.h (+ MultiMon.h)

Direct3D.pas = D3D.h + D3DTypes.h + D3DCaps.h +

D3DVec.inl + DXFile.h

Direct3DRM.pas = D3DRM.h + D3DRMDef.h + D3DRMObj.h +

D3DRMWin.h + RMXFGUID.h + RMXFTmpl.h

DirectInput.pas = DInput.h (+ DinputD.h)

DirectPlay.pas = DPlay.h + DPLobby.h

DirectSound.pas = DSound.h

DirectMusic.pas = DLS1.h + DLS2.h + DMDLS.h + DMError.h +

DMKSCtrl.h + DMusicC.h + DMusicF.h +

DMusicI.h + DMusBuff.h

DirectSetup.pas = DSetup.h

 

Both of these schemes are perfectly reasonable and Erik has done what he can to create solutions that he believes appeals to the largest number of users of his files. In particular, he tirelessly queried the community as to their preferences, and tried to follow the will of the majority.

In the DirectX programs that I shipped in Delphi 4 Unleashed, most of the DirectX header files were encapsulated in a single Pascal unit called DirectX.pas. If you try to compile these projects under Delphi 5, you will get the variant record error mentioned earlier in this article. If you download Eriks newest headers, you will have to edit my files, since DirectX.pas no longer exists.

In all the DirectX examples I give, the solution is very straightforward: simply changes references to the DirectX unit to DDraw or to DirectDraw. In some cases, you may have to add DSound to your uses clause.

The Direct3D examples I include are a bit more complicated. For instance, you might create a uses clause that looks like this:

uses

Windows, Graphics, DDraw,

D3DRM, D3DTypes, D3DRMObj,

D3DRMDef, D3DRMWin;

If you are using the second of Eriks new schemes, what you come up with will probably look like this:

Uses

Windows, Graphics, DirectDraw,

Direct3D, Direct3DRM.

Obviously there are no hard and fast rules as to which files you should include. The only way to know for sure is to try to compile your code, and see if some of the variables you use are not known by the compiler. If that is the case you can use the Grep utility that ships with Delphi to find the header file translation that you need to use.

One final note on this issue involves where you choose to place Eriks header translations. Readers of my books know that I usually place all my shared units in a single directory called units. In this case, I have finally broken down and created a new subdirectory just for DirectX files. I believe this is a wise thing to do, because you may need to delete or update some or all of these files on a regular basis as both Erik and Microsoft continue their work. Putting them all in a single dedicated directory is the simplest way to accomplish this goal. As a result, I now have a Units/DirectX directory where I keep these files.

Examples

In this section you will find two examples of how to use Eriks header. The first, shown in Listing 1, is a basic DirectDraw example. The second, shown in Listing 2, is a simple Direct3D retained mode example.

Example 1: A few simple DirectX examples using the DDraw JEDI translation. In some cases you may want to use DirectDraw instead of DDraw.

Direct Draw Examples

Example 2: A simple Direct3D retained mode example.

 


Server Response from: ETNASC04