Function Declarations

At this point, you have a good idea of how the various DirectX functions work, so it's time to see how to declare them. Listing 14.2 shows typical DirectX function declarations. I say typical because some of the functions will require more than one implementation to satisfy some development needs. In fact, some functions require at least two declarations for a minimal implementation.

Listing 14.2: The DirectX Specific Function Declarations

/// This function creates an instance of a DirectDraw object. The /// object doesn't include Direct3D support. /// </summary>

[DllImportCDDraw.DLL", CharSet=CharSet.Auto, SetLastError=true )] public static extern Int32 DirectDrawCreate(GUID lpGUID,

Object lplpDD, IntPtr pUnkOuter);

DirectDrawEnumerate() and DirectDrawEnumerateEx()

[DllImport("DDraw.DLL", CharSet=CharSet.Auto, SetLastError=true )] public static extern Int32 DirectDrawCreate(IntPtr NO_GUID,

Object lplpDD, IntPtr pUnkOuter);

/// This function creates an instance of a DirectDraw object that /// includes Direct3D support. Always used the IID_IDirectDraw7 /// constant for the third argument. /// </summary>

[DllImport("DDraw.DLL", CharSet=CharSet.Auto, SetLastError=true )] public static extern Int32 DirectDrawCreateEx(GUID lpGUID,

Object lplpDD, GUID iid,

IntPtr pUnkOuter);

[DllImport("DDraw.DLL", CharSet=CharSet.Auto, SetLastError=true )] public static extern Int32 DirectDrawCreateEx(IntPtr NO_GUID,

Object lplpDD, GUID iid,

IntPtr pUnkOuter);

/// This function creates a DirectDrawClipper object, which /// describes a clipping area on the screen. /// </summary>

[DllImport("DDraw.DLL", CharSet=CharSet.Auto, SetLastError=true )] public static extern Int32 DirectDrawCreateClipper( UInt32 dwFlags, Object lplpDDClipper, IntPtr pUnkOuter);

/// This function initiates an enumeration sequence that /// provides information about the DirectX capable devices /// that are installed on the host system. /// </summary>

[DllImport("DDraw.DLL", CharSet=CharSet.Auto, SetLastError=true,

EntryPoint="DirectDrawEnumerateExA" )] public static extern Int32 DirectDrawEnumerateEx( Callbacks.DDEnumCallbackEx lpCallback, IntPtr lpContext, DDEnumType dwFlags);

All of these functions require some level of conversion. However, the DirectDrawCreate() and DirectDrawCreateEx() functions require multiple implementations because of the GUID pointer required as the first argument. We need some way to pass a null value to DirectX, and the best way to do that is to use an IntPtr. Remember to set the pUnkOuter argument _to IntPtr.Zero in all cases because this feature isn't implemented. Also, you must use the IID_IDirectDraw7 constant for the iid argument for the DirectDrawCreateEx() function.

Warning Many of the DirectX function calls aren't implemented as Unicode calls. The

DDraw.DLL contains the proper Unicode function entry, but the function itself returns an error message. What this means is that you'll receive a return value of E_NOTIMPL (0x80004001) when you call the function—even if you provide the correct input values. This error number isn't registered as one of the errors that DirectX will return, which makes it even harder to troubleshoot. In fact, it's an error that you won't receive once your application is debugged and running. However, if you see this error during development, make sure you've added an EntryPoint argument to the [DllImport] attribute as shown for the DirectDrawEnumerateEx() function in Listing 14.2. This argument ensures that your application calls the correct function. Generally, you'll find that the error message goes away and you'll never see it again (at least not in this application).

The DDEnumCallbackEx() function contains more managed-code-specific changes than the other functions we have discussed. As previously mentioned, we're passing a pointer to a callback function delegate as the first argument. To make the code easier to read, use, and take apart for other uses, I decided to place the callback functions in a separate class (in a separate file). The Callbacks.DDEnumCallbackEx() member contains the definition of the DDEnumCallbackEx() callback function. The example also uses a special enumeration to ensure that users of the library use the correct value for the third argument. Here's the definition of the DDEnumType enumeration:

public enum DDEnumType {

// Normally, this flag isn't required. Because we're using an // enumeration we need some way of listing only the primary display // device.

DDENUM_NONE = 0x00000000,

// This flag causes enumeration of any GDI display devices which are // part of the Windows Desktop

DDENUM_ATTACHEDSECONDARYDEVICES = 0x00000001,

// This flag causes enumeration of any GDI display devices which are // not part of the Windows Desktop DDENUM_DETACHEDSECONDARYDEVICES = 0x00000002,

// This flag causes enumeration of non-display devices DDENUM_NONDISPLAYDEVICES = 0x00000004,

// This flag isn't part of the listing found in the C/C++ header, // but it makes working with the numeration easier. DDENUM_ALL_DEVICES = 0x00000007

Was this article helpful?

0 0

Post a comment