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