ddutil.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:29k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: ddutil.cpp
  3. //
  4. // Desc: DirectDraw framewark classes. Feel free to use this class as a 
  5. //       starting point for adding extra functionality.
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <tchar.h>
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <ddraw.h>
  14. #include "ddutil.h"
  15. #include "dxutil.h"
  16. //-----------------------------------------------------------------------------
  17. // Name: CDisplay()
  18. // Desc:
  19. //-----------------------------------------------------------------------------
  20. CDisplay::CDisplay()
  21. {
  22.     m_pDD                = NULL;
  23.     m_pddsFrontBuffer    = NULL;
  24.     m_pddsBackBuffer     = NULL;
  25.     m_pddsBackBufferLeft = NULL;
  26. }
  27. //-----------------------------------------------------------------------------
  28. // Name: ~CDisplay()
  29. // Desc:
  30. //-----------------------------------------------------------------------------
  31. CDisplay::~CDisplay()
  32. {
  33.     DestroyObjects();
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Name: DestroyObjects()
  37. // Desc:
  38. //-----------------------------------------------------------------------------
  39. HRESULT CDisplay::DestroyObjects()
  40. {
  41.     SAFE_RELEASE( m_pddsBackBufferLeft );
  42.     SAFE_RELEASE( m_pddsBackBuffer );
  43.     SAFE_RELEASE( m_pddsFrontBuffer );
  44.     if( m_pDD )
  45.         m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
  46.     SAFE_RELEASE( m_pDD );
  47.     return S_OK;
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Name: CreateFullScreenDisplay()
  51. // Desc:
  52. //-----------------------------------------------------------------------------
  53. HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth,
  54.                                            DWORD dwHeight, DWORD dwBPP )
  55. {
  56.     HRESULT hr;
  57.     // Cleanup anything from a previous call
  58.     DestroyObjects();
  59.     // DDraw stuff begins here
  60.     if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD,
  61.                                          IID_IDirectDraw7, NULL ) ) )
  62.         return E_FAIL;
  63.     // Set cooperative level
  64.     hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN );
  65.     if( FAILED(hr) )
  66.         return E_FAIL;
  67.     // Set the display mode
  68.     if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) )
  69.         return E_FAIL;
  70.     // Create primary surface (with backbuffer attached)
  71.     DDSURFACEDESC2 ddsd;
  72.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  73.     ddsd.dwSize            = sizeof( ddsd );
  74.     ddsd.dwFlags           = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  75.     ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
  76.                              DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
  77.     ddsd.dwBackBufferCount = 1;
  78.     if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer,
  79.                                            NULL ) ) )
  80.         return E_FAIL;
  81.     // Get a pointer to the back buffer
  82.     DDSCAPS2 ddscaps;
  83.     ZeroMemory( &ddscaps, sizeof( ddscaps ) );
  84.     ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  85.     if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
  86.                                                             &m_pddsBackBuffer ) ) )
  87.         return E_FAIL;
  88.     m_pddsBackBuffer->AddRef();
  89.     m_hWnd      = hWnd;
  90.     m_bWindowed = FALSE;
  91.     UpdateBounds();
  92.     return S_OK;
  93. }
  94.     
  95. //-----------------------------------------------------------------------------
  96. // Name: CreateWindowedDisplay()
  97. // Desc:
  98. //-----------------------------------------------------------------------------
  99. HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight )
  100. {
  101.     HRESULT hr;
  102.     // Cleanup anything from a previous call
  103.     DestroyObjects();
  104.     // DDraw stuff begins here
  105.     if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD,
  106.                                          IID_IDirectDraw7, NULL ) ) )
  107.         return E_FAIL;
  108.     // Set cooperative level
  109.     hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL );
  110.     if( FAILED(hr) )
  111.         return E_FAIL;
  112.     RECT  rcWork;
  113.     RECT  rc;
  114.     DWORD dwStyle;
  115.     // If we are still a WS_POPUP window we should convert to a normal app
  116.     // window so we look like a windows app.
  117.     dwStyle  = GetWindowStyle( hWnd );
  118.     dwStyle &= ~WS_POPUP;
  119.     dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
  120.     SetWindowLong( hWnd, GWL_STYLE, dwStyle );
  121.     // Aet window size
  122.     SetRect( &rc, 0, 0, dwWidth, dwHeight );
  123.     AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL,
  124.                         GetWindowExStyle(hWnd) );
  125.     SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  126.                   SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
  127.     SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  128.                   SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
  129.     //  Make sure our window does not hang outside of the work area
  130.     SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
  131.     GetWindowRect( hWnd, &rc );
  132.     if( rc.left < rcWork.left ) rc.left = rcWork.left;
  133.     if( rc.top  < rcWork.top )  rc.top  = rcWork.top;
  134.     SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0,
  135.                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  136.     LPDIRECTDRAWCLIPPER pcClipper;
  137.     
  138.     // Create the primary surface
  139.     DDSURFACEDESC2 ddsd;
  140.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  141.     ddsd.dwSize         = sizeof( ddsd );
  142.     ddsd.dwFlags        = DDSD_CAPS;
  143.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  144.     if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
  145.         return E_FAIL;
  146.     // Create the backbuffer surface
  147.     ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;    
  148.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
  149.     ddsd.dwWidth        = dwWidth;
  150.     ddsd.dwHeight       = dwHeight;
  151.     if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
  152.         return E_FAIL;
  153.     if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
  154.         return E_FAIL;
  155.     if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) )
  156.     {
  157.         pcClipper->Release();
  158.         return E_FAIL;
  159.     }
  160.     if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) )
  161.     {
  162.         pcClipper->Release();
  163.         return E_FAIL;
  164.     }
  165.     // Done with clipper
  166.     pcClipper->Release();
  167.     m_hWnd      = hWnd;
  168.     m_bWindowed = TRUE;
  169.     UpdateBounds();
  170.     return S_OK;
  171. }
  172. //-----------------------------------------------------------------------------
  173. // Name: 
  174. // Desc: 
  175. //-----------------------------------------------------------------------------
  176. HRESULT CDisplay::CreateSurface( CSurface** ppSurface,
  177.                                  DWORD dwWidth, DWORD dwHeight )
  178. {
  179.     if( NULL == m_pDD )
  180.         return E_POINTER;
  181.     if( NULL == ppSurface )
  182.         return E_INVALIDARG;
  183.     HRESULT        hr;
  184.     DDSURFACEDESC2 ddsd;
  185.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  186.     ddsd.dwSize         = sizeof( ddsd );
  187.     ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 
  188.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  189.     ddsd.dwWidth        = dwWidth;
  190.     ddsd.dwHeight       = dwHeight;
  191.     (*ppSurface) = new CSurface();
  192.     if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) )
  193.     {
  194.         delete (*ppSurface);
  195.         return hr;
  196.     }
  197.     return S_OK;
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Name: CDisplay::CreateSurfaceFromBitmap()
  201. // Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file.
  202. //       Use MAKEINTRESOURCE() to pass a constant into strBMP.
  203. //-----------------------------------------------------------------------------
  204. HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface,
  205.                                            TCHAR* strBMP,                                            
  206.                                            DWORD dwDesiredWidth, 
  207.                                            DWORD dwDesiredHeight )
  208. {
  209.     HRESULT        hr;
  210.     HBITMAP        hBMP = NULL;
  211.     BITMAP         bmp;
  212.     DDSURFACEDESC2 ddsd;
  213.     if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) 
  214.         return E_INVALIDARG;
  215.     *ppSurface = NULL;
  216.     //  Try to load the bitmap as a resource, if that fails, try it as a file
  217.     hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, 
  218.                                 IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, 
  219.                                 LR_CREATEDIBSECTION );
  220.     if( hBMP == NULL )
  221.     {
  222.         hBMP = (HBITMAP) LoadImage( NULL, strBMP, 
  223.                                     IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, 
  224.                                     LR_LOADFROMFILE | LR_CREATEDIBSECTION );
  225.         if( hBMP == NULL )
  226.             return E_FAIL;
  227.     }
  228.     // Get size of the bitmap
  229.     GetObject( hBMP, sizeof(bmp), &bmp );
  230.     // Create a DirectDrawSurface for this bitmap
  231.     ZeroMemory( &ddsd, sizeof(ddsd) );
  232.     ddsd.dwSize         = sizeof(ddsd);
  233.     ddsd.dwFlags        = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  234.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  235.     ddsd.dwWidth        = bmp.bmWidth;
  236.     ddsd.dwHeight       = bmp.bmHeight;
  237.     (*ppSurface) = new CSurface();
  238.     if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) )
  239.     {
  240.         delete (*ppSurface);
  241.         return hr;
  242.     }
  243.     // Draw the bitmap on this surface
  244.     if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) )
  245.     {
  246.         DeleteObject( hBMP );
  247.         return hr;
  248.     }
  249.     DeleteObject( hBMP );
  250.     return S_OK;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Name: CDisplay::CreateSurfaceFromText()
  254. // Desc: Creates a DirectDrawSurface from a text string using hFont or the default 
  255. //       GDI font if hFont is NULL.
  256. //-----------------------------------------------------------------------------
  257. HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface,
  258.                                          HFONT hFont, TCHAR* strText, 
  259.                                          COLORREF crBackground, COLORREF crForeground )
  260. {
  261.     HDC                  hDC  = NULL;
  262.     LPDIRECTDRAWSURFACE7 pDDS = NULL;
  263.     HRESULT              hr;
  264.     DDSURFACEDESC2       ddsd;
  265.     SIZE                 sizeText;
  266.     if( m_pDD == NULL || strText == NULL || ppSurface == NULL )
  267.         return E_INVALIDARG;
  268.     *ppSurface = NULL;
  269.     hDC = GetDC( NULL );
  270.     if( hFont )
  271.         SelectObject( hDC, hFont );
  272.     GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText );
  273.     ReleaseDC( NULL, hDC );
  274.     // Create a DirectDrawSurface for this bitmap
  275.     ZeroMemory( &ddsd, sizeof(ddsd) );
  276.     ddsd.dwSize         = sizeof(ddsd);
  277.     ddsd.dwFlags        = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  278.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  279.     ddsd.dwWidth        = sizeText.cx;
  280.     ddsd.dwHeight       = sizeText.cy;
  281.     (*ppSurface) = new CSurface();
  282.     if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) )
  283.     {
  284.         delete (*ppSurface);
  285.         return hr;
  286.     }
  287.     if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, 
  288.                                              crBackground, crForeground ) ) )
  289.         return hr;
  290.     return S_OK;
  291. }
  292. //-----------------------------------------------------------------------------
  293. // Name: 
  294. // Desc: 
  295. //-----------------------------------------------------------------------------
  296. HRESULT CDisplay::Present()
  297. {
  298.     HRESULT hr;
  299.     if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer )
  300.         return E_POINTER;
  301.     while( 1 )
  302.     {
  303.         if( m_bWindowed )
  304.             hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer,
  305.                                          NULL, DDBLT_WAIT, NULL );
  306.         else
  307.             hr = m_pddsFrontBuffer->Flip( NULL, 0 );
  308.         if( hr == DDERR_SURFACELOST )
  309.         {
  310.             m_pddsFrontBuffer->Restore();
  311.             m_pddsBackBuffer->Restore();
  312.         }
  313.         if( hr != DDERR_WASSTILLDRAWING )
  314.             return hr;
  315.     }
  316. }
  317. //-----------------------------------------------------------------------------
  318. // Name: 
  319. // Desc: 
  320. //-----------------------------------------------------------------------------
  321. HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette )
  322. {
  323.     if( NULL == m_pddsFrontBuffer ||  NULL == m_pddsBackBuffer )
  324.         return E_POINTER;
  325.     // Set the palette before loading the bitmap
  326.     if( pPalette )
  327.         m_pddsFrontBuffer->SetPalette( pPalette );
  328.     CSurface backBuffer;
  329.     backBuffer.Create( m_pddsBackBuffer );
  330.     if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) )
  331.         return E_FAIL;
  332.     return Present();
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Name: 
  336. // Desc: 
  337. //-----------------------------------------------------------------------------
  338. HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds,
  339.                                RECT* prc )
  340. {
  341.     if( NULL == m_pddsBackBuffer )
  342.         return E_POINTER;
  343.     return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY );
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Name: 
  347. // Desc: 
  348. //-----------------------------------------------------------------------------
  349. HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc,
  350.                        DWORD dwFlags )
  351. {
  352.     if( NULL == m_pddsBackBuffer )
  353.         return E_POINTER;
  354.     return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags );
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Name: 
  358. // Desc: 
  359. //-----------------------------------------------------------------------------
  360. HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc )
  361. {
  362.     if( NULL == pSurface )
  363.         return E_INVALIDARG;
  364.     if( pSurface->IsColorKeyed() )
  365.         return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY );
  366.     else
  367.         return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L );
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Name: 
  371. // Desc: 
  372. //-----------------------------------------------------------------------------
  373. HRESULT CDisplay::Clear( DWORD dwColor )
  374. {
  375.     if( NULL == m_pddsBackBuffer )
  376.         return E_POINTER;
  377.     // Erase the background
  378.     DDBLTFX ddbltfx;
  379.     ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  380.     ddbltfx.dwSize      = sizeof(ddbltfx);
  381.     ddbltfx.dwFillColor = dwColor;
  382.     return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Name: 
  386. // Desc: 
  387. //-----------------------------------------------------------------------------
  388. HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette )
  389. {
  390.     if( NULL == m_pddsFrontBuffer )
  391.         return E_POINTER;
  392.     return m_pddsFrontBuffer->SetPalette( pPalette );
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Name: 
  396. // Desc: 
  397. //-----------------------------------------------------------------------------
  398. HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette,
  399.                                            const TCHAR* strBMP )
  400. {
  401.     HRSRC             hResource      = NULL;
  402.     RGBQUAD*          pRGB           = NULL;
  403.     BITMAPINFOHEADER* pbi = NULL;
  404.     PALETTEENTRY      aPalette[256];
  405.     HANDLE            hFile = NULL;
  406.     DWORD             iColor;
  407.     DWORD             dwColors;
  408.     BITMAPFILEHEADER  bf;
  409.     BITMAPINFOHEADER  bi;
  410.     DWORD             dwBytesRead;
  411.     if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL )
  412.         return E_INVALIDARG;
  413.     *ppPalette = NULL;
  414.     //  Try to load the bitmap as a resource, if that fails, try it as a file
  415.     hResource = FindResource( NULL, strBMP, RT_BITMAP );
  416.     if( hResource )
  417.     {
  418.         pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) );       
  419.         if( NULL == pbi )
  420.             return E_FAIL;
  421.         pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize );
  422.         // Figure out how many colors there are
  423.         if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) )
  424.             dwColors = 0;
  425.         else if( pbi->biBitCount > 8 )
  426.             dwColors = 0;
  427.         else if( pbi->biClrUsed == 0 )
  428.             dwColors = 1 << pbi->biBitCount;
  429.         else
  430.             dwColors = pbi->biClrUsed;
  431.         //  A DIB color table has its colors stored BGR not RGB
  432.         //  so flip them around.
  433.         for( iColor = 0; iColor < dwColors; iColor++ )
  434.         {
  435.             aPalette[iColor].peRed   = pRGB[iColor].rgbRed;
  436.             aPalette[iColor].peGreen = pRGB[iColor].rgbGreen;
  437.             aPalette[iColor].peBlue  = pRGB[iColor].rgbBlue;
  438.             aPalette[iColor].peFlags = 0;
  439.         }
  440.         return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL );
  441.     }
  442.     // Attempt to load bitmap as a file
  443.     hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
  444.     if( INVALID_HANDLE_VALUE == hFile )
  445.         return E_FAIL;
  446.     // Read the BITMAPFILEHEADER
  447.     ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL );
  448.     if( dwBytesRead != sizeof(bf) )
  449.     {
  450.         CloseHandle( hFile );
  451.         return E_FAIL;
  452.     }
  453.     // Read the BITMAPINFOHEADER
  454.     ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL );
  455.     if( dwBytesRead != sizeof(bi) )
  456.     {
  457.         CloseHandle( hFile );
  458.         return E_FAIL;
  459.     }
  460.     // Read the PALETTEENTRY 
  461.     ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL );
  462.     if( dwBytesRead != sizeof(aPalette) )
  463.     {
  464.         CloseHandle( hFile );
  465.         return E_FAIL;
  466.     }
  467.     CloseHandle( hFile );
  468.     // Figure out how many colors there are
  469.     if( bi.biSize != sizeof(BITMAPINFOHEADER) )
  470.         dwColors = 0;
  471.     else if (bi.biBitCount > 8)
  472.         dwColors = 0;
  473.     else if (bi.biClrUsed == 0)
  474.         dwColors = 1 << bi.biBitCount;
  475.     else
  476.         dwColors = bi.biClrUsed;
  477.     //  A DIB color table has its colors stored BGR not RGB
  478.     //  so flip them around since DirectDraw uses RGB
  479.     for( iColor = 0; iColor < dwColors; iColor++ )
  480.     {
  481.         BYTE r = aPalette[iColor].peRed;
  482.         aPalette[iColor].peRed  = aPalette[iColor].peBlue;
  483.         aPalette[iColor].peBlue = r;
  484.     }
  485.     return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL );
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Name: 
  489. // Desc: 
  490. //-----------------------------------------------------------------------------
  491. HRESULT CDisplay::UpdateBounds()
  492. {
  493.     if( m_bWindowed )
  494.     {
  495.         GetClientRect( m_hWnd, &m_rcWindow );
  496.         ClientToScreen( m_hWnd, (POINT*)&m_rcWindow );
  497.         ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 );
  498.     }
  499.     else
  500.     {
  501.         SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN),
  502.                  GetSystemMetrics(SM_CYSCREEN) );
  503.     }
  504.     return S_OK;
  505. }
  506. //-----------------------------------------------------------------------------
  507. // Name: CDisplay::InitClipper
  508. // Desc: 
  509. //-----------------------------------------------------------------------------
  510. HRESULT CDisplay::InitClipper()
  511. {
  512.     LPDIRECTDRAWCLIPPER pClipper;
  513.     HRESULT hr;
  514.     // Create a clipper when using GDI to draw on the primary surface 
  515.     if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) )
  516.         return hr;
  517.     pClipper->SetHWnd( 0, m_hWnd );
  518.     if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) )
  519.         return hr;
  520.     // We can release the clipper now since g_pDDSPrimary 
  521.     // now maintains a ref count on the clipper
  522.     SAFE_RELEASE( pClipper );
  523.     return S_OK;
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Name: 
  527. // Desc: 
  528. //-----------------------------------------------------------------------------
  529. CSurface::CSurface()
  530. {
  531.     m_pdds = NULL;
  532.     m_bColorKeyed = NULL;
  533. }
  534. //-----------------------------------------------------------------------------
  535. // Name: 
  536. // Desc: 
  537. //-----------------------------------------------------------------------------
  538. CSurface::~CSurface()
  539. {
  540.     SAFE_RELEASE( m_pdds );
  541. }
  542. //-----------------------------------------------------------------------------
  543. // Name: 
  544. // Desc: 
  545. //-----------------------------------------------------------------------------
  546. HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds )
  547. {
  548.     m_pdds = pdds;
  549.     if( m_pdds )
  550.     {
  551.         m_pdds->AddRef();
  552.         // Get the DDSURFACEDESC structure for this surface
  553.         m_ddsd.dwSize = sizeof(m_ddsd);
  554.         m_pdds->GetSurfaceDesc( &m_ddsd );
  555.     }
  556.     return S_OK;
  557. }
  558. //-----------------------------------------------------------------------------
  559. // Name: 
  560. // Desc: 
  561. //-----------------------------------------------------------------------------
  562. HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd )
  563. {
  564.     HRESULT hr;
  565.     // Create the DDraw surface
  566.     if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) )
  567.         return hr;
  568.     // Prepare the DDSURFACEDESC structure
  569.     m_ddsd.dwSize = sizeof(m_ddsd);
  570.     // Get the DDSURFACEDESC structure for this surface
  571.     m_pdds->GetSurfaceDesc( &m_ddsd );
  572.     return S_OK;
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Name: 
  576. // Desc: 
  577. //-----------------------------------------------------------------------------
  578. HRESULT CSurface::Destroy()
  579. {
  580.     SAFE_RELEASE( m_pdds );
  581.     return S_OK;
  582. }
  583. //-----------------------------------------------------------------------------
  584. // Name: CSurface::DrawBitmap()
  585. // Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the 
  586. //       bitmap if nessasary
  587. //-----------------------------------------------------------------------------
  588. HRESULT CSurface::DrawBitmap( HBITMAP hBMP, 
  589.                               DWORD dwBMPOriginX, DWORD dwBMPOriginY, 
  590.                               DWORD dwBMPWidth, DWORD dwBMPHeight )
  591. {
  592.     HDC            hDCImage;
  593.     HDC            hDC;
  594.     BITMAP         bmp;
  595.     DDSURFACEDESC2 ddsd;
  596.     HRESULT        hr;
  597.     if( hBMP == NULL || m_pdds == NULL )
  598.         return E_INVALIDARG;
  599.     // Make sure this surface is restored.
  600.     if( FAILED( hr = m_pdds->Restore() ) )
  601.         return hr;
  602.     // Get the surface.description
  603.     ddsd.dwSize  = sizeof(ddsd);
  604.     m_pdds->GetSurfaceDesc( &ddsd );
  605.     if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC )
  606.         return E_NOTIMPL;
  607.     // Select bitmap into a memoryDC so we can use it.
  608.     hDCImage = CreateCompatibleDC( NULL );
  609.     if( NULL == hDCImage )
  610.         return E_FAIL;
  611.     SelectObject( hDCImage, hBMP );
  612.     // Get size of the bitmap
  613.     GetObject( hBMP, sizeof(bmp), &bmp );
  614.     // Use the passed size, unless zero
  615.     dwBMPWidth  = ( dwBMPWidth  == 0 ) ? bmp.bmWidth  : dwBMPWidth;     
  616.     dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight;
  617.     // Stretch the bitmap to cover this surface
  618.     if( FAILED( hr = m_pdds->GetDC( &hDC ) ) )
  619.         return hr;
  620.     StretchBlt( hDC, 0, 0, 
  621.                 ddsd.dwWidth, ddsd.dwHeight, 
  622.                 hDCImage, dwBMPOriginX, dwBMPOriginY,
  623.                 dwBMPWidth, dwBMPHeight, SRCCOPY );
  624.     if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) )
  625.         return hr;
  626.     DeleteDC( hDCImage );
  627.     return S_OK;
  628. }
  629. //-----------------------------------------------------------------------------
  630. // Name: CSurface::DrawText()
  631. // Desc: Draws a text string on a DirectDraw surface using hFont or the default
  632. //       GDI font if hFont is NULL.  
  633. //-----------------------------------------------------------------------------
  634. HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, 
  635.                             DWORD dwOriginX, DWORD dwOriginY,
  636.                             COLORREF crBackground, COLORREF crForeground )
  637. {
  638.     HDC     hDC = NULL;
  639.     HRESULT hr;
  640.     if( m_pdds == NULL || strText == NULL )
  641.         return E_INVALIDARG;
  642.     // Make sure this surface is restored.
  643.     if( FAILED( hr = m_pdds->Restore() ) )
  644.         return hr;
  645.     if( FAILED( hr = m_pdds->GetDC( &hDC ) ) )
  646.         return hr;
  647.     // Set the background and foreground color
  648.     SetBkColor( hDC, crBackground );
  649.     SetTextColor( hDC, crForeground );
  650.     if( hFont )
  651.         SelectObject( hDC, hFont );
  652.     // Use GDI to draw the text on the surface
  653.     TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) );
  654.     if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) )
  655.         return hr;
  656.     return S_OK;
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Name: CSurface::ReDrawBitmapOnSurface()
  660. // Desc: Load a bitmap from a file or resource into a DirectDraw surface.
  661. //       normaly used to re-load a surface after a restore.
  662. //-----------------------------------------------------------------------------
  663. HRESULT CSurface::DrawBitmap( TCHAR* strBMP, 
  664.                               DWORD dwDesiredWidth, DWORD dwDesiredHeight  )
  665. {
  666.     HBITMAP hBMP;
  667.     HRESULT hr;
  668.     if( m_pdds == NULL || strBMP == NULL )
  669.         return E_INVALIDARG;
  670.     //  Try to load the bitmap as a resource, if that fails, try it as a file
  671.     hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, 
  672.                                 IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, 
  673.                                 LR_CREATEDIBSECTION );
  674.     if( hBMP == NULL )
  675.     {
  676.         hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, 
  677.                                     dwDesiredWidth, dwDesiredHeight, 
  678.                                     LR_LOADFROMFILE | LR_CREATEDIBSECTION );
  679.         if( hBMP == NULL )
  680.             return E_FAIL;
  681.     }
  682.     // Draw the bitmap on this surface
  683.     if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) )
  684.     {
  685.         DeleteObject( hBMP );
  686.         return hr;
  687.     }
  688.     DeleteObject( hBMP );
  689.     return S_OK;
  690. }
  691. //-----------------------------------------------------------------------------
  692. // Name: 
  693. // Desc: 
  694. //-----------------------------------------------------------------------------
  695. HRESULT CSurface::SetColorKey( DWORD dwColorKey )
  696. {
  697.     if( NULL == m_pdds )
  698.         return E_POINTER;
  699.     m_bColorKeyed = TRUE;
  700.     DDCOLORKEY ddck;
  701.     ddck.dwColorSpaceLowValue  = ConvertGDIColor( dwColorKey );
  702.     ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey );
  703.     
  704.     return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck );
  705. }
  706. //-----------------------------------------------------------------------------
  707. // Name: CSurface::ConvertGDIColor()
  708. // Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a 
  709. //       DirectDrawSurface using its pixel format.  
  710. //-----------------------------------------------------------------------------
  711. DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor )
  712. {
  713.     if( m_pdds == NULL )
  714.     return 0x00000000;
  715.     COLORREF       rgbT;
  716.     HDC            hdc;
  717.     DWORD          dw = CLR_INVALID;
  718.     DDSURFACEDESC2 ddsd;
  719.     HRESULT        hr;
  720.     //  Use GDI SetPixel to color match for us
  721.     if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK)
  722.     {
  723.         rgbT = GetPixel(hdc, 0, 0);     // Save current pixel value
  724.         SetPixel(hdc, 0, 0, dwGDIColor);       // Set our value
  725.         m_pdds->ReleaseDC(hdc);
  726.     }
  727.     // Now lock the surface so we can read back the converted color
  728.     ddsd.dwSize = sizeof(ddsd);
  729.     hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
  730.     if( hr == DD_OK)
  731.     {
  732.         dw = *(DWORD *) ddsd.lpSurface; 
  733.         if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp
  734.             dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1;  
  735.         m_pdds->Unlock(NULL);
  736.     }
  737.     //  Now put the color that was there back.
  738.     if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK )
  739.     {
  740.         SetPixel( hdc, 0, 0, rgbT );
  741.         m_pdds->ReleaseDC(hdc);
  742.     }
  743.     
  744.     return dw;    
  745. }
  746. //-----------------------------------------------------------------------------
  747. // Name: CSurface::GetBitMaskInfo()
  748. // Desc: Returns the number of bits and the shift in the bit mask
  749. //-----------------------------------------------------------------------------
  750. HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits )
  751. {
  752.     DWORD dwShift = 0;
  753.     DWORD dwBits  = 0; 
  754.     if( pdwShift == NULL || pdwBits == NULL )
  755.         return E_INVALIDARG;
  756.     if( dwBitMask )
  757.     {
  758.         while( (dwBitMask & 1) == 0 )
  759.         {
  760.             dwShift++;
  761.             dwBitMask >>= 1;
  762.         }
  763.     }
  764.     while( (dwBitMask & 1) != 0 )
  765.     {
  766.         dwBits++;
  767.         dwBitMask >>= 1;
  768.     }
  769.     *pdwShift = dwShift;
  770.     *pdwBits  = dwBits;
  771.     return S_OK;
  772. }