BLOG (http://blog.9cbs.net/holyfire) from Holyfire
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 take advantage of the Message Arakelian Soft to develop ActiveX control DirectStudio98 or Tegosoft's Tegosoft ActiveX for Visual Basic for Visual Basic5.0 users. 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.
First, configure DirectX SDK1.1, configure Microsoft Developer Studio to compile the DirectX SDK, you need to open a new Project Workspace, insert the appropriate file, set the environment variable to find the compiler to find the required link library and include files, below Describe all the processes of the settings. Start Microsoft Developer Studio, install the following steps to create the project:. In the File menu, select New. In the New dialog box, select Win32 Application in Project, enter DDEX1 in Project Name. Enter the location of the project file in the location text box, 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:. On the Project menu Select Add Toproject | Files. Browse to the C: / DX5SDK / SDK / Samples / DDEX1 directory, select all files. Select OK, this directory DDEX1.CPP, Ddex1.rc, resource.h joined the project. Then set the path to the file:. In the Tools menu, select Options, pop up the options dialog box. Select Directories, select Include Files in the Show Directories FOR list box. On the Directories: list box Double-click the blank line at the bottom of the list, enter C: / DX5SDK / SDK / INC. Agitated another path C: / DX5SDK / SDK / Samples / Misc. Select the OK button, set the link library directory: Library Files in the show directories for list box. Double click on the Directories: list box Double click The bottom blank line, enter C: / DX5SDK / SDK / LIB. Click the OK button. Finally set the module that is linked when establishing an application:. Click Settings in the Project menu. Select Link. Select General. In the Category drop-down box, select General. 1.2, formulated 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. The following is the path to the file and link library module: @echo offset path = c: / program files / devstudio / sharedide / bin; c: / program files / devstudio / vc / bin;% PATH% SET INCLUDE = C: / Program Files / devStudio / VC / include; 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% joining the above content to AutoExec.bat. Enter NMAKE in the example of an example will create a debug directory 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. 3, configuring DirectX SDK for Borland C 5.0 Although DirectX 5 SDK is prepared for Visual C users, but Microsoft has not forgotten numerous Borland C users, so the DirectX's Borland C library is also available in DirectX SDK. However, it may not be the Borland C library in the DirectX SDK after the competition (guess). 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. Second, the 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 handle the object. Also need to create an instance of one or more DirectDrawSurface objects to display the game. Ddex1 first creates a DirectDraw object, then create a primary surface and a background buffer (back 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.
1. First, the DirectDraw object DDEX1 program is initialized in the DOINIT function contains the initialization code of DirectDraw: // Creating the primary DirectDraw object DDRVAL = DirectDrawCreate (NULL, & LPDD, NULL); if (DDRVAL == DD_OK) {// Get exclusive mode DDRVAL = LPDD-> SetCooperativeelevel (HWnd, DDSCL_EXCLUSIVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELEVELE (DDRVAL == DD_OK) {ddrval = LPDD-> setDisplayMode (640, 480, 8); if (ddrval == dd_ok) {// Creating a background buffer the main surface region 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) {// Gets the pointer of the background buffer DDSCAPS.DWCAPS = DDSCAPS_BACKBUFFER; DDRVAL = LPDDSPRIMARY-> GetAttachedSurface (& DDSCAPS, & LPDDSBACK); if (DDRVAL == DD_OK) {// Draw some text if (LPDDSPRIMARY-> Getdc (& HDC) == DD_OK) {setBkcolor (HDC, RGB (0, 0, 255)); setTextColor (HDC, RGB (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 IF of the flip page (SetTimer (hwnd, timer_id, timer_rate, null) {Return TRUE; }}}}}} WSPRINTF (BUF, "Direct Draw Init Failed (% 08LX) / N", DDRVAL); ............ The following detailed description of the creation of the DirectDraw object initialization and prepares the surface. Each step. 2. Creating a DirectDraw object Creating an instance of a DirectDraw object, you should use the DirectDrawCreate API function, you can also use the COCREATEINSTANCE function in COM. DirectDrawCreate characterizes the display device with a global unified marker Guid (GlobalLoBally Unique Identifier), in most cases, GUID is NULL (using the system's default display device, "empty device"); pointer points to the address of the DirectDraw object; Three parameters are always NULL (for future expansion). 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 legal DirectDraw object} else {// DirectDRAW object cannot be created}
3, Set the display mode Setting the display mode of the DirectDRAW application requires two steps: first call the iDirectdraw :: setCoopeRarativeEvelEvelLevel method to set the requirements in this mode, once the requirements are determined, then 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 :: SetCooperativeLevel Method: HRESULT ddrval; LPDIRECTDRAW lpDD; // already created by DirectDrawCreate ddrval = lpDD-> SetCooperativeLevel (hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); if (ddrval == DD_OK) {// fullscreen Excise mode Setting success} Else {// 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. 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 create DDRVAL = LPDD -> setDisplayMode (640, 480, 8); if (DDRVAL == DD_OK) {// Change mode Success} Else {// Display mode can not change // The system may not support this mode} When setting the display mode, it should 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.
5. Creating a flippable surface (FLIPPABLE SURFACE) After setting the display mode, you must create the surface where the application is placed. 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.
6. Define the first step in which the surface requirement to create 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 creates the flag required to convert the flip surface: // Create a main surface DDSD.dwsize = sizeof (DDSD) with a background buffer; DDSD.DWFLAGS = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; DDSD.DDSCAPS .dwcaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; DDSD.DWBACKBUFFFERCOUNT = 1; Example, 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 DDSCAPS_VIDEOMEMORY is specified, there is not enough display memory to create a surface, iDirectdraw :: CreateSurface will return a DderR_OutofVideoMory error.
7. Creating the surface fills the DDSurfaceDesc structure, you can use this structure and LPDD, LPDD is a pointer to the DirectDraw object created with the DirectDrawCreate method. 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. When the main surface of the pointer is available, you can call the method of obtaining IDirectDrawSurface :: GetAttachedSurface back buffer pointer, as follows: 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 success, the LPDDSBack parameter points to the background buffer by providing the address of the main surface and setting the DDSCAPS_BACKBuffer flag.
8, after the coloration surface creates the main surface and the background buffer, DDEX1 submits some text to the main surface and background buffer using the standard Windows GDI function, 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 to lock the handle 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.
9. After the writing surface and the flip surface are completed, 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 (bactage) {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 lock, 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;} f (DDRVAL = DDERR_SURFACELOST) {if (DDRVAL = LPDDSPRIMARY- & G> VAL! = DD_OK) {Break;}} f (DDRVAL! = DDERR_WASSTILLDRAWING) {Break;}} example, LPDDSPRIMARY indicates the main surface And its posterior 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, and idirectdrawsurface :: flip returns DDERR_WASSTILLDRAWING. In this example, idirectdrawsurface :: flip continues to loop until returns DD_OK ..
10. Release the 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 (LPDDSPRIMARY! = null) {lpddsprimary-> release (); lpddsprimary = null;} lpdd-> release (); lpdd = null;}} / * finiobjects * / program detection DirectDRAW object The pointer (LPDDSPRIMARY) of the pointer (LPDD) and the DirectDrawSurface object is equal to NULL, which is obviously not NULL in this example. 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.
11. Tune the position of the bitmap, such as Ddex1, the DOINIT function is the initialization function of DDEX2, the same, 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 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 a DirectDrawPalette object as follows: PDD-> CreatePalette (DDPCaps_8bit, APE, & DDPAL, NULL); Return DDPAL; when IdirectDraw: : When the CreatePalette method returns, ddpal points to the DirectDrawPalette object. 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).
12. Set the palette to create a palette after transferring the bitmap into the back buffer, you can transfer the DirectDrawPalette object's pointer DDPAL to the main surface by calling the IDiretTe method, the code is as follows: ddrval = lpddsprimary-> setPalette (LPDDPAL); if (DDRVAL! = DD_OK) // setPalette failed calls 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 The palette is set to it. After the object is linked together with DirectDrawPalette DirectDrawSurface objects, DDEX2 Back.bmp using the following code files into the back 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 bitmap into memory, use the getObject function to get the size of the bitmap, then get the size of the background buffer to place bitmap with the following code: // 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. 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, srcopy); PDDS-> ReleaseDC (HDC);} 13, transmit Ddex2 from the exterior surface block transmission DDEX2 is basically the same . 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.
Here is part of DDEX3 in doInit function, function is to create a buffer zone outside the two screens: // 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);} You can see from the code, dwflags indicates the program using the DDSCAPS structure and sets the high and wide 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. 14. After the bitmap file is built into the exterior surface, DDEX3 uses the INTSURFACES function to load the bitmap from the frntback.bmp file to both surfaces. InitSurfaces function using two bitmaps transferred DDCopyBitmap function, as follows: // Load our bitmap resource hbm = (HBITMAP) LoadImage (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 by two Part of the composition, half on, half is below. 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.
15. Transfer the exterior surface bit block to the background buffer WM_TIMER contains the code of the write surface and the flip surface. In DDEX3, it selects 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 = 480; 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 screen out of the block is transferred to the background buffer, then call the iDirectdrawsurface :: BLTFast method to transfer the selected screens to the background buffer Starting from the position of the upper left corner 0, 0. 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, the examples of creating animations are just written to the background buffer, and then turn the background buffer with the main surface, and the 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.
1. Color Key and Bitmap Animation describes a primary way to place bitmaps in an exterior buffer in DDEX3. 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. To set the color key code as follows: // set the color key for this bitmap (black) // Note this Bitmap Has Black as entry 255 in the color table. // ddck.dwcolorspacelowvalue = 0xff; // DDCK.DWCOLORSPACEHIGHVALUE = 0xFF; // LPDDSONE-> setColorKey (DDCKEY_SRCBLT, & DDCK); // if we did not want to hard code the para. 0, 0)); Return True; two different methods of setting the Color Key are given. The first method is the 3 line within the comment, first set the range of the Color Key in the DDColorKey structure, then call the idirectdrawsurface :: setColorKey method Set the color key to black (false location map in black as a palette index Item 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.
2, the animation DDEX4 in DDEX4 uses the red circle in all.bmp to create a simple animation. Animation consists of 3 spaces of the circles. 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, dynamic change the palette DDEX5 describes any dynamically changed the palette when the program is run, 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 Remember 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 half of the upper half of all.bmp 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.
4. Replacing the UpdateFrame function in DDEX5 in DDEX5 is the same as 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, 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] .pled 2)% 256; PE [i] .pegreen = (PE [i] .pegreen 1)% 256; PE [i] .peblue = (PE [i] .peblue 3)% 256;} if (lpddpal-> setENTRIES 0, 0, 256, pee)! = 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, program Continue 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. Fourth, using the overlay surface This example will use the DirectX SDK's 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.
1. Creating a main surface To use the overlay surface, you must first initialize a major surface, the overlay surface will be displayed on the main surface. MOSQUITO creates a master 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); DDSURFACEDESC initialized program configuration to be used, then set The appropriate logo calls 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. 2. After detecting the support of the overlay to initialize 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 Areoverlayssupported () {DDCAPS Capsdrv; HRESULT DDRVAL;
// Get Driver Capabilities To Determine Overlay Support. ZerMemory (& 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 ability to get 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.
3. Create an overlay 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 this idea of performance: 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.DWBACKBUFFEFFERCOUNT = 2;
// Try to create an overlay surface using one of the pixel formats in our // 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
// We couldn't create an overlay surface. EXIT, RETURNING FAILURE. IF (Failed (DDRVAL)) Return False;} The above code is the logo and value of the DDSurfaceDesc structure reflects a single non-flip cover surface, then Create a surface through a loop in a pixel format. 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. Display the overlay surface can display it after the overlay surface is created. 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.1: The minimum requirement display of the display is constrained in the display hardware when the overlay is displayed. 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 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 accordingly if (capsDrv.dwCaps & DDCAPS_OVERLAYSTRETCH) uStretchFactor1000 = (capsDrv.dwMinOverlayStretch> 1000) capsDrv.dwMinOverlayStretch: 1000; else uStretchFactor1000 = 1000; The above code calls IDirectDraw2 :: GetCaps Methods The ability to get hardware. 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 description of the driver code size measuring alignment constraint value: // 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 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: // 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 hold the value of the destination rectangle boundary constraints, the value is from a member of the dwAlignBoundaryDest come again when the cover is placed after the program Will be used. 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.
2. Setting the source rectangle and the 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 Rect. Rs.Left = 0; rs.top = 0; rs.right = 320; rs.bottom = 240; // Apply Size Alignment Restrictions, if Necessary. if (Capsdrv.dwcaps & DDCAPS_ALIGNSIZESRC & DDCSIGN) rs.right - = rs.right% usrcsizEalign; the above code sets the initial value of 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 stretching factor: // set up the destination review, starting with the source rect Dimensions INSTEAD OF THE SURFACE DIMENSIONS INSTETEAD OF THE SURFACE DIMENSIONS INSTED of THE SURFACE DIMENSIONS INSTER Differ. rd.Left = 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 top left of the objective rectangle The angular position, then set 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 sizes alignment constraints. The following is the corresponding code: // adjust the destination rect's width to comply with any imposed // alignment rest (Capsdrv.dwcaps & DDCAPS_ALIGNSISIZEDEST & D) UDESTSIAALIGN) RD.right = (int) ((RD.right UDestsizeAlign-1) / udestsizealign) * udestsizEalign; program detects the logo of hardware capabilities, check whether the driver is added 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. 3. When the cover surface is displayed, it can be displayed after setting the source rectangle and the destination rectangle. If the preparation date before the overlay is displayed correctly, the display coverage will be simple. Mosquito program with the following code to display the cover:? // 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 around The image. // this probably Won't work with yuv formats if (capsdrv.dwckeycaps & ddckeycaps_srcover) 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 is not set ZeroMemory (& ovfx, sizeof (ovfx));.. Ovfx.dwSize = sizeof (ovfx);
Ovfx.dcksrccolorKey.dwcolorspaceLowValue = 0; // specify black as the color key ovfx.dcksrcolorty.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; program begins in temporary variable dwUpdateFlags in DDOVER_SHOW and DDOVER_DDFX flags indicate that the overlay is displayed for the first time, and the hardware should be done using 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. 5. Update the overwritten display location Show After the cover is covered, it may sometimes do 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 override, the code is as follows: // set x and y-coordinates. 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 (! RestoreAllSurfaces ()) return;} program begins aligned rectangular to meet any possible Destination rectangular boundary alignment constraint. 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. 6. Hide overwriting surface If you no longer need an overlay surface or just want the overlay, you can set the appropriate flag to call the IDirectDrawSurface3 :: Updateoverlay method to hide the overlay surface. Mosquito cover the surface with the following code to hide and is ready 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 :: UpdateOverlay, the source and destination rectangles specify NULL, because the process does not require the cover to hide the source Rectangle and destination rectangles. 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.
5. Examples of other DirectDraw in DirectDraw