home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / stretch2 / stretch.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  10KB  |  447 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       stretch.cpp
  6.  *
  7.  *  stretch with multimonitor support
  8.  *
  9.  ***************************************************************************/
  10.  
  11. #define NAME "Stretch"
  12. #define TITLE "Stretch"
  13.  
  14. #define WIN32_LEAN_AND_MEAN
  15. #include <windows.h>
  16. #include <windowsx.h>
  17. #include <ddraw.h>
  18. #include "resource.h"
  19. #include "ddutil.h"
  20. #include "ddmm.h"
  21.  
  22. #define SIZEX    64
  23. #define SIZEY    64
  24. char *szBitmap = "DONUT";
  25.  
  26. HWND        hwnd;
  27. DWORD           UpdateDelay = 100;
  28.  
  29. LPDIRECTDRAW        lpDD;        // DirectDraw object
  30. LPDIRECTDRAWSURFACE    lpDDSPrimary;    // DirectDraw primary surface
  31. LPDIRECTDRAWSURFACE    lpDDSOne;    // Offscreen surface 1
  32. LPDIRECTDRAWCLIPPER     lpClipper;      // clipper for primary
  33. LPDIRECTDRAWPALETTE    lpDDPal;    // DirectDraw palette
  34. BOOL                    bActive;        // is application active?
  35.  
  36. /* multimon stuff
  37. */
  38. int     MyDevice;
  39. char    MyDeviceName[128];
  40. RECT    MyDeviceRect;
  41.  
  42. BOOL ddInit(HWND);
  43.  
  44. /*
  45.  * restoreAll
  46.  *
  47.  * restore all lost objects
  48.  */
  49. BOOL restoreAll( void )
  50. {
  51.     return lpDDSPrimary->Restore() == DD_OK &&
  52.            lpDDSOne->Restore()     == DD_OK &&
  53.            DDReLoadBitmap(lpDDSOne, szBitmap) == DD_OK;
  54.  
  55. } /* restoreAll */
  56.  
  57. /*
  58.  * updateFrame
  59.  * 
  60.  * Decide what needs to be blitted next, wait for flip to complete,
  61.  * then flip the buffers.
  62.  */
  63. void updateFrame( void )
  64. {
  65.     static DWORD    lastTickCount = 0;
  66.     static int        currentFrame = 0;
  67.     static BOOL         haveBackground = FALSE;
  68.     DWORD        thisTickCount;
  69.     RECT        rcRect;
  70.     RECT        destRect;
  71.     HRESULT        ddrval;
  72.     POINT               pt;
  73.  
  74.     thisTickCount = GetTickCount();
  75.     if((thisTickCount - lastTickCount) <= UpdateDelay)
  76.     {
  77.     return;
  78.     }
  79.  
  80.     // Move to next frame;
  81.     lastTickCount = thisTickCount;
  82.     currentFrame++;
  83.     if(currentFrame > 59)
  84.     {
  85.         currentFrame = 0;
  86.     }
  87.  
  88.     // Blit the stuff for the next frame
  89.     rcRect.left   = currentFrame%10*64;
  90.     rcRect.top    = currentFrame/10*64;
  91.     rcRect.right  = currentFrame%10*64 + 64;
  92.     rcRect.bottom = currentFrame/10*64 + 64;
  93.  
  94.     GetClientRect( hwnd, &destRect );
  95.     if (destRect.right  < 64) destRect.right = 64;
  96.     if (destRect.bottom < 64)  destRect.bottom = 64;
  97.  
  98.     pt.x = pt.y = 0;
  99.     ClientToScreen( hwnd, &pt );
  100.     pt.x -= MyDeviceRect.left;
  101.     pt.y -= MyDeviceRect.top;
  102.     OffsetRect(&destRect, pt.x, pt.y);
  103.  
  104.     while( 1 )
  105.     {
  106.         ddrval = lpDDSPrimary->Blt( &destRect, lpDDSOne, &rcRect, 0, NULL );
  107.  
  108.     if( ddrval == DD_OK )
  109.     {
  110.         break;
  111.     }
  112.     if( ddrval == DDERR_SURFACELOST )
  113.     {
  114.             if(!restoreAll())
  115.         {
  116.         return;
  117.         }
  118.     }
  119.     if( ddrval != DDERR_WASSTILLDRAWING )
  120.     {
  121.         return;
  122.     }
  123.     }
  124.     if(ddrval != DD_OK)
  125.     {
  126.     return;
  127.     }
  128. } /* updateFrame */
  129.  
  130.  
  131. /*
  132.  * finiObjects
  133.  *
  134.  * finished with all objects we use; release them
  135.  */
  136. static void finiObjects( BOOL fKillDD )
  137. {
  138.     if( lpDDSPrimary != NULL )
  139.     {
  140.         lpDDSPrimary->Release();
  141.         lpDDSPrimary = NULL;
  142.     }
  143.     if( lpDDSOne != NULL )
  144.     {
  145.         lpDDSOne->Release();
  146.         lpDDSOne = NULL;
  147.     }
  148.     if( lpDDPal != NULL )
  149.     {
  150.         lpDDPal->Release();
  151.         lpDDPal = NULL;
  152.     }
  153.     if( fKillDD && lpDD != NULL )
  154.     {
  155.         lpDD->Release();
  156.         lpDD = NULL;
  157.     }
  158. } /* finiObjects */
  159.  
  160. long FAR PASCAL WindowProc( HWND hWnd, UINT message, 
  161.                 WPARAM wParam, LPARAM lParam )
  162. {
  163.     RECT  rc;
  164.  
  165.     switch( message )
  166.     {
  167.     case WM_ACTIVATEAPP:
  168.         bActive = wParam;
  169.     break;
  170.  
  171.     case WM_DISPLAYCHANGE:
  172.         ddInit(hwnd);
  173.         break;
  174.  
  175.     case WM_SIZE:
  176.     case WM_MOVE:
  177.         if (MyDevice != DirectDrawDeviceFromWindow(hwnd,NULL,NULL))
  178.         {
  179.             ddInit(hwnd);
  180.         }
  181.         break;
  182.  
  183.     case WM_PALETTECHANGED:
  184.         if ((HWND)wParam == hWnd)
  185.             break;
  186.         // fall through to WM_QUERYNEWPALETTE
  187.     case WM_QUERYNEWPALETTE:
  188.         // install our palette here
  189.         if (lpDDPal)
  190.         {
  191.             lpDDSPrimary->SetPalette(lpDDPal);
  192.         }
  193.         // reload the bitmap into the surface because the palette
  194.         // has changed..
  195.         DDReLoadBitmap(lpDDSOne, szBitmap);
  196.         break;
  197.  
  198.  
  199.     case WM_CREATE:
  200.         break;
  201.  
  202.     case WM_GETMINMAXINFO:
  203.         ((MINMAXINFO*)lParam)->ptMinTrackSize.x = SIZEX;
  204.         ((MINMAXINFO*)lParam)->ptMinTrackSize.y = SIZEY;
  205.         return 0;
  206.  
  207.     case WM_KEYDOWN:
  208.     switch( wParam )
  209.     {
  210.     case VK_ESCAPE:
  211.         case VK_F12:
  212.             PostMessage(hWnd, WM_CLOSE, 0, 0);
  213.         break;
  214.     }
  215.     break;
  216.  
  217.     case WM_DESTROY:
  218.         finiObjects(TRUE);
  219.     PostQuitMessage( 0 );
  220.         break;
  221.  
  222.     case WM_KEYUP:
  223.         if (wParam >= '1' && wParam <= '9')
  224.         {
  225.             SetRect(&rc, 0, 0, SIZEX*(wParam-'0'), SIZEY*(wParam-'0'));
  226.             goto size_me;
  227.         }
  228.         break;
  229.  
  230.     case WM_COMMAND: 
  231.         switch(LOWORD(wParam))
  232.     {
  233.         case ID_ROTATION_STOP:        
  234.         UpdateDelay = 0x7fffffff;
  235.         break;
  236.         case ID_ROTATION_SLOW:        
  237.         UpdateDelay = 200;
  238.         break;
  239.         case ID_ROTATION_FAST:        
  240.                 UpdateDelay = 100;
  241.         break;
  242.         case ID_FILE_EXIT:        
  243.                 PostMessage( hWnd, WM_CLOSE, 0, 0L );
  244.             break;
  245.             
  246.             case ID_SIZE_1X1: SetRect(&rc, 0, 0, SIZEX*1, SIZEY*1); goto size_me;
  247.             case ID_SIZE_2X1: SetRect(&rc, 0, 0, SIZEX*2, SIZEY*1); goto size_me;
  248.             case ID_SIZE_3X1: SetRect(&rc, 0, 0, SIZEX*3, SIZEY*1); goto size_me;
  249.             case ID_SIZE_1X2: SetRect(&rc, 0, 0, SIZEX*1, SIZEY*2); goto size_me;
  250.             case ID_SIZE_2X2: SetRect(&rc, 0, 0, SIZEX*2, SIZEY*2); goto size_me;
  251.             case ID_SIZE_3X2: SetRect(&rc, 0, 0, SIZEX*3, SIZEY*2); goto size_me;
  252.             case ID_SIZE_1X3: SetRect(&rc, 0, 0, SIZEX*1, SIZEY*3); goto size_me;
  253.             case ID_SIZE_2X3: SetRect(&rc, 0, 0, SIZEX*2, SIZEY*3); goto size_me;
  254.         case ID_SIZE_3X3: SetRect(&rc, 0, 0, SIZEX*3, SIZEY*3); goto size_me;
  255. size_me:
  256.                 AdjustWindowRectEx(&rc, GetWindowLong(hWnd, GWL_STYLE),
  257.             GetMenu(hWnd) != NULL, GetWindowLong(hWnd, GWL_EXSTYLE));
  258.         SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  259.                     SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
  260.         break;
  261.         } 
  262.         break;
  263.     }
  264.  
  265.     return DefWindowProc(hWnd, message, wParam, lParam);
  266.  
  267. } /* WindowProc */
  268.  
  269. /*
  270.  * This function is called if the initialization function fails
  271.  */
  272. BOOL initFail( HWND hwnd )
  273. {
  274.     finiObjects(TRUE);
  275.     MessageBox( hwnd, "DirectDraw Init FAILED", TITLE, MB_OK );
  276.     DestroyWindow( hwnd );
  277.     return FALSE;
  278.  
  279. } /* initFail */
  280.  
  281. /*
  282.  * ddInit
  283.  */
  284. BOOL ddInit( HWND hwnd )
  285. {
  286.     DDSURFACEDESC    ddsd;
  287.     HRESULT             ddrval;
  288.     char                ach[128];
  289.  
  290.     /*
  291.      * clean up our mess
  292.      */
  293.     finiObjects(TRUE);
  294.  
  295.     MyDevice = DirectDrawDeviceFromWindow(hwnd,MyDeviceName,&MyDeviceRect);
  296.  
  297.     if (MyDeviceName[0] == 0) lstrcpy(MyDeviceName, "(none)");
  298.     wsprintf(ach, "%s - %s", TITLE, MyDeviceName);
  299.     SetWindowText(hwnd, ach);
  300.  
  301.     /*
  302.      * create the main DirectDraw object
  303.      */
  304.     lpDD = DirectDrawCreateFromWindow(hwnd);
  305.  
  306.     if( lpDD == NULL )
  307.     {
  308.     return initFail(hwnd);
  309.     }
  310.     ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
  311.  
  312.     // Create the primary surface
  313.     ddsd.dwSize = sizeof( ddsd );
  314.     ddsd.dwFlags = DDSD_CAPS;
  315.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  316.  
  317.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  318.     if( ddrval != DD_OK )
  319.     {
  320.     return initFail(hwnd);
  321.     }
  322.  
  323.     // create a clipper for the primary surface
  324.     ddrval = lpDD->CreateClipper( 0, &lpClipper, NULL );
  325.     if( ddrval != DD_OK )
  326.     {
  327.         return initFail(hwnd);
  328.     }
  329.  
  330.     ddrval = lpClipper->SetHWnd( 0, hwnd );
  331.     if( ddrval != DD_OK )
  332.     {
  333.         return initFail(hwnd);
  334.     }
  335.  
  336.     ddrval = lpDDSPrimary->SetClipper( lpClipper );
  337.     if( ddrval != DD_OK )
  338.     {
  339.         return initFail(hwnd);
  340.     }
  341.  
  342.     // load our palette
  343.     lpDDPal = DDLoadPalette(lpDD, szBitmap);
  344.  
  345.     // make sure to set the palette before loading bitmaps.
  346.     if (lpDDPal)
  347.     lpDDSPrimary->SetPalette(lpDDPal);
  348.  
  349.     // load our bitmap
  350.     lpDDSOne = DDLoadBitmap(lpDD, szBitmap, 0, 0);
  351.  
  352.     if( lpDDSOne == NULL )
  353.     {
  354.     return initFail(hwnd);
  355.     }
  356.  
  357.     return TRUE;
  358. } /* doInit */
  359.  
  360. /*
  361.  * doInit - do work required for every instance of the application:
  362.  *          create the window, initialize data
  363.  */
  364. static BOOL doInit( HINSTANCE hInstance, int nCmdShow )
  365. {
  366.     WNDCLASS        wc;
  367.  
  368.     /*
  369.      * set up and register window class
  370.      */
  371.     wc.style = CS_HREDRAW | CS_VREDRAW;
  372.     wc.lpfnWndProc = WindowProc;
  373.     wc.cbClsExtra = 0;
  374.     wc.cbWndExtra = 0;
  375.     wc.hInstance = hInstance;
  376.     wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
  377.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  378.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  379.     wc.lpszMenuName = NULL; // MAKEINTRESOURCE(IDR_MENU);
  380.     wc.lpszClassName = NAME;
  381.     RegisterClass( &wc );
  382.     
  383.     /*
  384.      * create a window
  385.      */
  386.     hwnd = CreateWindowEx(
  387.     0,
  388.     NAME,
  389.     TITLE,
  390.         WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
  391.     CW_USEDEFAULT,
  392.     CW_USEDEFAULT,
  393.     128,
  394.     128,
  395.     NULL,
  396.     NULL,
  397.     hInstance,
  398.     NULL );
  399.  
  400.     if( !hwnd )
  401.     {
  402.     return FALSE;
  403.     }
  404.  
  405.     PostMessage(hwnd, WM_COMMAND, ID_SIZE_3X3, 0);
  406.  
  407.     ShowWindow( hwnd, nCmdShow );
  408.     UpdateWindow( hwnd );
  409.  
  410.     /*
  411.      * create the direct draw objects
  412.      */
  413.     ddInit(hwnd);
  414.  
  415.     return TRUE;
  416.  
  417. } /* doInit */
  418.  
  419. /*
  420.  * WinMain - initialization, message loop
  421.  */
  422. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  423.             LPSTR lpCmdLine, int nCmdShow)
  424. {
  425.     MSG         msg;
  426.  
  427.     if( !doInit( hInstance, nCmdShow ) )
  428.     {
  429.     return FALSE;
  430.     }
  431.  
  432.     while( 1 )
  433.     {
  434.     if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  435.     {
  436.         if( !GetMessage( &msg, NULL, 0, 0 ) )
  437.         return msg.wParam;
  438.         TranslateMessage(&msg); 
  439.         DispatchMessage(&msg);
  440.     }
  441.         else
  442.     {
  443.         updateFrame();
  444.     }
  445.     }
  446. } /* WinMain */
  447.