home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / DONUT / DONUT.CPP < prev    next >
C/C++ Source or Header  |  1996-08-28  |  11KB  |  461 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       donut.cpp
  6.  *
  7.  ***************************************************************************/
  8.  
  9. #define NAME "Donut"
  10. #define TITLE "Donut"
  11.  
  12. #define WIN32_LEAN_AND_MEAN
  13. #include <windows.h>
  14. #include <windowsx.h>
  15. #include <ddraw.h>
  16. #include "resource.h"
  17. #include "ddutil.h"
  18.  
  19. char szBitmap[] = "DONUT";
  20.  
  21. int             gPos = 0;
  22. BOOL            gExclusive = FALSE;
  23. int             gMode = 0;
  24. HWND            hwnd;
  25.  
  26. LPDIRECTDRAW            lpDD;           // DirectDraw object
  27. LPDIRECTDRAWSURFACE     lpDDSPrimary;   // DirectDraw primary surface
  28. LPDIRECTDRAWSURFACE     lpDDSOne;       // Offscreen surface 1
  29. LPDIRECTDRAWSURFACE     lpDDSTwo;       // Offscreen surface 2
  30. LPDIRECTDRAWPALETTE     lpDDPal;        // DirectDraw palette
  31. BOOL                    bActive;        // is application active?
  32.  
  33. /*
  34.  * restoreAll
  35.  *
  36.  * restore all lost objects
  37.  */
  38. HRESULT restoreAll( void )
  39. {
  40.     HRESULT     ddrval;
  41.  
  42.     ddrval = lpDDSPrimary->Restore();
  43.     if( ddrval == DD_OK )
  44.     {
  45.         ddrval = lpDDSOne->Restore();
  46.         if( ddrval == DD_OK )
  47.         {
  48.             ddrval = lpDDSTwo->Restore();
  49.             if( ddrval == DD_OK )
  50.             {
  51.                 DDReLoadBitmap(lpDDSOne, szBitmap);
  52.             }
  53.         }
  54.     }
  55.     return ddrval;
  56.  
  57. } /* restoreAll */
  58.  
  59. /*
  60.  * updateFrame
  61.  * 
  62.  * Decide what needs to be blitted next, wait for flip to complete,
  63.  * then flip the buffers.
  64.  */
  65. void updateFrame( void )
  66. {
  67.     static DWORD        lastTickCount = 0;
  68.     static int          currentFrame = 0;
  69.     static BOOL         haveBackground = FALSE;
  70.     DWORD               thisTickCount;
  71.     RECT                rcRect;
  72.     DWORD               delay = 17;
  73.     HRESULT             ddrval;
  74.     int                 pos;
  75.  
  76.     thisTickCount = GetTickCount();
  77.     if((thisTickCount - lastTickCount) <= delay)
  78.     {
  79.         return;
  80.     }
  81.  
  82.     switch( gPos )
  83.     {
  84.         case 0: pos = 0; break;
  85.         case 1: pos = 64; break;
  86.         case 2: pos = 128; break;
  87.     }
  88.     rcRect.left = 0;
  89.     rcRect.top = 0;
  90.     rcRect.right = 64;
  91.     rcRect.bottom = 64;
  92.  
  93.     // restore a previously saved patch
  94.     while( haveBackground )
  95.     {
  96.         ddrval = lpDDSPrimary->BltFast( pos, 0, lpDDSTwo, &rcRect, FALSE );
  97.         if( ddrval == DD_OK )
  98.         {
  99.             haveBackground = TRUE;
  100.             break;
  101.         }
  102.         if( ddrval == DDERR_SURFACELOST )
  103.         {
  104.             ddrval = restoreAll();
  105.             if( ddrval != DD_OK )
  106.             {
  107.                 return;
  108.             }
  109.         }
  110.         if( ddrval != DDERR_WASSTILLDRAWING )
  111.         {
  112.             return;
  113.         }
  114.     }
  115.  
  116.     rcRect.left = pos;
  117.     rcRect.right = pos+64;
  118.     // Save the current primary surface that we are about to overwrite
  119.     while( 1 )
  120.     {
  121.         haveBackground = FALSE;
  122.         ddrval = lpDDSTwo->BltFast( 0, 0, lpDDSPrimary,
  123.             &rcRect, DDBLTFAST_NOCOLORKEY);
  124.  
  125.         if( ddrval == DD_OK )
  126.         {
  127.             haveBackground = TRUE;
  128.             break;
  129.         }
  130.         if( ddrval == DDERR_SURFACELOST )
  131.         {
  132.             ddrval = restoreAll();
  133.             if( ddrval != DD_OK )
  134.             {
  135.                 return;
  136.             }
  137.         }
  138.         if( ddrval != DDERR_WASSTILLDRAWING )
  139.         {
  140.             return;
  141.         }
  142.     }
  143.             
  144.     thisTickCount = GetTickCount();
  145.     if((thisTickCount - lastTickCount) > delay)
  146.     {
  147.         // Move to next frame;
  148.         lastTickCount = thisTickCount;
  149.         currentFrame++;
  150.         if(currentFrame > 59)
  151.         {
  152.             currentFrame = 0;
  153.         }
  154.     }
  155.  
  156.     // Blit the stuff for the next frame
  157.     rcRect.left   = currentFrame%10*64;
  158.     rcRect.top    = currentFrame/10*64;
  159.     rcRect.right  = currentFrame%10*64 + 64;
  160.     rcRect.bottom = currentFrame/10*64 + 64;
  161.  
  162.     while( 1 )
  163.     {
  164.         ddrval = lpDDSPrimary->BltFast( pos, 0, lpDDSOne,
  165.             &rcRect, DDBLTFAST_SRCCOLORKEY);
  166.  
  167.         if( ddrval == DD_OK )
  168.         {
  169.             break;
  170.         }
  171.         if( ddrval == DDERR_SURFACELOST )
  172.         {
  173.             ddrval = restoreAll();
  174.             if( ddrval != DD_OK )
  175.             {
  176.                 return;
  177.             }
  178.         }
  179.         if( ddrval != DDERR_WASSTILLDRAWING )
  180.         {
  181.             return;
  182.         }
  183.     }
  184.     if(ddrval != DD_OK)
  185.     {
  186.         return;
  187.     }
  188. } /* updateFrame */
  189.  
  190.  
  191. /*
  192.  * finiObjects
  193.  *
  194.  * finished with all objects we use; release them
  195.  */
  196. static void finiObjects( void )
  197. {
  198.     if( lpDD != NULL )
  199.     {
  200.         if( lpDDSPrimary != NULL )
  201.         {
  202.             lpDDSPrimary->Release();
  203.             lpDDSPrimary = NULL;
  204.         }
  205.         if( lpDDSOne != NULL )
  206.         {
  207.             lpDDSOne->Release();
  208.             lpDDSOne = NULL;
  209.         }
  210.         if( lpDDPal != NULL )
  211.         {
  212.             lpDDPal->Release();
  213.             lpDDPal = NULL;
  214.         }
  215.         lpDD->Release();
  216.         lpDD = NULL;
  217.     }
  218.     // Clean up the screen on exit
  219.     RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
  220.                      RDW_ALLCHILDREN );
  221.  
  222. } /* finiObjects */
  223.  
  224. long FAR PASCAL WindowProc( HWND hWnd, UINT message, 
  225.                             WPARAM wParam, LPARAM lParam )
  226. {
  227.     hwnd = hWnd;
  228.     switch( message )
  229.     {
  230.     case WM_ACTIVATEAPP:
  231.         bActive = wParam;
  232.         break;
  233.  
  234.     case WM_SETCURSOR:
  235.         SetCursor(NULL);
  236.         return TRUE;
  237.  
  238.     case WM_PALETTECHANGED:
  239.         if ((HWND)wParam == hWnd)
  240.             break;
  241.         // fall through to WM_QUERYNEWPALETTE
  242.     case WM_QUERYNEWPALETTE:
  243.         // install our palette here
  244.         if (lpDDPal)
  245.         {
  246.             lpDDSPrimary->SetPalette(lpDDPal);
  247.         }
  248.         DDReLoadBitmap(lpDDSOne, szBitmap);
  249.         break;
  250.         
  251.     case WM_CREATE:
  252.         break;
  253.  
  254.     case WM_KEYDOWN:
  255.         switch( wParam )
  256.         {
  257.         case VK_ESCAPE:
  258.         case VK_F12:
  259.             PostMessage(hWnd,WM_CLOSE,0,0);
  260.             break;
  261.         }
  262.         break;
  263.  
  264.     case WM_DESTROY:
  265.         finiObjects();
  266.         PostQuitMessage( 0 );
  267.         break;
  268.     }
  269.  
  270.     return DefWindowProc(hWnd, message, wParam, lParam);
  271.  
  272. } /* WindowProc */
  273.  
  274. /*
  275.  * This function is called if the initialization function fails
  276.  */
  277. BOOL initFail( HWND hwnd )
  278. {
  279.     finiObjects();
  280.     MessageBox( hwnd, "DirectDraw Init FAILED", TITLE, MB_OK );
  281.     DestroyWindow( hwnd );
  282.     return FALSE;
  283.  
  284. } /* initFail */
  285.  
  286. /*
  287.  * doInit - do work required for every instance of the application:
  288.  *                create the window, initialize data
  289.  */
  290. static BOOL doInit( HINSTANCE hInstance, int nCmdShow )
  291. {
  292.     HWND                hwnd;
  293.     WNDCLASS            wc;
  294.     DDSURFACEDESC       ddsd;
  295.     HRESULT             ddrval;
  296.  
  297.     /*
  298.      * set up and register window class
  299.      */
  300.     wc.style = CS_HREDRAW | CS_VREDRAW;
  301.     wc.lpfnWndProc = WindowProc;
  302.     wc.cbClsExtra = 0;
  303.     wc.cbWndExtra = 0;
  304.     wc.hInstance = hInstance;
  305.     wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
  306.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  307.     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  308.     wc.lpszMenuName = NAME;
  309.     wc.lpszClassName = NAME;
  310.     RegisterClass( &wc );
  311.     
  312.     /*
  313.      * create a window
  314.      */
  315.     hwnd = CreateWindowEx(
  316.         0,
  317.         NAME,
  318.         TITLE,
  319.         WS_POPUP,
  320.         0,
  321.         0,
  322.         1,
  323.         1,
  324.         NULL,
  325.         NULL,
  326.         hInstance,
  327.         NULL );
  328.  
  329.     if( !hwnd )
  330.     {
  331.         return FALSE;
  332.     }
  333.  
  334.     ShowWindow( hwnd, nCmdShow );
  335.     UpdateWindow( hwnd );
  336.  
  337.     /*
  338.      * create the main DirectDraw object
  339.      */
  340.     ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  341.     if( ddrval != DD_OK )
  342.     {
  343.         return initFail(hwnd);
  344.     }
  345.  
  346.     // Get exclusive mode if requested
  347.     if(gExclusive)
  348.     {
  349.         ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  350.     }
  351.     else
  352.     {
  353.         ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
  354.     }
  355.     if( ddrval != DD_OK )
  356.     {
  357.         return initFail(hwnd);
  358.     }
  359.  
  360.     // Set the video mode to 640x480x8
  361.     switch( gMode )
  362.     {
  363.         case 1:  ddrval = lpDD->SetDisplayMode( 640, 480, 8); break;
  364.         case 2:  ddrval = lpDD->SetDisplayMode( 800, 600, 8); break;
  365.         case 3:  ddrval = lpDD->SetDisplayMode( 1024, 768, 8); break;
  366.         case 4:  ddrval = lpDD->SetDisplayMode( 1280, 1024, 8); break;
  367.     }
  368.     if( ddrval != DD_OK )
  369.     {
  370.         return initFail(hwnd);
  371.     }
  372.  
  373.     // Create the primary surface
  374.     ddsd.dwSize = sizeof( ddsd );
  375.     ddsd.dwFlags = DDSD_CAPS;
  376.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  377.  
  378.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  379.     if( ddrval != DD_OK )
  380.     {
  381.         return initFail(hwnd);
  382.     }
  383.  
  384.     lpDDPal = DDLoadPalette(lpDD, szBitmap);
  385.  
  386.     if (lpDDPal)
  387.     {
  388.         lpDDSPrimary->SetPalette(lpDDPal);
  389.     }
  390.  
  391.     lpDDSOne = DDLoadBitmap(lpDD, szBitmap, 0, 0);
  392.     if( lpDDSOne == NULL )
  393.     {
  394.         return initFail(hwnd);
  395.     }
  396.  
  397.     // set color key to black
  398.     DDSetColorKey(lpDDSOne, RGB(0,0,0));
  399.  
  400.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  401.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  402.     ddsd.dwHeight = 64;
  403.     ddsd.dwWidth = 64;
  404.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSTwo, NULL );
  405.     if( ddrval != DD_OK )
  406.     {
  407.         return initFail(hwnd);
  408.     }
  409.  
  410.     return TRUE;
  411. } /* doInit */
  412.  
  413. /*
  414.  * WinMain - initialization, message loop
  415.  */
  416. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  417.                         LPSTR lpCmdLine, int nCmdShow)
  418. {
  419.     MSG         msg;
  420.     LPSTR       c;
  421.  
  422.     for(c=lpCmdLine; *c != '\0'; c++)
  423.     {
  424.         switch( *c )
  425.         {
  426.             case '0': gPos = 0; break;
  427.             case '1': gPos = 1; break;
  428.             case '2': gPos = 2; break;
  429.             case 'X': gExclusive = TRUE; break;
  430.             case 'A': gExclusive = TRUE; gMode = 1; break;
  431.             case 'B': gExclusive = TRUE; gMode = 2; break;
  432.             case 'C': gExclusive = TRUE; gMode = 3; break;
  433.             case 'D': gExclusive = TRUE; gMode = 4; break;
  434.         }
  435.     }
  436.     
  437.     if( !doInit( hInstance, nCmdShow ) )
  438.     {
  439.         return FALSE;
  440.     }
  441.  
  442.     while( 1 )
  443.     {
  444.         if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  445.         {
  446.             if( !GetMessage( &msg, NULL, 0, 0 ) )
  447.                 return msg.wParam;
  448.             TranslateMessage(&msg); 
  449.             DispatchMessage(&msg);
  450.         }
  451.         else if( !gExclusive || bActive )
  452.         {
  453.             updateFrame();
  454.         }
  455.         else
  456.         {
  457.             WaitMessage();
  458.         }
  459.     }
  460. } /* WinMain */
  461.