DONUT.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       donut.cpp
  6.  *
  7.  *  This sample takes the ddraw donut sample from the DirectX SDK and
  8.  *  adds an animating text string to it using DirectX Animation.  A
  9.  *  direct draw primary surface is created in this file and passed to
  10.  *  the DAView object for rendering.
  11.  *
  12.  ***************************************************************************/
  13. #define NAME "Donut"
  14. #define TITLE "Donut"
  15. #define WIN32_LEAN_AND_MEAN
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include <ddrawex.h>
  19. #include "ddutil.h"
  20. #include "dxa.h"
  21. char szBitmap[] = "DONUT";
  22. BOOL            gExclusive = FALSE;
  23. BOOL            bPaused = FALSE;
  24. HWND            hWndMain;
  25. IDirectDrawFactory      *lpDDF;
  26. LPDIRECTDRAW            lpDD;           // DirectDraw object
  27. LPDIRECTDRAWSURFACE     lpDDSPrimary;   // DirectDraw primary surface
  28. LPDIRECTDRAWSURFACE     lpDDSDA;        // Offscreen surface for DA
  29. LPDIRECTDRAWSURFACE     lpDDSDonut;     // Offscreen surface for donut
  30. LPDIRECTDRAWPALETTE     lpDDPal;        // DirectDraw palette
  31. LPDIRECTDRAWCLIPPER     lpClipper;      // Clipper for the primary surface
  32. BOOL                    bActive;        // is application active?
  33. RECT                    windowRect;     // windows' client rectangle
  34. /*
  35.  * releaseSurfaces
  36.  *
  37.  * Release the global surfaces and clipper.
  38.  */
  39. void releaseSurfaces( void )
  40. {
  41.     if( lpDDSPrimary != NULL )
  42.     {
  43.         lpDDSPrimary->Release();
  44.         lpDDSPrimary = NULL;
  45.     }
  46.     if( lpDDSDA != NULL )
  47.     {
  48.         lpDDSDA->Release();
  49.         lpDDSDA = NULL;
  50.     }
  51.     if( lpDDSDonut != NULL )
  52.     {
  53.         lpDDSDonut->Release();
  54.         lpDDSDonut = NULL;
  55.     }
  56.     if( lpClipper != NULL )
  57.     {
  58.         lpClipper->Release();
  59.         lpClipper = NULL;
  60.     }
  61. /*
  62.  * finiObjects
  63.  *
  64.  * Finish with all objects we use; release them
  65.  */
  66. static void finiObjects( void )
  67. {
  68.     if( lpDD != NULL )
  69.     {
  70.         releaseSurfaces();
  71.         if( lpDDPal != NULL )
  72.         {
  73.             lpDDPal->Release();
  74.             lpDDPal = NULL;
  75.         }
  76.         lpDD->Release();
  77.         lpDD = NULL;
  78.     }
  79.     // Clean up the screen on exit
  80.     RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
  81.                      RDW_ALLCHILDREN );
  82. } /* finiObjects */
  83. /*
  84.  * initFail
  85.  *
  86.  * This function is called if the initialization function fails
  87.  */
  88. BOOL initFail( HWND hWnd, LPCTSTR msg )
  89. {
  90.     finiObjects();
  91.     MessageBox( hWnd, msg, TITLE, MB_OK );
  92.     DestroyWindow( hWnd );
  93.     return FALSE;
  94. } /* initFail */
  95. /*
  96.  * createSurfaces
  97.  *
  98.  * Create the front and back buffers.
  99.  */
  100. BOOL createSurfaces( void )
  101. {
  102.     HRESULT             ddrval;
  103.     DDSURFACEDESC       ddsd;
  104.     
  105.     // Create the primary surface
  106.     ddsd.dwSize = sizeof( ddsd );
  107.     ddsd.dwFlags = DDSD_CAPS;
  108.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  109.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  110.     if( ddrval != DD_OK )
  111.         return false;
  112.     if(!gExclusive)
  113.     {
  114.         //
  115.         // now create a DirectDrawClipper object.
  116.         //
  117.         ddrval = lpDD->CreateClipper(0, &lpClipper, NULL);
  118.         if( ddrval == DD_OK )
  119.         {
  120.             ddrval = lpClipper->SetHWnd(0, hWndMain);
  121.             if( ddrval == DD_OK )
  122.             {
  123.                 ddrval = lpDDSPrimary->SetClipper(lpClipper);
  124.             }
  125.         }
  126.         if( ddrval != DD_OK )
  127.             return false;
  128.     }
  129.     //
  130.     // Create a DirectDrawSurface to hand to Direct Animation.
  131.     //
  132.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  133.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  134.     ddsd.dwWidth = WINDOW_WIDTH;
  135.     ddsd.dwHeight = WINDOW_HEIGHT;
  136.     ddrval = lpDD->CreateSurface(&ddsd, &lpDDSDA, NULL);
  137.     if (ddrval != DD_OK)
  138.         return false;
  139.     lpDDPal = DDLoadPalette(lpDD, szBitmap);
  140.     if (lpDDPal)
  141.     {
  142.         lpDDSPrimary->SetPalette(lpDDPal);
  143.     }
  144.     lpDDSDonut = DDLoadBitmap(lpDD, szBitmap, 0, 0);
  145.     if( lpDDSDonut == NULL )
  146.     {
  147.         return false;
  148.     }
  149.     // set color key to black
  150.     DDSetColorKey(lpDDSDonut, RGB(0,0,0));
  151.     return true;
  152. } /* createSurfaces */
  153. /*
  154.  * recreateSurfaces
  155.  *
  156.  * The screen resolution or bitdepth has changed, re-create
  157.  * all surfaces.
  158.  */
  159. BOOL recreateSurfaces( void )
  160. {
  161.     releaseSurfaces();
  162.     if (createSurfaces())
  163.     {
  164.         return resetDXASurfaces(lpDDSDA);
  165.     }
  166.     return false;
  167. } /* recreateSurfaces */
  168. /*
  169.  * restoreAll
  170.  *
  171.  * Restore all lost objects
  172.  */
  173. BOOL restoreAll( void )
  174. {
  175.     HRESULT     ddrval;
  176.     ddrval = lpDDSPrimary->Restore();
  177.     if (ddrval == DDERR_WRONGMODE)
  178.     {
  179.         if (recreateSurfaces())
  180.             return true;
  181.     }
  182.     else if (ddrval == DD_OK)
  183.     {
  184.         ddrval = lpDDSDA->Restore();
  185.         if( ddrval == DD_OK )
  186.         {
  187.             ddrval = lpDDSDonut->Restore();
  188.             if( ddrval == DD_OK )
  189.             {
  190.                 DDReLoadBitmap(lpDDSDonut, szBitmap);
  191.                 return true;
  192.             }
  193.         }
  194.     }
  195.     return initFail(hWndMain, "DirectDraw: Can't Recreate Surfaces");
  196. } /* restoreAll */
  197. /*
  198.  * updateFrame
  199.  * 
  200.  * Decide what needs to be blitted next, wait for flip to complete,
  201.  * then flip the buffers.
  202.  */
  203. void updateFrame( void )
  204. {
  205.     static DWORD        lastTickCount = 0;
  206.     static int          currentFrame = 0;
  207.     static BOOL         haveBackground = FALSE;
  208.     DWORD               thisTickCount;
  209.     DWORD               delay = 17;
  210.     HRESULT             ddrval;
  211.     thisTickCount = GetTickCount();
  212.     if((thisTickCount - lastTickCount) <= delay)
  213.     {
  214.         return;
  215.     }
  216.     thisTickCount = GetTickCount();
  217.     if((thisTickCount - lastTickCount) > delay)
  218.     {
  219.         // Move to next frame;
  220.         lastTickCount = thisTickCount;
  221.         currentFrame++;
  222.         if(currentFrame > 59)
  223.         {
  224.             currentFrame = 0;
  225.         }
  226.     }
  227.     // DA doesn't like lost surface.  We should restore lost surface
  228.     // before asking DA to render.
  229.     if (lpDDSDA && lpDDSDA->IsLost() == DDERR_SURFACELOST)
  230.     {
  231.         // This function will destroy the window if failed.        
  232.         if (!restoreAll())
  233.             return;
  234.     }
  235.     // Ask DA to render to the DA surface the next image/sound for view1.
  236.     tick(view1);
  237.     // The image in the DA model (defined in dxa.cpp) has a background
  238.     // image, so we don't need to clear the background before we draw here.
  239.     RECT  donutSrcRect;
  240.     donutSrcRect.left   = currentFrame%10*64;
  241.     donutSrcRect.top    = currentFrame/10*64;
  242.     donutSrcRect.right  = currentFrame%10*64 + 64;
  243.     donutSrcRect.bottom = currentFrame/10*64 + 64;
  244.     // Blt the donut to the center of the DDSDonut surface.
  245.     RECT donutDestRect;
  246.     donutDestRect.left   = WINDOW_WIDTH/2-32;
  247.     donutDestRect.top    = WINDOW_HEIGHT/2-32;
  248.     donutDestRect.right  = donutDestRect.left + 64;
  249.     donutDestRect.bottom = donutDestRect.top + 64;
  250.     // Blit the donut for the next frame to the DA surface.
  251.     while( 1 )
  252.     {
  253.         ddrval = lpDDSDA->Blt(&donutDestRect, lpDDSDonut,
  254.             &donutSrcRect, DDBLT_WAIT|DDBLT_KEYSRC, NULL);
  255.         if( ddrval == DD_OK )
  256.         {
  257.             break;
  258.         }
  259.         if( ddrval == DDERR_SURFACELOST )
  260.         {
  261.             ddrval = restoreAll();
  262.             if( ddrval != DD_OK )
  263.             {
  264.                 return;
  265.             }
  266.         }
  267.         if( ddrval != DDERR_WASSTILLDRAWING )
  268.         {
  269.             return;
  270.         }
  271.     }
  272.     // Ask DA to render to the DA surface the next image/sound for view2.
  273.     tick(view2);
  274.     // Blit from the DA surface to the screen.
  275.     RECT daRect;
  276.     daRect.left = 0;
  277.     daRect.top = 0;
  278.     daRect.right = WINDOW_WIDTH;
  279.     daRect.bottom = WINDOW_HEIGHT;
  280.     RECT screenRect;
  281.     screenRect.left = windowRect.left;
  282.     screenRect.top = windowRect.top;
  283.     screenRect.right = windowRect.left + WINDOW_WIDTH;
  284.     screenRect.bottom = windowRect.top + WINDOW_HEIGHT;
  285.         
  286.     while( 1 )
  287.     {
  288.         ddrval = lpDDSPrimary->Blt(&screenRect, lpDDSDA,
  289.                                    &daRect, DDBLT_WAIT, NULL);
  290.         if( ddrval == DD_OK )
  291.         {
  292.             break;
  293.         }
  294.         if( ddrval == DDERR_SURFACELOST )
  295.         {
  296.             ddrval = restoreAll();
  297.             if( ddrval != DD_OK )
  298.             {
  299.                 return;
  300.             }
  301.         }
  302.         if( ddrval != DDERR_WASSTILLDRAWING )
  303.         {
  304.             return;
  305.         }
  306.     }
  307. } /* updateFrame */
  308. long FAR PASCAL WindowProc( HWND hWnd, UINT message, 
  309.                             WPARAM wParam, LPARAM lParam )
  310. {
  311.     switch( message )
  312.     {
  313.     case WM_SIZE:
  314.     case WM_MOVE:
  315.         if (IsIconic(hWnd))
  316.         {
  317.             bPaused = true;
  318.         }
  319.         if (!gExclusive) 
  320.         {
  321.             GetClientRect(hWnd, &windowRect);
  322.             ClientToScreen(hWnd, (LPPOINT)&windowRect);
  323.             ClientToScreen(hWnd, (LPPOINT)&windowRect+1);
  324.         } else {
  325.             SetRect(&windowRect, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
  326.         }
  327.         break;
  328.     case WM_ACTIVATEAPP:
  329.         bActive = wParam && GetForegroundWindow() == hWnd;
  330.         // Unpause when we're no longer iconic.
  331.         if (bPaused && bActive)
  332.         {
  333.             bPaused = false;
  334.         }
  335.         break;
  336.     case WM_SETCURSOR:
  337.         if (gExclusive && bActive)
  338.         {
  339.             SetCursor(NULL);
  340.             return TRUE;
  341.         }
  342.         break;
  343.     case WM_PALETTECHANGED:
  344.         if ((HWND)wParam == hWnd)
  345.             break;
  346.         // fall through to WM_QUERYNEWPALETTE
  347.     case WM_QUERYNEWPALETTE:
  348.         // install our palette here
  349.         if (lpDDPal)
  350.         {
  351.             lpDDSPrimary->SetPalette(lpDDPal);
  352.         }
  353.         DDReLoadBitmap(lpDDSDonut, szBitmap);
  354.         break;
  355.         
  356.     case WM_CREATE:
  357.         break;
  358.     case WM_KEYDOWN:
  359.         switch( wParam )
  360.         {
  361.         case VK_ESCAPE:
  362.         case VK_F12:
  363.             PostMessage(hWnd,WM_CLOSE,0,0);
  364.             break;
  365.         }
  366.         break;
  367.     case WM_DESTROY:
  368.         finiObjects();
  369.         PostQuitMessage( 0 );
  370.         break;
  371.     }
  372.     return DefWindowProc(hWnd, message, wParam, lParam);
  373. } /* WindowProc */
  374. /*
  375.  * doInit - do work required for every instance of the application:
  376.  *                create the window, initialize data
  377.  */
  378. static BOOL doInit( HINSTANCE hInstance, int nCmdShow )
  379. {
  380.     WNDCLASS            wc;
  381.     HRESULT             ddrval;
  382.     /*
  383.      * set up and register window class
  384.      */
  385.     wc.style = CS_HREDRAW | CS_VREDRAW;
  386.     wc.lpfnWndProc = WindowProc;
  387.     wc.cbClsExtra = 0;
  388.     wc.cbWndExtra = 0;
  389.     wc.hInstance = hInstance;
  390.     wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
  391.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  392.     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  393.     wc.lpszMenuName = NAME;
  394.     wc.lpszClassName = NAME;
  395.     RegisterClass( &wc );
  396.     
  397.     /*
  398.      * create a window
  399.      */
  400.     DWORD wndStyle = WS_OVERLAPPEDWINDOW;
  401.     if( gExclusive)
  402.         wndStyle = WS_POPUP;
  403.     hWndMain = CreateWindowEx(
  404.         WS_EX_APPWINDOW,
  405.         NAME,
  406.         TITLE,
  407.         wndStyle,
  408.         0,
  409.         0,
  410.         WINDOW_WIDTH,
  411.         WINDOW_HEIGHT,
  412.         NULL,
  413.         NULL,
  414.         hInstance,
  415.         NULL );
  416.     if( !hWndMain )
  417.     {
  418.         return FALSE;
  419.     }
  420.     ShowWindow( hWndMain, nCmdShow );
  421.     UpdateWindow( hWndMain );
  422.     /*
  423.      * create the main DirectDraw object
  424.      */
  425.     
  426.     ddrval = CoCreateInstance(CLSID_DirectDrawFactory,
  427.                               NULL, CLSCTX_INPROC_SERVER,
  428.                               IID_IDirectDrawFactory,
  429.                               (void **) & lpDDF);
  430.     char strDDFailed[] = "DirectDraw Init Failed";
  431.     if( ddrval != DD_OK )
  432.     {
  433.         return initFail(hWndMain, strDDFailed);
  434.     }
  435.     ddrval = lpDDF->CreateDirectDraw(NULL, hWndMain, DDSCL_NORMAL, 0, NULL, &lpDD);
  436.     if( ddrval != DD_OK )
  437.     {
  438.         return initFail(hWndMain, strDDFailed);
  439.     }
  440.     // Get exclusive mode if requested
  441.     if(gExclusive)
  442.     {
  443.         ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  444.     }
  445.     else
  446.     {
  447.         ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_NORMAL );
  448.     }
  449.     if( ddrval != DD_OK )
  450.     {
  451.         return initFail(hWndMain, strDDFailed);
  452.     }
  453.     if (!createSurfaces())
  454.     {
  455.         return initFail(hWndMain, strDDFailed);
  456.     }
  457.     // Create a DAView object and construct the model.
  458.     if (!initDXAViewObj(lpDDSDA))
  459.     {
  460.         return initFail(hWndMain, "DirectX Animation Init FAILED");
  461.     }
  462.     return TRUE;
  463. } /* doInit */
  464. /*
  465.  * WinMain - initialization, message loop
  466.  */
  467. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  468.                         LPSTR lpCmdLine, int nCmdShow)
  469. {
  470.     MSG         msg;
  471.     LPSTR       c;
  472.     for(c=lpCmdLine; *c != ''; c++)
  473.     {
  474.         switch( *c )
  475.         {
  476.             case 'X': gExclusive = TRUE; break;
  477.         }
  478.     }
  479.     
  480.     if( !doInit( hInstance, nCmdShow ) )
  481.     {
  482.         return FALSE;
  483.     }
  484.     while( 1 )
  485.     {
  486.         if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  487.         {
  488.             if( !GetMessage( &msg, NULL, 0, 0 ) )
  489.                 return msg.wParam;
  490.             TranslateMessage(&msg); 
  491.             DispatchMessage(&msg);
  492.         }
  493.         else if (!bPaused && (bActive || !gExclusive))
  494.         {
  495.             updateFrame();
  496.         }
  497.         else
  498.         {
  499.             WaitMessage();
  500.         }
  501.     }
  502. } /* WinMain */