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

游戏

开发平台:

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