JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
  Previous Section Next Section

Cooperating with Windows

As you know, Windows is a cooperative, shared environment. At least that's the idea, although as a programmer I still haven't figured out how to make it cooperate with my code! Anyway, DirectX is similar to any Win32 system, and at the very least, it must inform Windows that it's going to use various resources so that other Windows applications don't try to request (and get) resources that DirectX has control over. Basically, DirectX can be a complete resource hog as long is it tells Windows what it's doing—seems fair to me <BG>.

In the case of DirectDraw, about the only thing that you should be interested in is the video display hardware. There are two cases that you must concern yourselves with:

  • Full-screen mode

  • Windowed mode

In full-screen mode, DirectDraw acts much like an old DOS program. That is, the entire screen surface is allocated to your game, and you write directly to the video hardware. No other application can touch the hardware. Windowed mode is a little different. In windowed mode, DirectDraw must cooperate much more with Windows because other applications may need to update their own client window areas (which may be visible to the user). Hence, in windowed mode your control and monopolization of the video hardware is much more restrained. However, you still have full access to 2D and 3D acceleration, so that's a good thing. But then, so were bell-bottoms at first…

Chapter 7, "Advanced DirectDraw and Bitmapped Graphics," will talk more about windowed DirectX applications, but they are a little more complex to handle. Most of this chapter will deal with full-screen modes because they are easier to work with, so keep that in mind.

Now that you know a little bit about why there needs to be cooperation between Windows and DirectX, let's see how to tell Windows how you want to cooperate. To set the cooperation level of DirectDraw, use the IDirectDraw7:: SetCooperativeLevel() function, which is a method of IDirectDraw7.

C++

For you C programmers, the syntax IDirectDraw7::SetCooperative Level() may be a little cryptic. The :: operator is called the scope resolution operator, and the syntax simply means that SetCooperativeLevel() is a method (or member function) of the IDirectDraw7 interface. This is basically a class that is nothing more than a structure with data and a virtual function table. In some cases, I may forgo using the interface to prefix the method and write it like SetCooperativeLevel(). However, be advised that all DirectX functions are part of an interface and thus must be called using a function pointer style call, like lpdd->function(...).


Here's the prototype of IDirectDraw7::SetCooperativeLevel():

HRESULT SetCooperativeLevel(HWND hWnd,     // window handle
                            DWORD dwFlags);// control flags

This returns DD_OK if successful, and an error code if not.

Interestingly enough, this is the first time that the window handle has entered into the DirectX equation. The hWnd parameter is needed so that DirectX (or more specifically, DirectDraw) has something to anchor to. Simply use your main window handle in all cases.

The second and last parameter to SetCoopertiveLevel() is dwFlags, which is the control flags parameter and directly influences the way that DirectDraw works with Windows. Table 6.2 lists the most commonly used values that can be logically ORed together to obtain the desired cooperation level.

Table 6.2. Control Flags for SetCooperativeLevel()
Value Description
DDSCL_ALLOWMODEX Allows the use of Mode X (320x200,240,400) display modes. Can be used only if the DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN flags are present.
DDSCL_ALLOWREBOOT Allows Ctrl+Alt+Del to be detected while in exclusive (full-screen) mode.
DDSCL_EXCLUSIVE Requests the exclusive level. This flag must be used with the DDSCL_FULLSCREEN flag.
DDSCL_FPUSETUP Indicates that the calling application is likely to keep the FPU set up for optimal Direct3D performance (single precision and exceptions disabled) so Direct3D does not need to explicitly set the FPU each time. For more information, look up "DirectDraw Cooperative Levels and FPU Precision" in the DirectX SDK.
DDSCL_FULLSCREEN Indicates full-screen mode will be used. GDI from other appli cations will not be able to draw on the screen. This flag must be used with the DDSCL_EXCLUSIVE flag.
DDSCL_MULTITHREADED Requests multithread-safe DirectDraw behavior. Don't worry about this for now.
DDSCL_NORMAL Indicates that the application will function as a regular Windows application. This flag cannot be used with the DDSCL_ALLOWMODEX, DDSCL_EXCLUSIVE, or DDSCL_FULLSCREEN flags.
DDSCL_NOWINDOWCHANGES Indicates that DirectDraw is not allowed to minimize or restore the application window on activation.

If you take a good look at the various flags, it may seem that some of them are redundant—very true. Basically, DDSCL_FULLSCREEN and DDSCL_EXCLUSIVE must be used together, and if you decide to use any Mode X modes, you must use DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE, and DDSCL_ALLOWMODEX all together. Other than that, the flags pretty much do what they would seem to from their definitions. In most cases, you'll set full-screen applications like this:

lpdd7->SetCooperativeLevel(hwnd,
                           DDSCL_FULLSCREEN |
                           DDSCL_ALLOWMODEX |
                           DDSCL_EXCLUSIVE |
                           DDSCL_ALLOWREBOOT);

and normal windowed applications like this:

lpdd7->SetCooperativeLevel(hwnd, DDSCL_NORMAL);

Of course, when you get to multithreaded programming techniques later in the book, you might want to add the multithreading flag DDSCL_MULTITHREADED to play it safe. Anyway, let's see how you would create a DirectDraw object and set the cooperation level together:

LPDIRECTDRAW lpdd  = NULL; // standard DirectDraw 1.0
LPDIRECTDRAW7 lpdd7 = NULL; // DirectDraw 7.0 interface 7

// first create base IDirectDraw interface
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd7, IID_IDirectDraw7, NULL)))
   {
   // error
   } // end if
// now set the cooperation level for windowed DirectDraw
// since we aren't going to do any drawing yet
if (FAILED(lpdd7->SetCooperativeLevel(hwnd, DDSCL_NORMAL)))
   {
   // error
   } // end if

NOTE

I may start leaving out the error handling calls to FAILED() and/or SUCCEEDED() to save space, but remember that you should always check for errors!


At this point, you have enough information to create a complete DirectX application that creates a window, starts up DirectDraw, and sets the cooperation level. Although you don't know how to draw, it's a start. As an example, take a look at DEMO6_1.CPP on the CD, along with its executable DEMO6_1.EXE. When you run the program, you'll see something like what's shown in Figure 6.5. I based the program on the T3D Game Console template, so the only changes I made were in the Game_Init() and Game_Shutdown() to create and set the cooperation level for DirectDraw.

Figure 6.5. DEMO6_1.EXE in action.

graphics/06fig05.gif

Here are those functions with the added DirectDraw code from DEMO6_1.CPP, so you can see how simple DirectDraw is to set up:

int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here

// first create base IDirectDraw interface
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
   {
   // error
   return(0);
   } // end if
// set cooperation to normal since this will be a windowed app
lpdd->SetCooperativeLevel(main_window_handle, DDSCL_NORMAL);

// return success or failure or your own return code here
return(1);

} // end Game_Init

/////////////////////////////////////////////////////////////

int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// this is called after the game is exited and the main event
// loop while is exited, do all you cleanup and shutdown here

// simply blow away the IDirectDraw interface
if (lpdd)
   {
   lpdd->Release();
   lpdd = NULL;
   } // end if

// return success or failure or your own return code here
return(1);

} // end Game_Shutdown

TIP

If you're about to jump in head-first and try to compile DEMO6_1.CPP, please remember to manually include DDRAW.LIB from the DirectX 8.0 SDK LIB\ directory, along with adding the DirectX header paths to your compiler's .H search directories as the first directory! And of course, you should build a Win32 .EXE. I get at least 10 emails a day from rookie compiler users who forget to include the .LIB files, so don't be another statistic…


      Previous Section Next Section
    



    JavaScript EditorAjax Editor     JavaScript Editor