DirectX5.0 Latest Game Programming Guide
One configuration DirectX SDK 2
1.1 Configuring Microsoft Developer Studio 2
1.2 Formulated NMAKE Path 3
1.3 Configuring DirectX SDK 3 for Borland C 5.0
Two first DirectDraw example 3
2.1 First initialization DirectDraw object 4
2.2 Creating a DirectDraw object 5
2.3 Setting the display mode 5
2.4 Changing the display mode 6
2.5 Creating a flippable surface (FLIPPABLE SURFACE) 6
2.6 Define Surface Requirements 6
2.7 Creating a surface 7
2.8 Coloring Surface 8
2.9 Write surface and flip surface 8
2.10 Release DirectDRAW Object 10
2.11 Tune the bitmap into the surface 10
2.12 Set the palette to transfer the bitmap into the backbound buffer 11
2.13 Transmission 12 from the exterior surface block
2.14 Turn the bitmap file into the exterior surface 13
2.15 Transfer the outer surface bit block to the background buffer 13
Third, create an animation 14
3.1 Color Key and Downport Animation 14
3.2 Animation 15 in DDEX4
3.3 Dynamic changes palette 15
3.4 Replace the palette 15
Four use coverage surface 16
4.1 Creating a major surface 16
4.2 Detecting hardware to cover coverage 17
4.3 Creating a coverage surface 17
4.4 Displaying the cover surface 19
4.5 Update Overwrite Display Position 22
4.6 Hide Cover Surface 23
Other DirectDraw example 23 in five DirectDraw
DirectDraw tutorial
DirectX is prepared for users of Visual C , so the DirectDraw game program is to be prepared, and it is best to have a certain understanding of VC. Users who are unwilling to use VC can also use Arakelian Soft to develop ActiveX control DirectStudio98 or Tegosoft's Tegosoft ActiveX for Visual Basic for Visual Basic5.0 users developed by Arakelian Soft. However, if you want to give full play to DirectX performance, and you want to keep the program's compatibility, it is best to use Visual C .
For the convenience of narrative, it is assumed that DirectX5.0 SDK and Visual C 5.0 have been installed, and its directory is C: / DX5SDK and C: / Program Files / DevStudio. If you use another compiler or install it to other directories, you must do appropriate modifications to make appropriate modifications. Someone has installed DirectX SDK, but I don't know how to use because it is based on Visual C , but there is no interface-friendly integrated development environment, so Visual C must be appropriately formulated.
One configuration DirectX SDK
1.1 Configuring Microsoft Developer Studio
In order to compile the DirectX SDK, you need to open a new Project Workspace, insert the appropriate file, set the environment variable to enable the compiler to find the required link library and include files, which describe the entire process of settings. Start Microsoft Developer Studio, install the following steps to create a project:
In the File menu, choose New;
Select Win32 Application in Project in the New dialog box, enter DDEX1 in Project Name
. In the location text box, enter the location of the project file, point OK button
A new DDEX1 Classes folder appears on the left of the Workspace window.
After the project is created, you need to use the following steps to insert the appropriate file to the project:
Select Add Toproject | Files in the Project menu. Browse to the C: / DX5SDK / SDK / Samples / DDEX1 directory, select all files
Select OK, Ddex1.cpp, Ddex1.rc, resource.h in this directory is added.
Then set the path to the file:
. In the Tools menu, select Options, pop-up OPTIONS dialog box
Select Directories, select include Files in the Show Directories for list box
In the Directories: list box double-click the blank line at the bottom of the list, enter C: / DX5SDK / SDK / INC.
Again, add another path C: / DX5SDK / SDK / Samples / Misc
. Select the OK button,
Set the link library directory:
Select Library Files in the Show Directories for list box
In the Directories: list box double-click the bottom blank line, enter C: / DX5SDK / SDK / LIB.
. Click the OK button.
Finally set the module that links when the application is established:
Click Settings in the Project menu.
. Select LINK
Select General in the Category drop-down box.
Add DDRAW.LIB and WINMM.LIB in the Object / Library module list box.
Click OK.
1.2 Formulate NMAKE path
Sometimes the way the command line is more convenient than the integrated environment, so many experienced programmers are more willing to build applications in the way they are command line. Below is the path to the file and link library module:
@echo off
SET PATH = C: / Program Files / DevStudio / Sharedide / bin
C: / program files / devstudio / vc / bin;% PATH%
Set include = c: / program files / devstudio / vc / incrude;
C: / program files / devstudio / vc / mfc / include; c: / dx5sdk / sdk / inc;% include%
SET lib = c: / program files / devstudio / sharedide / vc / lib;
C: / Program Files / DevStudio / VC / MFC / LIB; C: / DX5SDK / SDK / LIB;% LIB%
Set init = c: / program files / devstudio;% init%
Add the above to Autoexec.bat. Enter in the directory of the example
Nmake
A debug directory will be created in the current directory and place the generated executable in this directory.
In order to be familiar with DirectX SDK during the learning process, we will follow the sequence of the sample programs provided by DirectX SDK, step by step.
1.3 Configuring DirectX SDK for Borland C 5.0
Although DirectX 5 SDK is prepared for Visual C users, Microsoft has not forgotten many Borland.
C users, so the DirectX's Borland C library is also available in DirectX SDK. However, it is possible for competition (guessing), there is no Borland C library in the DirectX SDK after installation. This requires users to handle this annoying problem. We know, DirectX 5 SDK is released in an idx5sdk.exe. After running IDX5SDK, it will first extract the compressed files into a directory (such as d: / dx5sdk), then run the setup.exe in this directory. Install DirectX SDK (assuming the directory is C: / DX5SDK). In fact, in the decompressed directory contains a D: / DX5SDK / SDK / LIB / BORLANDC directory, this directory is the link library file for Borland C . However, when Setup installation, the installer does not copy the directory to the installation directory. The solution is very simple, that is, after the setup installation is complete, create a C: / DX5SDK / SDK / lib / borland, copy all the files under the directory D: / DX5SDK / SDK / LIB / BORLAND to C: / DX5SDK / SDK / LIB / BORLAND directory. The project file is then configured in the Integrated Environment of the Borland C 5.0 as configuring Visual C 5.0. Two first DirectDraw instance
To use DirectDraw, you must first create an instance of the DirectDRAW object to characterize the display adapter card on your computer and then use the interface method to process the object. Also need to create an instance of one or more DirectDrawSurface objects to display the game. DDEX1 first creates a DirectDraw object, create a primary surface (Primary
Surface and a background buffer and then converts between the surface. DDEXX examples are written in C . If you are using a C compiler, you must make the code appropriately change, at least the pocket to point to the interface method.
2.1 First initialize the DirectDraw object
The DDEX1 program contains DIINIT functions containing the initialization code of DirectDraw:
// Create a primary DirectDraw object
DDRVAL = DirectDrawCreate (NULL, & LPDD, NULL);
IF (DDRVAL == DD_OK)
{
// Get exclusive mode
DDRVAL = LPDD-> SetCooperativeElevel (HWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
IF (DDRVAL == DD_OK)
{
DDRVAL = LPDD-> setDisplayMode (640, 480, 8);
IF (DDRVAL == DD_OK)
{
// Create a main surface with a background buffer
Ddsd.dwsize = sizeof (ddsd);
DDSD.DWFLAGS = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
DDSD.DDSCAPS.DWCAPS = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
DDSD.DWBACKBUFFERCOUNT = 1;
DDRVAL = LPDD-> CreateSurface (& DDSD, & LPDDSPRIMARY, NULL);
IF (DDRVAL == DD_OK) {
/ / Get pointers in the background buffer
DDSCAPS.DWCAPS = DDSCAPS_BACKBUFFER;
DDRVAL = LPDDSPRIMARY-> GetAttachedSurface (& DDSCAPS, & LPDDSBACK);
IF (DDRVAL == DD_OK)
{
// Picture some text
IF (LPDDSPRIMARY-> Getdc (& HDC) == DD_OK)
{
SetBkcolor (HDC, RGB (0, 0, 255));
SetTextColor (HDC, RGB (255, 255, 0));
Textout (HDC, 0, 0, SZFRONTMSG, LSTRLEN (SZFRONTMSG);
LPDDSPRIMARY-> ReleaseDC (HDC);
}
IF (LPDDSBACK-> Getdc (& HDC) == DD_OK)
{
SetBkcolor (HDC, RGB (0, 0, 255));
SetTextColor (HDC, RGB (255, 255, 0));
Textout (HDC, 0, 0, SzBackMSG, LSTRLEN (SZBackMSG);
LPDDSBACK-> ReleaseDC (HDC);
}
// Create a timer of the flip page
IF (SetTimer (HWnd, Timer_ID, Timer_Rate, Null)
{
Return True;
}
}
}
}
}
}
WSPRINTF (BUF, "Direct Draw Init Failed (% 08LX) / N", DDRVAL);
..........
Each of the steps of the creation of the DirectDRAW object will be described in detail below.
2.2 Creating a DirectDRAW object
Creating an instance of the DirectDraw object, you should use the DirectDrawCreate API function, you can also use the CoCreateInstance function in COM. DirectDrawCreate with a global unified marker Guid (Globally
UNIQUE Identifier "to characterize the display device, in most cases GUID is NULL (using the system's default display device," empty device "); pointer points to the address of the DirectDraw object; the third parameter is always null (for future expansion use). The following code indicates how to create a DirectDraw object and the inspection is successful.
DDRVAL = DirectDrawCreate (NULL, & LPDD, NULL);
IF (DDRVAL == DD_OK)
{
// LPDD IS is a legitimate DirectDraw object
}
Else
{
// DirectDRAW object cannot be created
}
2.3 Setting the display mode
Setting up the display mode of the DirectDRAW application requires two steps: first call the iDirectDraw :: SetCoopeLevelLevel method to set the requirements in this mode, once the requirements are determined, use the idirectdraw :: setDisplayMode method to select the display resolution.
Before changing the display resolution, you must also specify the DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN flags via the iDirectDraw :: SetCooperativeEvelEvel method.
This allows the game program to fully control the display device, and other applications cannot share the display device at the same time. The DDSCL_FULLSCREEN flag indicates that the program is set to full screen mode. The following code shows how to use iDirectdraw :: setCooperativeElevel method: HRESULT DDRVAL;
LPDIRECTDRAW LPDD; // Already Created by DirectDrawCreate
DDRVAL = LPDD-> SetCooperativeElevel (HWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
IF (DDRVAL == DD_OK)
{
/ / Full screen exclusive way setting success
}
Else {
// The call is unsuccessful, but the program can continue to run
}
If iDIRECTDRAW :: SETCOOPERATIVELEVEL does not return DD_OK, you can still run the program, but not full screen mode, sometimes some unpredictable errors. So you should display an error message, let the user know what happened, by the user to decide whether to continue the game.
When using iDirectdraw :: SetCoopeRATIVELEVEL, you must transfer a handle to the window (HWND), allowing the window to determine when the application is not normally stopped. For example, if a GP error or GDI is flipped (FLIP) to the background buffer, the user cannot access the current screen. In order to avoid this, DirectDraw has a background waiting process that captures all messages sent to the window, use these messages to determine when the application is terminated. If a new window is created, you must make sure that the window is active, otherwise, there will be a series of events that cannot continue to work.
2.4 Changing the display mode
Once the application's operating mode is selected, you can use the iDirectdraw :: setDisplayMode method to change the display mode, the following code sets the display mode to 640x480x256:
HRESULT DDRVAL;
LPDIRECTDRAW LPDD; // Already CREATED
DDRVAL = LPDD-> setDisplayMode (640, 480, 8);
IF (DDRVAL == DD_OK)
{
// change the mode success
}
Else
{
// Display mode cannot be changed
// The system may not support this mode
}
When setting the display mode, make sure that if the user's device does not support higher resolution, the application should return to the standard mode supported by the system. If you display a resolution of the design, IDirectDraw :: setDisplayMode returns a DDERR_INVALIDMODE error value. Therefore, when setting the resolution, you should first use the IDirectDraw :: EnumDisplayMode method to detect the performance of the user's display device.
2.5 Creating a flippable surface (FLIPPABLE SURFCE)
After setting the display mode, you must create the surface of the placed application. In DDEX1, we use the iDirectDraw :: SetCoopeRarativeEvelEvel method to set the program exclusive full screen mode, and then create a flip surface. If you use iDireCTDraw :: SetCoopeRATIVELEVEL to be DDSCL_NORMAL mode, you can only create a block of writing.
2.6 Define surface requirements
The first step in creating a flipped surface is to define the requirements of the surface in the DDSurfaceDesc structure. The following code describes the definition of the structure and the flag required to create a flipped surface:
// Create a main surface with a background buffer
Ddsd.dwsize = sizeof (ddsd);
DDSD.DWFLAGS = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; DDSD.DDSCAPS.DWCAPS = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
DDSD.DWBACKBUFFERCOUNT = 1;
In the example, the member variable DWSIZE is set to the size of the DDSurfaceDesc structure. DWFlags flag Specifies which domains in the DDSurfaceDesc structure can store valid information.
In DDEX1, dwflags pointed out that you need to use a DDSCAPS structure (DDSD_CAPS) and create a background buffer
(DDSD_BACKBUFFERCOUNT). DWCaps indicates the flags of the DDSCAPS structure, which specifies a master surface (DDSCAPS_PRIMARYSURFACE, a flip surface (DDSCAPS_FLIP), and a complex surface (DDSCAPS_COMPLEX).
Finally, the program specifies a background buffer. The background buffer is the background image and the person will be written, which can be converted to the main surface.
In this example, the number of background buffers is 1, in fact, as long as there is enough display memory, you can create any multiple background buffers, usually every 1m display memory can only be used to create a background buffer. The surface of the surface can be either displayed, or a system memory.
DirectDRAW will automatically use system memory when using the displayed memory (for example, 2 background buffers that only 1m display memory) will automatically use. You can specify only system memory or only display memory only by setting DWCaps in the DDSCAPS structure to DDSCAPS_SYSTEMEMORY or DDSCAPS_VIDEMEMORY. If you specify DDSCAPS_VIDEMEMORY, there is not enough display memory to create a surface, iDirectdraw :: CreateSurface
A DderR_OutofVideoMEMory error will be returned.
2.7 Creating a surface
Fill the DDSurfaceDesc structure, you can use this structure and LPDD, LPDD is DirectDrawCreate
Method created the pointer of the DirectDraw object, the following code shows this process:
DDRVAL = LPDD-> CreateSurface (& DDSD, & LPDDSPRIMARY, NULL);
IF (DDRVAL == DD_OK)
{
// LPDDSPRIMARY POINTS TO New Surface
}
Else
{
// Surface Was Not Created
Return False;
}
If the call is successful, the IDirectDraw :: CreateSurface function returns the pointer LPDDSPRIMARY to the main surface. If the main surface pointer is available, you can call the IDirectDrawsurface :: getAttachedSurface method to get the pointer to the background buffer, as shown below:
DDSCAPS.DWCAPS = DDSCAPS_BACKBUFFER;
DDRVAL = LPDDSPRIMARY-> GetAttachedSurface (& DDCAPS, & LPDDSBACK);
IF (DDRVAL == DD_OK)
{
// LPDDSBACK POINTS to the Back Buffer
}
Else
{
Return False;
}
If the iDirectdrawsurface :: getAttachedSurface calls successfully, the LPDDSBACK parameter points to the background buffer by providing the address of the main surface and setting the DDSCAPS_BACKBuffer flag. 2.8 Coloring Surface
After creating the main surface and the background buffer, DDEX1 uses the standard WindowsGDI function to submit some text to the main surface and background buffer, the code is as follows:
IF (LPDDSPRIMARY-> Getdc (& HDC) == DD_OK)
{
SetBkcolor (HDC, RGB (0, 0, 255));
SetTextColor (HDC, RGB (255, 255, 0));
Textout (HDC, 0, 0, SZFRONTMSG, LSTRLEN (SZFRONTMSG);
LPDDSPRIMARY-> ReleaseDC (HDC);
}
IF (LPDDSBACK-> Getdc (& HDC) == DD_OK)
{
SetBkcolor (HDC, RGB (0, 0, 255));
SetTextColor (HDC, RGB (255, 255, 0));
Textout (HDC, 0, 0, SzBackMSG, LSTRLEN (SZBackMSG);
LPDDSBACK-> ReleaseDC (HDC);
}
The IDIRECTDRAWSURFACE :: GETDC method is used in the example to lock the surface and lock the surface. If you don't want to use the Windows function of your handle, you can also lock and unlock the background buffer using the iDirectdrawsurface :: Lock and IdirectDrawSurface :: UNLock method. The memory of the lock surface (whether the entire surface is also part of it) ensures that your application and system will not access this memory at the same time. In addition, the program cannot flush the surface unless the memory is unlocked. In this case, use the Windows GDI function setBkcolor to set the background color after the lock surface, use setTextColor to set the text color, then output the text to the surface using Textout. When the text is written into the buffer, the idirectdrawsurface :: releasedc method is used to unlock the surface and release the handle. Good habits are that after writing data to the background buffer, call IDirectDrawsurface :: releasedc or idirectdrawsurface :: unlock.
In general, when writing data to the surface, the surface is the background buffer, and then the buffer is turned out into the main surface. In DDEX1, there is an important delay before the first flip surface. So DDEX1 writes data to a main buffer to avoid too long time intervals when the start is displayed. It will be said later that DDEX1 will write data to the background only during WM_TIMER. Initialization functions or header heads may be written to the main buffer. It should be noted that once the IDIRECTDRAWSURFACE :: UNLock is unlocked to the surface, the pointer to the surface becomes invalid, and the iDirectDrawsurface :: Lock method must be used again to obtain the valid pointer of the surface memory.
2.9 Write surface and flip surface
After completing the initialization, DDEX1 starts processing a message loop. During the message cycle, complete the lockup background buffer - write new text-unlock the background buffer-flip surface. WM_TIMER contains most of the code in writing data and flipping surfaces.
The first half of the WM_TIMER message is used to write data to the background buffer, and the "Phase" variable is determined whether to write the main buffer message or write the background buffer message. If PHASE is 1, represent the message written in the main buffer, then change the phase to 0; if 0, represent the message written in the background buffer, and then change the phase to 1. Note that the messages in both cases are written to the background buffer. After writing the message, the background buffer is unlocked using the idirectdrawsurface :: releasedc method. The following code implements this: Case WM_TIMER:
// Flip Surfaces
IF (BACTIVE)
{
IF (LPDDSBACK-> Getdc (& HDC) == DD_OK)
{
SetBkcolor (HDC, RGB (0, 0, 255));
SetTextColor (HDC, RGB (255, 255, 0));
IF (PHASE)
{
Textout (HDC, 0, 0, SZFRONTMSG, LSTRLEN (SZFRONTMSG);
PHASE = 0;
}
Else
{
Textout (HDC, 0, 0, SzBackMSG, LSTRLEN (SZBackMSG);
Phase = 1;
}
LPDDSBACK-> ReleaseDC (HDC);
}
After the surface is blocked, use the iDirectdrawsurface :: flip method to turn the background buffer into the main surface, the code is as follows:
While (1)
{
HRESULT DDRVAL;
DDRVAL = LPDDSPRIMARY-> FLIP (NULL, 0);
IF (DDRVAL == DD_OK)
{
Break;
}
IF (DDRVAL == DDERR_SURFACELOST)
{
IF (DDRVAL = LPDDSPRIMARY- & G> VAL! = DD_OK)
{
Break;
}
}
IF (DDRVAL! = DDERR_WASSTILLDRAWING)
{
Break;
}
}
In the example, LPDDSPRIMARY indicates the main surface and its rear buffer. After calling the idirectdrawsurface :: FLIP method, the main surface and the rear surface are swapped. After the call is successful, return DD_OK, the program terminates the While loop; if you return Dderr_Surface :: The program terminates the While loop and returns an error value. In addition, as mentioned above, even if the IDirectDrawSurface :: flip is successful, the exchange is not immediately complete, it will wait until the system is completed after this. For example, the previous surface flip has not happened, iDirectdrawsurface :: flip returns DERR_WASSTILLDRAWING. In this example, idirectdrawsurface :: flip continues to loop until returns DD_OK ..
2.10 Release DirectDRAW object
When F12 is pressed, the DDEX1 program processes the WM_DESTROY message before exiting, which calls the FiniObjects function, and the FiniObjects function contains all the iUnknown Release calls, the code is as follows:
Static void finiobjects (void) {
IF (LPDD! = NULL)
{
IF (LPDDSPRIMARY! = NULL)
{
LPDDSPRIMARY-> Release ();
LPDDSPRIMARY = NULL;
}
LPDD-> Release ();
LPDD = NULL;
}
} / * FiniObjects * /
Program Detection DirectDraw object's pointer (LPDDSPRIMARY) for DirectDrawSurface objects (LPDDSPRIMARY)
Whether it is equal to NULL, this example is obviously not NULL. Then DDEX1 calls the idirectdrawsurface :: release method minus the reference value of the DirectDrawSurface object, which will make its reference value becomes 0, the DirectDrawSurface object is released, and the DirectDrawSurface's pointer is set to a null value, then undo. The program is called iDirectdraw :: Release reduces the reference value of the DirectDRAW object to 0, and the DirectDRAW object and its pointer are released.
The above DDEX1 is the most basic application of DirectDraw. It first creates a DirectDraw object and a DirectDrawSurface object. Create a home surface and its rear buffer, output text to the background buffer, then transform the surface. The second example DDEX2 extends the function of DDEX1, which can transfer a bitmap file into the backbrew. The third example DDEX3 further, in addition to a major surface and the background buffer, two screens are created, transfer the bitmap into each screen, then use the idirectdrawsurface :: bltfast method to put a single screen The content bit block of the surface is transmitted to the background buffer, then flip the surface and transmits the content bit block of the other screen outside to the background buffer. These features will be discussed in detail below.
2.11 Turn the bitmap into the surface
For example, in DDEX1, the DOINIT function is the initialization function of DDEX2, and the substance of both, until the following code:
LPDDPAL = DDLOADPALETTE (LPDD, SZBACKGROUND);
IF (LPDDPAL == NULL)
Goto error;
DDRVAL = LPDDSPRIMARY-> SetPalette (LPDDPAL);
IF (DDRVAL! = DD_OK)
Goto error;
// load a bitmap INTO The Back Buffer.
DDRVAL = DDRELOADBITMAP (LPDDSBACK, SZBACKGROUND);
IF (DDRVAL! = DD_OK)
Goto error;
The first row of the code returns a value from the function DDLoadPalette, which is in the ddutil.cpp file in the C: / DX5SDK / SDK / Samples / MISC, so it is necessary to join DDUTIL.CPP and DDUTIL.H when compiling DDEX2. Most DirectDraw programs require this file. In DDEX2, the DDLoadPalette function creates a DirectDrawPalette object from the Back.BMP file. The DDLoadPalette function first checks the file or resource exists for creating a palette. If there is no existence, create a default palette. In DDEX2, it extracts the palette information from the bitmap file and stores the structure pointed to by the APE, then create the DirectDrawPalette object as follows:
PDD-> CREATEPALETTE (DDPCAPS_8bit, APE, & DDPAL, NULL);
Return ddpal;
DDPAL points to the DirectDrawPalette object when the IDiretDraw :: Creatette method returns. APE is a pointer to a structure that includes 2/4/16/256 linear entities, and the number of entities is determined by the dwflags parameter called by idirectdraw :: CreatePalette. In this example, DWFLAGS is set to DDPCAPS_8bit, which means that there are 256 entities in the structure, each entity has four bytes (red, green, blue, and flag bytes).
2.12 Set the palette to transfer the bitmap into the backbound buffer
After creating a palette, you can transfer the pointer DDPAL of the DirectDrawPalette object to the main surface by calling the IDiretTe method. The code is as follows:
DDRVAL = LPDDSPRIMARY-> SetPalette (LPDDPAL);
IF (DDRVAL! = DD_OK)
// setPalette failed
After calling the IDirectDrawsurface :: setPalette method, the DirectDrawPalette object is together with the DirectDrawSurface object, and when you need to change the palette, you only need to create a new palette to set it.
After the DirectDrawPalette object is hanging together with the DirectDrawSurface object, DDEX2 uses the following code to load the back.bmp file into the background buffer:
// load a bitmap INTO The Back Buffer.
DDRVAL = DDRELOADBITMAP (LPDDSBACK, SZBACKGROUND);
IF (DDRVAL! = DD_OK)
// load failed
DDRELOADBITMAP is another function in ddutil.cpp, which transfers bitmaps to the existing DirectDRAW surface from files or resources. In this example, it puts the back.bmp pointing by SZBackground into the background buffer pointing to LPDDSBack. DDRELOADBITMAP calls the DDCopybitmap function to copy the file to the background buffer and extend to the appropriate size. The DDCopyBitmap function removes bitmaps into memory, use the getObject function to get the size of the bitmap, then use the code below to get the size of the background buffer to place the bitmap:
// Get size of surface.
Ddsd.dwsize = sizeof (ddsd);
DDSD.DWFLAGS = DDSD_HEIGHT | DDSD_WIDTH;
PDDS-> GetSurfaceDesc (& DDSD);
DDSD is a pointer to the DDSurfaceDesc structure that stores the current description of the DirectDraw surface. The member of the DDSurfaceDesc structure describes the high and width of the surface by DDSD_HEIGHT and DDSD_WIDTH. IdirectdrawSurface :: getSurfaceDesc method Use the appropriate value to the structure, the example is 480, and the width is 640. The DDCopyBitmap function locks the surface and copies the bitmap to the background buffer, and then stretch or compress the bitmap with the StretchBLT function. The code is as follows:
IF ((hr = pdds-> getdc (& hdc)) == DD_OK)
{
Stretchblt (HDC, 0, 0, DDSD.dwwidth, ddsd.dwheight, HDCImage, X, Y, DX, DY, SRCCopy);
PDDS-> ReleaseDC (HDC);
2.13 Transmission from the exterior surface block
DDEX2 is basically the same as DDEX1. DDEX2 opens a bitmap file and sent it to the background buffer and flip the background buffer and main surface. However, this is not particularly ideal for display bitmaps. DDEX3 extends the function of DDEX2, which adds two screen buffers, and each buffer stores a bitmap. Below is a part of the DOINIT function in DDEX3, the function is to create two exterior buffers:
// Create an offscreen bitmap.
DDSD.DWFLAGS = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
DDSD.DDSCAPS.DWCAPS = DDSCAPS_OFFSCREENPLAIN
DDSD.DWHEIGHT = 480;
Ddsd.dwwidth = 640;
DDRVAL = LPDD-> CreateSurface (& DDSD, & lpddsone, NULL);
IF (DDRVAL! = DD_OK)
{
Return INITFAIL (HWND);
}
// CREATE ANOTHER OFFSCREEN BITMAP.
DDRVAL = LPDD-> CreateSurface (& DDSD, & LPDDSTWO, NULL);
IF (DDRVAL! = DD_OK)
{
Return INITFAIL (HWND);
}
As can be seen from the code, DWFlags indicates that the program uses the DDSCAPS structure and sets the high and width of the buffer. The DDSCAPS_OFFSCREEN flag in the DDSCAPS structure is specified that the surface is the exterior buffer, which will be high and wide to 480 and 640 in the DDSurfaceDesc structure, and then use the iDirectdraw :: CreateSurface method to create the surface. Because the size of the outer surface of the two screens, create a second buffer only need to run idirectdraw :: CreateSurface (of course, different pointers). You can also set DDSCAPS_SYSTEMMORY or DDSCAPS_VIDEMEMORY in DDSCAPS to specify that the screen outer buffer is placed in the display memory or system memory. Place the bitmap in the display memory can speed up the data transfer speed between the background buffer and the exterior surface, which is very important in bitmap animation. However, if you specify DDSCAPS_VIDEOMEMORY for the exterior buffer and there is not enough display memory to transfer the entire bitmap. When the surface is created, the program returns a DDERR_OUTOFVIDEMEMORY error value.
2.14 Turn the bitmap file into the exterior surface
After creating two exterior surfaces, DDEX3 uses the INITSURFACES function to load the bitmap from the frntback.bmp file to both surfaces. The INITSURFACES function uses the DDCopyBitmap function to transfer two bitmaps, the code is as follows:
// loadur bitmap resource.
HBM = (Hbitmap) loading (getModuleHandle (NULL), SZBitmap,
Image_bitmap, 0, 0, lr_createdibsection;
IF (hbm == null)
Return False;
DDCopyBitmap (LPDDsone, HBM, 0, 0, 640, 480);
DDCopyBitmap (LPDDSTWO, HBM, 0, 480, 640, 480);
DeleteObject (HBM);
Return True;
FRNTBACK.BMP file consists of two parts, half on, half is under. The DDCopyBitmap function is transferred to the first half of the first screen LPDDSOONE, and the lower half is transferred to the second surface LPDDSTWO. 2.15 Transfer the outer surface bit block to the background buffer
WM_TIMER contains code that writes the surface and flip surface. In DDEX3, it selects the appropriate screen of the appropriate screen and transfer its bit block to the background buffer, the code is as follows:
RcRect.Left = 0;
RcRect.top = 0;
RcRect.Right = 640;
RcRect.bottom = 480;
IF (PHASE)
{
PDDS = LPDDSTWO;
PHASE = 0;
}
Else {
PDDS = lpddsone;
Phase = 1;
}
While (1) {
DDRVAL = LPDDSBACK-> BLTFAST (0, 0, PDDS, & RCRECT, FALSE);
IF (DDRVAL == DD_OK)
{
Break;
}
"Phase" determines which to transfer which screen outline block is transferred to the background buffer, then call the idirectdrawsurface :: bltfast method to transfer the selected screen of the selected screen bit block to the background buffer, from the upper left corner 0, 0 begin. RcRect points to the RECT structure that defines the left corner of the exterior surface and the lower right corner. The last parameter is set to false or 0, indicating that the special transmission flag is not used. Once the exterior surface is transferred to the background buffer, the front method can be utilized to flush the background buffer and the main surface each other.
Third, create an animation
The above example is just written data into the background buffer, and then flip the background buffer with the main surface, and its speed is not too fast. The following examples DDEX4 and DDEX5 optimize real-time features, making it more like a real game. DDEX4 shows how to set the color key for the surface, how to use the iDirectdrawsurface :: BLTFast method to copy each part of the exterior surface to the background buffer to generate an animation. DDEX5 adds a read tone plate and changing the palette when moving.
3.1 Color Key and Chart Animation
In DDEX3, a primary way to place a bitmap is placed in an exterior buffer. DDEX4 uses the background and a series of wizards (sprite, this example is a ring) to load the exterior surface technology, then use, iDirectdrawsurface :: BLTFast method copies each part of the outer surface to the background buffer . In addition to the functionality in the previous example, the DOINIT function also includes code for setting the color key for the elf. Color Key is a color value for setting transparency. When the hardware block is written, other pixels are written by the pixels set to the Color Key, thereby generating a non-tum-like wizard on the surface. The code to set the color key is as follows:
// set the color key for this bitmap (Black)
// Note This Bitmap Has Black As Entry 255 in The Color Table.
// DDCK.DWCOLORSPA PartLOWVALUE = 0xff;
// DDCK.DWCOLORSPACEHIGHVALUE = 0xff;
// LPDDSONE-> SetColorKey (DDCKEY_SRCBLT, & DDCK);
// if we did not want to hard code the parapte index (0xff)
// We can Also Set The Color Key Like So ...
DDSETCOLORKEY (LPDDSONE, RGB (0, 0));
Two different methods for setting Color Key are given in Return True; The first method is 3 lines within the comment, set DDCOLORKEY first
In the range of the Color Key, then call the idirectdrawsurface :: setColorKey method Set the Color Key to black (false location diagram in black as a palette index 255). The second method is to call the DDSETCOLORKEY function to set the color RGB value to select Color Key, black is RGB (0, 0, 0). The DDSETCOLORKEY function calls the DDColormatch function, and the DDColormatch stores the color value of the 0,0 position pixels of the bitmap of the LPDDsone surface, and then assigns pixels of 0,0 positions with the supplied RGB value, and shields the color value.
After completing this step, the original color can reap back to 0,0 and use the correct color key to call the DDSetColorKey function. After the call is successful, the Color Key is placed in the DDColorKey structure DWColorspaceLowValue, and also copies to DWColorspacehighValue. Members, then call IDirectDrawSurface :: SetColorKey Set Color Key. CLR_INVALID is another useful variable in the DDSetColorKey and DDColormatch functions. If this value is used as a color key in DDSETCOLORKEY, the pixels in the upper left corner of the bit are used as the Color Key. To achieve this, you need to transfer the bitmap file all.bmp, turn the pixel value at 0,0 as black, save the changes, then change the call to DDSETCOLORKEY: DDSETCOLORKEY (LPDDSONE, CLR_INVALID); recompile DDEX4 DDEX4 will use the pixel values at 0,0 as the Color Key.
3.2 Animation in DDEX4
DDEX4 uses the red circle in all.bmp to create a simple animation. Animation consists of 3 locations of the ring. An example is determined by comparing GetTickCount in Win32 and starting running whether the time running is running. Which ring is retransmond, then use the idirectdrawsurface :: BLTFast method to transfer the background from the exterior surface LPDDsone bit block to the background buffer, then use The COLOR Key that has already set will write the circle into the background buffer. After all the rings are written to the background buffer, call the iDirectdrawsurface :: flip method to flip the background buffer and main surface.
3.3 Dynamic changes palette
DDEX5 describes any dynamically chase palettes during program runtime, although this is not always used in the game. DirectDraw really can control the palette well. The following code in DDEX5 puts the palette in the lower half of the all.bmp file:
// first, set all colors as unused
For (i = 0; i <256; i )
{
Toruscolors [i] = 0;
}
// Lock The Surface and Scan The Lower Part (The Torus Area)
// and repeember all the index's we find.
Ddsd.dwsize = sizeof (ddsd);
While (LPDDsone-> Lock (NULL, & DDSD, 0, NULL) == DDERR_WASSTILLDRAWING
// Now Search Through The Torus Frames and Mark Used Colors
FOR (Y = 480; Y <480 384; Y ) {for (x = 0; x <640; x )
{
Toruscolors [(Byte *) DDSD.LPSURFACE) [Y * DDSD.LPITCH X] = 1;
}
}
LPDDSONE-> UNLOCK (NULL);
Array TorusColors is used to specify the index value of the lower semi-semi-semi-palette in all.bmp, and the array is initialized to 0 before use. Then lock the outer surface of the screen to detect if a color index value is used. Array TorusColors starts at the 0th row of bitmaps, the color index value in the array is placed in one byte of the location of the memory by the bitmap surface, which is determined by the LPSURFACE member variable in the DDSurfaceDesc structure, LPSurface points The memory address (Y * LPITCH X) corresponding to bitmap (0, 480). The color index value set in the array is used to detect which colors in the palette are replaced. Because there is no common color between the background and the red ring, there is only those color values that are combined with the circular circle to be replaced.
3.4 Replacing the palette
The updateframe function in DDEX5 is the same as the DDEX4, first writes the background block into the background buffer, and writes 3 red circles to the foreground. However, before the flip surface, the UpdateFrame creates a palette index value created by the DOINIT function, and the code is as follows:
// Change the Palette
IF (LPDDPAL-> GetENTRIES (0, 0, 256, PE)! = DD_OK)
{
Return;
}
For (i = 1; i <256; i )
{
IF (! toruscolors [i])
{
CONTINUE;
}
PE [i] .pled = (PE [i] .pered 2)% 256;
PE [i] .pegreen = (PE [i] .pegreen 1)% 256;
PE [i] .peblue = (PE [i] .peblue 3)% 256;
}
IF (LPDDPAL-> setENTRIES (0, 0, 256, pe)! = dd_ok)
{
Return;
} IDirectdrawpalette :: getNtries method query the value of the palette in the DirectDrawPalette object, because the value of the palette entity points to PE is valid, the method returns DD_OK, and the program continues to run. Then the loop detection whether TorusColors is set to 1 in the initialization, and if the index value is set to 1, the red, green, and blue value of the palette pointing to the PE is replaced. After all the marked palette entities are replaced, then call the IDirectDrawPalette :: STENTRIES method to truly change the entities in DirectDrawPalette. If the palette has been set to the main surface, the above change will be completed immediately. After completing this, the rest is the same flip surface as in front.
Four use coverage surface
This example will use the DirectX SDK MOSQUITO sample program to explain how to use DirectDRAW and hardware support coverage surfaces in the program step by step. MOSQUITO uses the flip chain override the surface of the surface without bit blocks to the main surface to display the motion bitmap on the desktop. The MOSquito program adjusts the feature of the cover surface to accommodate hardware.
4.1 Creating a major surface
To use the overlay surface, you must first initialize a major surface, and the override surface will be displayed on the main surface. Mosquito creates a major surface with the following code:
// Zero-Out The Structure and Set The DWSIZE MEMBER.
ZeromeMory (& DDSD, SIZEOF (DDSD)); DDSD.dwsize = SizeOf (DDSD);
// set flags and create a primary surface.
DDSD.DWFLAGS = DDSD_CAPS;
DDSD.DDSCAPS.DWCAPS = DDSCAPS_PRIMARYSURFACE;
DDRVAL = G_LPDD-> CreateSurface (& DDSD, & G_LPDDSPRIMARY, NULL);
The program first initializes the DDSurfaceDesc structure that will be used, and then set the appropriate flag to call the IDirectDraw2 :: createSurface method to create the main surface. In the call to the method, the first parameter is a pointer to the DDSurfaceDesc structure that will be created; the second parameter is a pointer to a variable, and if the call is successful, the variable will receive the pointer of the IDirectdrawSurface interface; third The parameter is set to NULL indicates that there is no COM collection.
4.2 Detecting hardware to cover coverage
After initializing DirectDraw, you need to detect whether the device supports the cover surface. Because DirectDRAW cannot simulate overwritten, if the hardware does not support overwriting, you cannot continue the following work. You can get the ability to detect overlay support for hardware device drivers with iDirectDraw2 :: getCaps. After calling the method, check whether DWFlags members in the DDCaps structure contains the DDCaps_overlay flag. If there is, it indicates that support coverage, otherwise it will not be supported.
The following code is part of the MOSquito program that shows how to detect hardware coverage support capabilities:
Bool isoverlayssupported ()
{
DDCAPS Capsdrv;
HRESULT DDRVAL;
// Get Driver Capabilities To Determine overlay support.
ZeromeMory (& CapsDRV, SIZEOF (CAPSDRV));
Capsdrv.dwsize = sizeof (capsdrv);
DDRVAL = g_lpdd-> getCaps (& CapsDRV, NULL);
IF (Failed (DDRVAL))
Return False;
// does the Driver Support overlays in the current mode?
// (Currently The DirectDraw Emulation Layer Does Not Support overlays.
// Overlay Related Apis Will Fail without Hardware Support.
IF (! (Capsdrv.dwcaps & DDCAPS_OVERLAY))
Return False;
Return True;
}
The program first calls the iDirectdraw2 :: getCaps method to get the power of the device driver. The first parameter is the address pointer of the DDCAPS structure; because the program does not need to shut down simulation information, the second parameter is set to NULL. After obtaining the driver's ability, the program uses logic "and" to check if the dwflags member contains the DDCaps_overlay flag. If not, the program returns FALSE indicates that failed. If so, returns True to indicate that the display device supports the cover surface.
4.3 Creating a coverage surface
If you know that the display device supports the overlay surface, you can create one. Since there is no specification that the device supports the standards that covers the surface, it is not expected to create a surface of any pixel format. Also, do not expect the first time to create a coverage surface will succeed. Therefore, it is necessary to prepare an attempt to create multiple creating until there is a work. The MOSQUITO program follows the principle of "Best Case to Worst Case" when you create a surface, first try to create a three buffer flip-flush complex coverage surface. If the attempt fails, the program changes the method to configure it with other universal rapid formats. The following code is the performance of this idea:
ZeromeMory (& DDSDOVERLAY, SIZEOF (DDSDOVERLAY));
DDSDOVERLAY.DWSIZE = SizeOf (DDSDoverLay);
DDSDOVERLAY.DWFLAGS = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT;
DDSDOVERLAY.DDSCAPS.DWCAPS = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEMEMORY
DDSDOVERLAY.DWWIDTH = 320;
DDSDOVERLAY.DWHEIGHT = 240;
DDSDOVERLAY.DWBACKBUFFERCOUNT = 2;
// try to create an overlay surface use one of the pixel formats in ou
// Global List.
i = 0;
Do {
DDSDOVERLAY.DDPFPIXELFORMAT = g_ddpfoverlayformats [i];
// Try to create the overlay surface
DDRVAL = G_LPDD-> CreateSurface (& DDSDOVERLAY, & G_LPDDSOVERLAY, NULL);
} While (Failed (DDRVAL) && ( i The program sets the flags and values in the DDSurfaceDesc structure to reflect the three buffer flops flip complex cover surface, and then perform a loop. In the loop, the program attempts to create a requesting surface with a variety of commonly used pixel formats. If the attempt is successful, the loop is terminated. If the trial fails, it is very likely that the display of the hardware does not have enough display memory support three buffers or the hardware does not support the flip cover surface. In this case, use a single non-flip cover surface under the minimum required configuration, the code is as follows: // if we failed to create a triple buffered complex overlay surface, TRY // Again with a single non-flippable buffer. IF (Failed (DDRVAL)) { DDSDOVERLAY.DWBACKBUFFERCOUNT = 0; DDSDOVERLAY.DDSCAPS.DWCAPS = DDSCAPS_OVERLAY | DDSCAPS_VIDEMEMORY DDSDOVERLAY.DWFLAGS = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; // Try to create the overlay surface DDRVAL = G_LPDD-> CreateSurface (& DDSDOVERLAY, & G_LPDDSOVERLAY, NULL); i = 0; DO { DDSDOVERLAY.DDPFPIXELFORMAT = g_ddpfoverlayformats [i]; DDRVAL = G_LPDD-> CreateSurface (& DDSDOVERLAY, & G_LPDDSOVERLAY, NULL); WHILE (Failed (DDRVAL) && ( i // We couldn't create an overlay surface. EXIT, RETURNING FAILURE. IF (Failed (DDRVAL)) Return False; } The above code refers to a single non-flip overlay surface on the DDSurfaceDesc structure, and then attempts to create a surface through a pixel format loop. If the created surface is successful, the loop stops. If it is not successful, the program returns false indicates that the creation surface failed. After successfully created the overlay surface, the bitmap can be displayed in it. 4.4 Displaying the cover surface You can display it after you create a coverage. Typically, the hardware adds alignment constraints on the location and pixel format of the covered rectangle. In addition, it is also necessary to explain the minimum required tensile factor to successfully display the cover surface by adjusting the width of the destination rectangle. The MOSQUITO program is prepared and display the overlay surface as follows. 4.4.1: Test the minimum requirements displayed Most of the display hardware will add constraints when displaying overrides. You must take care of the overlay to satisfy these constraints. Information about these constraints can be obtained by calling the IDirectDraw2 :: getCaps method. The structure filling structure DDCAPS contains information about coverage and use constraints. Different hardware constraints are different, so you must always look at the flag contained in the DWFlags member to determine which constraint is. The MOSQUITO program begins to get hardware capabilities, and then use the method based on the minimum tensile factor, as shown below: // Get Driver Capabilities DDRVAL = g_lpdd-> getCaps (& CapsDRV, NULL); IF (Failed (DDRVAL)) Return False; // Check the minimum stretch and set the local variable acidingly. IF (Capsdrv.dwcaps & DDCAPS_OVERLAYSTRETCH) USTRETCHFACTOR1000 = (Capsdrv.dwminoverlaystretch> 1000) ? Capsdrv.dwminOverlaystretch: 1000; Else USTRETCHFACTOR1000 = 1000; The above code calls IDirectDraw2 :: getCaps method to get hardware capabilities. In this example, the first parameter is a pointer to the DDCAPS structure; the second parameter is NULL, indicating that there is no need to obtain information about simulation. The program retains the minimum tensile factor in a temporary variable for use. If the tensile factor reported in the driver is greater than 1000, it indicates that the driver requires all the destination rectangles to stretch along the direction of the X axis. For example, if the tensile factor is 1.3, the source rectangle is 320 pixels, and the destination rectangle must have at least 416 (320 x 1.3 = 416) pixels wide. If the tensile factor reported in the driver is less than 1000, it indicates that the driver can display smaller coverage than the source rectangle, but cannot be extended. The following code is the value of the measurement of the size alignment constraint of the driver: // Grab Any Alignment Restrictions and Set The Local Variables acordingly. USRCSIZEALIGN = (Capsdrv.dwcaps & ddcaps_alignsizesrc)? Capsdrv.dwalignsizesrc: 0; UDESTSIZEALIGN = (Capsdrv.dwcaps & ddcaps_alignsizesrc) Capsdrv.dwalignsizedest: 0; More temporary variables are used in Example to save the size alignment constraints obtained from DwalignSizesRC and DwalignSizeDest members. These values provide information about the pixel width alignment constraint, and need to be used in the later set source rectangle and the destination rectangle. The source rectangles and destination rectangles must be multiple multiple of these values. Finally, the program determines the value of the destination rectangular boundary alignment constraint: // set the "Destination Position Alignment" Global So We Won't have to // Keep Calling getCaps () Every Time We move the overlay surface. IF (Capsdrv.dwcaps & DDCAPS_ALIGNBOUNDARYDEST) g_dwoverlayxpositionalignment = capsdrv.dwalignboundaryDest; Else g_dwoverlayxpositionalignment = 0; The above code uses a global variable to save the value of the rectangular boundary constraint, which is obtained from the DwalignBoundaryDest member, which will be used when the program is reset later. You must set the X coordinates in the upper left corner of the destination rectangle to align in the pixel format. That is, if the value is 4, it can only specify the destination rectangle of the X coordinates of the upper left corner of 0, 4, 8, 12. The MOSQUITO program is first displayed at 0,0, so it is not necessary to obtain constraint information before the first display overlay is displayed. But because the implementation of different applications may be different, you may need to check this information before displaying overrides to adjust the destination rectangle. 4.4.2 Setting the source rectangle and destination rectangle After obtaining the overlay constraint of the driver, the value of the source rectangle and the destination rectangle should be set to ensure that the overlay can be displayed correctly. The following code sets the feature of the source rectangle: // set initial value in the source. Rs.left = 0; rs.top = 0; Rs.right = 320; RS.BOTTOM = 240; // Apply Size Alignment Restrictions, if Necessary. IF (Capsdrv.dwcaps & DDCAPS_ALIGNSIZESRC && USRCSIGN) Rs.right - = rs.right% usrcsizEalign; The above code sets an initial value that contains the entire surface size. If the device driver requires size alignment, the program adjusts the source rectangle to ensure. The program is adjusted to the width of the source rectangle, which is less than the initial value, because if it is not completely recreated, it is not possible to extend the width. After setting the source rectangle, you need to set and adjust the size of the destination rectangle. This process needs a little more work because the destination rectangle may need to be stretched first to comply with the size alignment constraint. The following code sets and adjusts the size of the destination rectangle according to the minimum tensile factor: // set up The destination Rect, Starting with The Source Rect Values. // We use the source rect Dimensions Instead of the Surface Dimensions in // Case the Differ.rd.LD = 0; rd.top = 0; Rd.right = (RS.right * uStretchFactor1000 999) / 1000; // (Add 999 Avoids Integer Truncation Problems.) // (this isn't Required by DDRAW, But We'll Stretch the // HEIGHT, TOO, TO Maintain Aspect Ratio. Rd.bottom = rs.bottom * uStretchFactor1000 / 1000; The front code first sets the upper left corner position of the object, and then sets the width of the destination rectangle according to the minimum tensile factor. When adjusting the rectangle according to the tensile factor, the payment is added in the product of the width and tensile factor, which is to avoid the interception of the integer, and the cutting of the integer causes the rectangle as the minimum tensile factor. The program also stretched the height of the rectangle after the stretch width. However, the stretching of the height is not necessary, here is just to maintain the phenomenon of distortion in order to maintain the growth rate of the bitmap. After the stretching rectangle, the program is adjusted to keep and the magnitude alignment constraint, the following is the corresponding code: // Adjust The Destination Reth Width To Comply with any imposed // Alignment Restrictions. IF (Capsdrv.dwcaps & DDCaps_alignsizedest && UDestsizEalign) Rd.right = (int) ((Rd.right udestsizEalign-1) / udestsizEalign) * uDestsizealign; The program detects the logo of the hardware capabilities, check whether the driver has added rectangular alignment constraints. If so, the width of the increase in the rectangle is increased to satisfy the size alignment constraint. Here, the adjustment of the rectangle is extended its width without reducing its width, as the width may result in a small destination rectangle than the minimum tensile factor, thereby causing the display coverage surface failure. 4.4.3, display coverage surface After setting the source rectangle and the destination rectangle, it can be displayed. If the preparation date before the overlay is displayed correctly, the display coverage will be simple. The MOTO program uses the following code to display the overlay: // set the flags we'll send to updateoverlay DwupdateFlags = DDOVER_SHOW | DDOVER_DDFX; // Does the overlay hardware support source color keying? // if so, we can hide the black background involved the image. // this probably Won't work with yuv formats IF (Capsdrv.dwcKeycaps & DdcKeycaps_srcoverlay) DwupdateFlags | = DDOVER_KEYSRCOVERRIDE; // Create An Overlay FX Structure So We can Specify A Source Color Key. // this information is ignored if the ddover_srckeyoverride flag isn't set. ZeromeMory (& Ovfx, SizeOf (OVFX)); Ovfx.dwsize = sizeof (ovfx); Ovfx.dcksrccolorKey.dwcolorspacelowValue = 0; // specify black as the color keyovfx.dcksrcolort.dwcolorspacehighValue = 0; // Call Updateoverlay () To Displays The overlay on the screen. DDRVAL = g_lpddsoverlay-> Updateoverlay (& RS, g_lpddsprimary, & rd, dwupdateflags, & ovfx); IF (Failed (DDRVAL)) Return False; The program started to set the DDOVER_SHOW and DDOVER_DDFX flags in the temporary variable dwupdateflags, indicating that the overlay is the first time, and the hardware should use the effect information contained in the DDOverLayFX structure. Then, the program checks the DDCAPS structure to determine if the override supports the source color Key. If so, the DDOVER_KEYSRCOVERRIDE flag is included in the dwupdateflags variable, and the program also sets the Color Key accordingly. After the preparation is completed, the program calls IDirectDrawSurface3 :: updateoverlay method to display overwriting. In the call to the method, the first parameter and the third parameter are the address that has been adjusted source rectangles and destination rectangles. The second parameter is to override the address of the main surface displayed thereon. The fourth parameter is a flag included in the DWUPDATEFLAGS variable placed in previously prepared. The fifth parameter is the address of the DDOVERLAYFX structure, and the members in this structure will match the same flag. If the hardware only supports a coverage surface and the surface is being used, the UpdateoverLay method will fail and return DDERR_OUTOFCAPS. In addition, it is possible that the minimum tensile factor of hardware report is too small. After the UpdateoverLay method fails, you need to try to reduce the width of the destination rectangle to cope with this possibility. However, this situation rarely occurs, but only simply returns an error message in Mosquito. 4.5 Update overwriting display location After displaying the cover surface, sometimes you may not need to operate the left left. However, some software also needs to reset override, change the display position override. The MOSquito program uses the iDirectdrawsurface3 :: setoverlayPosition method to reset overwrites, the code is as follows: // set X- and y-coordinates ...... // We need to check for any alignment restrictions on the x position // and align it if nesessary. IF (g_dwoverlayxpositionalignment) Dwxaligned = g_noverlayxpos- g_noverlayxpos% g_dwoverlayXPositionalIgnment; Else Dwxaligned = g_noverlayXPOS; // set the overlay to its new position. DDRVAL = g_lpddsoverlay-> setoverlayPosition (dwxaligned, g_noverlayypos); IF (DDRVAL == DDERR_SURFACELOST) { IF (! restoreallsurface ()) Return; } The program begins to align the rectangular boundary alignment constraints to meet any destination boundaries that may exist. When the program previously calls the IDirectdraw2 :: getCaps method, the global variable g_dwoverlayXPositionAlignment has been set to the value reported by DWALIGNBOUNDARYDEST members in the DDCAPS structure. If there is a destination rectangle constraint, the program adjusts the new X coordinate as a pixel accordingly. If you do not meet the requirements, the cover cannot be displayed. After completing the adjustment of the X coordinate, the program calls IDirectDrawSurface3 :: setoverlayPosition method Re-placed overwrites. The first parameter in the call is the aligned new X coordinate, the new Y coordinate of the second parameter. These values indicate a new location in the upper left corner. There is no need to get width and height information here, because DirectDraw has obtained information on the surface size when it starts with the idirectdrawsurface3 :: updateoverLay method. If the failure caused by a reset overlay surface caused by one or more surfaces, the MOSQUITO program calls an application-defined function to restore these surfaces and reload their bitmaps. Note that do not use the coordinates of the right and lower boundaries of the target surface. Because IdirectDraw2 :: SETOVERLAYPOSITION method does not execute shear feature, uses those who may cause the coordinates that can cause the target surface boundary to cause the call to fail, and return DDERR_INVALIDPSITION. 4.6 Hide Covering Surface If you no longer need an overlay surface or you only want to be visible, you can set the appropriate flag to call the IDirectdrawSurface3 :: UpdateoverLay method to hide the overlay surface. MOSQUITO hides the cover surface with the following code and prepares to close the application: void destroyoverlay () { IF (g_lpddsoverlay) { // use updateoverlay () with the ddover_hide flag to remove an overlay // from the display. G_lpddsoverlay-> Updateoverlay (Null, G_LPDDsPrimary, Null, Ddover_Hide, Null); g_lpddsoverlay-> release (); g_lpddsoverlay = null; } } When calling idirectdrawsurface3 :: updateover, NULL is specified for the source rectangle and destination rectangles because there is no need for source rectangles and destination rectangles during hidden coverage. Similarly, the fifth parameters are also designated as NULL because it does not use overlay. The second parameter is a pointer to the target surface. Finally, the program uses the DDOVER_HIDE flag in the fourth parameter to indicate that the overlay will be canceled from the viewport. After the program is hidden, it releases its IDirectdrawSurface3 interface and set the global variable to null to make it invalid. For MOSQUITO programs, overwriting is no longer needed. If you need to use it in the application, you just need to simply hide override, not to release it, and then redisplay it when you need it. Other DirectDraw examples in five DirectDraw To master the application of DirectDraw, it should also be included in DirectX. SDK: The following example is described. 1, Stretch Describe how to create an unique mode in one window, which has the function of the shear bit block transmission and the stretching clip bit block transmission. 2, Donut The application of multiple monographs is described with interaction between the use of non-exclusive mode applications. 3, Wormhole This example describes the detailed palette animation. 4, DXVIEW Detailed describes how to get the ability to display hardware. Other Duel, IKLOWNS, FOXBEAR, PALETTE, and FLIP2D, etc., as long as these examples are more analytical, master DirectX's most basic technology DirectDraw is not difficult. Address: Huazhong University of Technology Postal code: 430074 Tel: 027-7545580 DirectX5.0 Tutorial DirectDraw