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