Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

ddutil.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------- 00002 // File: ddutil.cpp 00003 // 00004 // Desc: DirectDraw framewark classes. Feel free to use this class as a 00005 // starting point for adding extra functionality. 00006 // 00007 // 00008 // Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. 00009 //----------------------------------------------------------------------------- 00010 #define STRICT 00011 #include <tchar.h> 00012 #include <windows.h> 00013 #include <windowsx.h> 00014 #include <ddraw.h> 00015 #include "ddutil.h" 00016 #include "dxutil.h" 00017 00018 00019 00020 00021 00022 00023 //----------------------------------------------------------------------------- 00024 // Name: CDisplay() 00025 // Desc: 00026 //----------------------------------------------------------------------------- 00027 CDisplay::CDisplay() 00028 { 00029 m_pDD = NULL; 00030 m_pddsFrontBuffer = NULL; 00031 m_pddsBackBuffer = NULL; 00032 m_pddsBackBufferLeft = NULL; 00033 } 00034 00035 00036 00037 00038 //----------------------------------------------------------------------------- 00039 // Name: ~CDisplay() 00040 // Desc: 00041 //----------------------------------------------------------------------------- 00042 CDisplay::~CDisplay() 00043 { 00044 DestroyObjects(); 00045 } 00046 00047 00048 00049 00050 //----------------------------------------------------------------------------- 00051 // Name: DestroyObjects() 00052 // Desc: 00053 //----------------------------------------------------------------------------- 00054 HRESULT CDisplay::DestroyObjects() 00055 { 00056 SAFE_RELEASE( m_pddsBackBufferLeft ); 00057 SAFE_RELEASE( m_pddsBackBuffer ); 00058 SAFE_RELEASE( m_pddsFrontBuffer ); 00059 00060 if( m_pDD ) 00061 m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); 00062 00063 SAFE_RELEASE( m_pDD ); 00064 00065 return S_OK; 00066 } 00067 00068 00069 00070 00071 //----------------------------------------------------------------------------- 00072 // Name: CreateFullScreenDisplay() 00073 // Desc: 00074 //----------------------------------------------------------------------------- 00075 HRESULT CDisplay::CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, 00076 DWORD dwHeight, DWORD dwBPP ) 00077 { 00078 HRESULT hr; 00079 00080 // Cleanup anything from a previous call 00081 DestroyObjects(); 00082 00083 // DDraw stuff begins here 00084 if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, 00085 IID_IDirectDraw7, NULL ) ) ) 00086 return E_FAIL; 00087 00088 // Set cooperative level 00089 hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); 00090 if( FAILED(hr) ) 00091 return E_FAIL; 00092 00093 // Set the display mode 00094 if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) ) 00095 return E_FAIL; 00096 00097 // Create primary surface (with backbuffer attached) 00098 DDSURFACEDESC2 ddsd; 00099 ZeroMemory( &ddsd, sizeof( ddsd ) ); 00100 ddsd.dwSize = sizeof( ddsd ); 00101 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; 00102 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | 00103 DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; 00104 ddsd.dwBackBufferCount = 1; 00105 00106 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, 00107 NULL ) ) ) 00108 return E_FAIL; 00109 00110 // Get a pointer to the back buffer 00111 DDSCAPS2 ddscaps; 00112 ZeroMemory( &ddscaps, sizeof( ddscaps ) ); 00113 ddscaps.dwCaps = DDSCAPS_BACKBUFFER; 00114 00115 if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps, 00116 &m_pddsBackBuffer ) ) ) 00117 return E_FAIL; 00118 00119 m_pddsBackBuffer->AddRef(); 00120 00121 m_hWnd = hWnd; 00122 m_bWindowed = FALSE; 00123 UpdateBounds(); 00124 00125 return S_OK; 00126 } 00127 00128 00129 00130 00131 //----------------------------------------------------------------------------- 00132 // Name: CreateWindowedDisplay() 00133 // Desc: 00134 //----------------------------------------------------------------------------- 00135 HRESULT CDisplay::CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ) 00136 { 00137 HRESULT hr; 00138 00139 // Cleanup anything from a previous call 00140 DestroyObjects(); 00141 00142 // DDraw stuff begins here 00143 if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD, 00144 IID_IDirectDraw7, NULL ) ) ) 00145 return E_FAIL; 00146 00147 // Set cooperative level 00148 hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); 00149 if( FAILED(hr) ) 00150 return E_FAIL; 00151 00152 RECT rcWork; 00153 RECT rc; 00154 DWORD dwStyle; 00155 00156 // If we are still a WS_POPUP window we should convert to a normal app 00157 // window so we look like a windows app. 00158 dwStyle = GetWindowStyle( hWnd ); 00159 dwStyle &= ~WS_POPUP; 00160 dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; 00161 SetWindowLong( hWnd, GWL_STYLE, dwStyle ); 00162 00163 // Aet window size 00164 SetRect( &rc, 0, 0, dwWidth, dwHeight ); 00165 00166 AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, 00167 GetWindowExStyle(hWnd) ); 00168 00169 SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, 00170 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 00171 00172 SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, 00173 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); 00174 00175 // Make sure our window does not hang outside of the work area 00176 SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); 00177 GetWindowRect( hWnd, &rc ); 00178 if( rc.left < rcWork.left ) rc.left = rcWork.left; 00179 if( rc.top < rcWork.top ) rc.top = rcWork.top; 00180 SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0, 00181 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); 00182 00183 LPDIRECTDRAWCLIPPER pcClipper; 00184 00185 // Create the primary surface 00186 DDSURFACEDESC2 ddsd; 00187 ZeroMemory( &ddsd, sizeof( ddsd ) ); 00188 ddsd.dwSize = sizeof( ddsd ); 00189 ddsd.dwFlags = DDSD_CAPS; 00190 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 00191 00192 if( FAILED( m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) ) 00193 return E_FAIL; 00194 00195 // Create the backbuffer surface 00196 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 00197 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; 00198 ddsd.dwWidth = dwWidth; 00199 ddsd.dwHeight = dwHeight; 00200 00201 if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) ) 00202 return E_FAIL; 00203 00204 if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) ) 00205 return E_FAIL; 00206 00207 if( FAILED( hr = pcClipper->SetHWnd( 0, hWnd ) ) ) 00208 { 00209 pcClipper->Release(); 00210 return E_FAIL; 00211 } 00212 00213 if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pcClipper ) ) ) 00214 { 00215 pcClipper->Release(); 00216 return E_FAIL; 00217 } 00218 00219 // Done with clipper 00220 pcClipper->Release(); 00221 00222 m_hWnd = hWnd; 00223 m_bWindowed = TRUE; 00224 UpdateBounds(); 00225 00226 return S_OK; 00227 } 00228 00229 00230 00231 00232 //----------------------------------------------------------------------------- 00233 // Name: 00234 // Desc: 00235 //----------------------------------------------------------------------------- 00236 HRESULT CDisplay::CreateSurface( CSurface** ppSurface, 00237 DWORD dwWidth, DWORD dwHeight ) 00238 { 00239 if( NULL == m_pDD ) 00240 return E_POINTER; 00241 if( NULL == ppSurface ) 00242 return E_INVALIDARG; 00243 00244 HRESULT hr; 00245 DDSURFACEDESC2 ddsd; 00246 ZeroMemory( &ddsd, sizeof( ddsd ) ); 00247 ddsd.dwSize = sizeof( ddsd ); 00248 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 00249 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 00250 ddsd.dwWidth = dwWidth; 00251 ddsd.dwHeight = dwHeight; 00252 00253 (*ppSurface) = new CSurface(); 00254 if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) 00255 { 00256 delete (*ppSurface); 00257 return hr; 00258 } 00259 00260 return S_OK; 00261 } 00262 00263 00264 00265 00266 //----------------------------------------------------------------------------- 00267 // Name: CDisplay::CreateSurfaceFromBitmap() 00268 // Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file. 00269 // Use MAKEINTRESOURCE() to pass a constant into strBMP. 00270 //----------------------------------------------------------------------------- 00271 HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface, 00272 TCHAR* strBMP, 00273 DWORD dwDesiredWidth, 00274 DWORD dwDesiredHeight ) 00275 { 00276 HRESULT hr; 00277 HBITMAP hBMP = NULL; 00278 BITMAP bmp; 00279 DDSURFACEDESC2 ddsd; 00280 00281 if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) 00282 return E_INVALIDARG; 00283 00284 *ppSurface = NULL; 00285 00286 // Try to load the bitmap as a resource, if that fails, try it as a file 00287 hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, 00288 IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, 00289 LR_CREATEDIBSECTION ); 00290 if( hBMP == NULL ) 00291 { 00292 hBMP = (HBITMAP) LoadImage( NULL, strBMP, 00293 IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, 00294 LR_LOADFROMFILE | LR_CREATEDIBSECTION ); 00295 if( hBMP == NULL ) 00296 return E_FAIL; 00297 } 00298 00299 // Get size of the bitmap 00300 GetObject( hBMP, sizeof(bmp), &bmp ); 00301 00302 // Create a DirectDrawSurface for this bitmap 00303 ZeroMemory( &ddsd, sizeof(ddsd) ); 00304 ddsd.dwSize = sizeof(ddsd); 00305 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; 00306 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 00307 ddsd.dwWidth = bmp.bmWidth; 00308 ddsd.dwHeight = bmp.bmHeight; 00309 00310 (*ppSurface) = new CSurface(); 00311 if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) 00312 { 00313 delete (*ppSurface); 00314 return hr; 00315 } 00316 00317 // Draw the bitmap on this surface 00318 if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) 00319 { 00320 DeleteObject( hBMP ); 00321 return hr; 00322 } 00323 00324 DeleteObject( hBMP ); 00325 00326 return S_OK; 00327 } 00328 00329 00330 00331 00332 //----------------------------------------------------------------------------- 00333 // Name: CDisplay::CreateSurfaceFromText() 00334 // Desc: Creates a DirectDrawSurface from a text string using hFont or the default 00335 // GDI font if hFont is NULL. 00336 //----------------------------------------------------------------------------- 00337 HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface, 00338 HFONT hFont, TCHAR* strText, 00339 COLORREF crBackground, COLORREF crForeground ) 00340 { 00341 HDC hDC = NULL; 00342 LPDIRECTDRAWSURFACE7 pDDS = NULL; 00343 HRESULT hr; 00344 DDSURFACEDESC2 ddsd; 00345 SIZE sizeText; 00346 00347 if( m_pDD == NULL || strText == NULL || ppSurface == NULL ) 00348 return E_INVALIDARG; 00349 00350 *ppSurface = NULL; 00351 00352 hDC = GetDC( NULL ); 00353 00354 if( hFont ) 00355 SelectObject( hDC, hFont ); 00356 00357 GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); 00358 ReleaseDC( NULL, hDC ); 00359 00360 // Create a DirectDrawSurface for this bitmap 00361 ZeroMemory( &ddsd, sizeof(ddsd) ); 00362 ddsd.dwSize = sizeof(ddsd); 00363 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; 00364 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 00365 ddsd.dwWidth = sizeText.cx; 00366 ddsd.dwHeight = sizeText.cy; 00367 00368 (*ppSurface) = new CSurface(); 00369 if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) 00370 { 00371 delete (*ppSurface); 00372 return hr; 00373 } 00374 00375 if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, 0, 0, 00376 crBackground, crForeground ) ) ) 00377 return hr; 00378 00379 return S_OK; 00380 } 00381 00382 00383 00384 00385 //----------------------------------------------------------------------------- 00386 // Name: 00387 // Desc: 00388 //----------------------------------------------------------------------------- 00389 HRESULT CDisplay::Present() 00390 { 00391 HRESULT hr; 00392 00393 if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) 00394 return E_POINTER; 00395 00396 while( 1 ) 00397 { 00398 if( m_bWindowed ) 00399 hr = m_pddsFrontBuffer->Blt( &m_rcWindow, m_pddsBackBuffer, 00400 NULL, DDBLT_WAIT, NULL ); 00401 else 00402 hr = m_pddsFrontBuffer->Flip( NULL, 0 ); 00403 00404 if( hr == DDERR_SURFACELOST ) 00405 { 00406 m_pddsFrontBuffer->Restore(); 00407 m_pddsBackBuffer->Restore(); 00408 } 00409 00410 if( hr != DDERR_WASSTILLDRAWING ) 00411 return hr; 00412 } 00413 } 00414 00415 00416 00417 00418 //----------------------------------------------------------------------------- 00419 // Name: 00420 // Desc: 00421 //----------------------------------------------------------------------------- 00422 HRESULT CDisplay::ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette ) 00423 { 00424 if( NULL == m_pddsFrontBuffer || NULL == m_pddsBackBuffer ) 00425 return E_POINTER; 00426 00427 // Set the palette before loading the bitmap 00428 if( pPalette ) 00429 m_pddsFrontBuffer->SetPalette( pPalette ); 00430 00431 CSurface backBuffer; 00432 backBuffer.Create( m_pddsBackBuffer ); 00433 00434 if( FAILED( backBuffer.DrawBitmap( hbm, 0, 0, 0, 0 ) ) ) 00435 return E_FAIL; 00436 00437 return Present(); 00438 } 00439 00440 00441 00442 00443 //----------------------------------------------------------------------------- 00444 // Name: 00445 // Desc: 00446 //----------------------------------------------------------------------------- 00447 HRESULT CDisplay::ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, 00448 RECT* prc ) 00449 { 00450 if( NULL == m_pddsBackBuffer ) 00451 return E_POINTER; 00452 00453 return m_pddsBackBuffer->BltFast( x, y, pdds, prc, DDBLTFAST_SRCCOLORKEY ); 00454 } 00455 00456 00457 00458 00459 //----------------------------------------------------------------------------- 00460 // Name: 00461 // Desc: 00462 //----------------------------------------------------------------------------- 00463 HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc, 00464 DWORD dwFlags ) 00465 { 00466 if( NULL == m_pddsBackBuffer ) 00467 return E_POINTER; 00468 00469 return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags ); 00470 } 00471 00472 00473 00474 00475 //----------------------------------------------------------------------------- 00476 // Name: 00477 // Desc: 00478 //----------------------------------------------------------------------------- 00479 HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc ) 00480 { 00481 if( NULL == pSurface ) 00482 return E_INVALIDARG; 00483 00484 if( pSurface->IsColorKeyed() ) 00485 return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY ); 00486 else 00487 return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L ); 00488 } 00489 00490 00491 00492 00493 //----------------------------------------------------------------------------- 00494 // Name: 00495 // Desc: 00496 //----------------------------------------------------------------------------- 00497 HRESULT CDisplay::Clear( DWORD dwColor ) 00498 { 00499 if( NULL == m_pddsBackBuffer ) 00500 return E_POINTER; 00501 00502 // Erase the background 00503 DDBLTFX ddbltfx; 00504 ZeroMemory( &ddbltfx, sizeof(ddbltfx) ); 00505 ddbltfx.dwSize = sizeof(ddbltfx); 00506 ddbltfx.dwFillColor = dwColor; 00507 00508 return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); 00509 } 00510 00511 00512 00513 00514 //----------------------------------------------------------------------------- 00515 // Name: 00516 // Desc: 00517 //----------------------------------------------------------------------------- 00518 HRESULT CDisplay::SetPalette( LPDIRECTDRAWPALETTE pPalette ) 00519 { 00520 if( NULL == m_pddsFrontBuffer ) 00521 return E_POINTER; 00522 00523 return m_pddsFrontBuffer->SetPalette( pPalette ); 00524 } 00525 00526 00527 00528 00529 //----------------------------------------------------------------------------- 00530 // Name: 00531 // Desc: 00532 //----------------------------------------------------------------------------- 00533 HRESULT CDisplay::CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, 00534 const TCHAR* strBMP ) 00535 { 00536 HRSRC hResource = NULL; 00537 RGBQUAD* pRGB = NULL; 00538 BITMAPINFOHEADER* pbi = NULL; 00539 PALETTEENTRY aPalette[256]; 00540 HANDLE hFile = NULL; 00541 DWORD iColor; 00542 DWORD dwColors; 00543 BITMAPFILEHEADER bf; 00544 BITMAPINFOHEADER bi; 00545 DWORD dwBytesRead; 00546 00547 if( m_pDD == NULL || strBMP == NULL || ppPalette == NULL ) 00548 return E_INVALIDARG; 00549 00550 *ppPalette = NULL; 00551 00552 // Try to load the bitmap as a resource, if that fails, try it as a file 00553 hResource = FindResource( NULL, strBMP, RT_BITMAP ); 00554 if( hResource ) 00555 { 00556 pbi = (LPBITMAPINFOHEADER) LockResource( LoadResource( NULL, hResource ) ); 00557 if( NULL == pbi ) 00558 return E_FAIL; 00559 00560 pRGB = (RGBQUAD*) ( (BYTE*) pbi + pbi->biSize ); 00561 00562 // Figure out how many colors there are 00563 if( pbi == NULL || pbi->biSize < sizeof(BITMAPINFOHEADER) ) 00564 dwColors = 0; 00565 else if( pbi->biBitCount > 8 ) 00566 dwColors = 0; 00567 else if( pbi->biClrUsed == 0 ) 00568 dwColors = 1 << pbi->biBitCount; 00569 else 00570 dwColors = pbi->biClrUsed; 00571 00572 // A DIB color table has its colors stored BGR not RGB 00573 // so flip them around. 00574 for( iColor = 0; iColor < dwColors; iColor++ ) 00575 { 00576 aPalette[iColor].peRed = pRGB[iColor].rgbRed; 00577 aPalette[iColor].peGreen = pRGB[iColor].rgbGreen; 00578 aPalette[iColor].peBlue = pRGB[iColor].rgbBlue; 00579 aPalette[iColor].peFlags = 0; 00580 } 00581 00582 return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); 00583 } 00584 00585 // Attempt to load bitmap as a file 00586 hFile = CreateFile( strBMP, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); 00587 if( NULL == hFile ) 00588 return E_FAIL; 00589 00590 // Read the BITMAPFILEHEADER 00591 ReadFile( hFile, &bf, sizeof(bf), &dwBytesRead, NULL ); 00592 if( dwBytesRead != sizeof(bf) ) 00593 { 00594 CloseHandle( hFile ); 00595 return E_FAIL; 00596 } 00597 00598 // Read the BITMAPINFOHEADER 00599 ReadFile( hFile, &bi, sizeof(bi), &dwBytesRead, NULL ); 00600 if( dwBytesRead != sizeof(bi) ) 00601 { 00602 CloseHandle( hFile ); 00603 return E_FAIL; 00604 } 00605 00606 // Read the PALETTEENTRY 00607 ReadFile( hFile, aPalette, sizeof(aPalette), &dwBytesRead, NULL ); 00608 if( dwBytesRead != sizeof(aPalette) ) 00609 { 00610 CloseHandle( hFile ); 00611 return E_FAIL; 00612 } 00613 00614 CloseHandle( hFile ); 00615 00616 // Figure out how many colors there are 00617 if( bi.biSize != sizeof(BITMAPINFOHEADER) ) 00618 dwColors = 0; 00619 else if (bi.biBitCount > 8) 00620 dwColors = 0; 00621 else if (bi.biClrUsed == 0) 00622 dwColors = 1 << bi.biBitCount; 00623 else 00624 dwColors = bi.biClrUsed; 00625 00626 // A DIB color table has its colors stored BGR not RGB 00627 // so flip them around since DirectDraw uses RGB 00628 for( iColor = 0; iColor < dwColors; iColor++ ) 00629 { 00630 BYTE r = aPalette[iColor].peRed; 00631 aPalette[iColor].peRed = aPalette[iColor].peBlue; 00632 aPalette[iColor].peBlue = r; 00633 } 00634 00635 return m_pDD->CreatePalette( DDPCAPS_8BIT, aPalette, ppPalette, NULL ); 00636 } 00637 00638 00639 00640 00641 //----------------------------------------------------------------------------- 00642 // Name: 00643 // Desc: 00644 //----------------------------------------------------------------------------- 00645 HRESULT CDisplay::UpdateBounds() 00646 { 00647 if( m_bWindowed ) 00648 { 00649 GetClientRect( m_hWnd, &m_rcWindow ); 00650 ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); 00651 ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); 00652 } 00653 else 00654 { 00655 SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), 00656 GetSystemMetrics(SM_CYSCREEN) ); 00657 } 00658 00659 return S_OK; 00660 } 00661 00662 00663 00664 00665 00666 //----------------------------------------------------------------------------- 00667 // Name: CDisplay::InitClipper 00668 // Desc: 00669 //----------------------------------------------------------------------------- 00670 HRESULT CDisplay::InitClipper() 00671 { 00672 LPDIRECTDRAWCLIPPER pClipper; 00673 HRESULT hr; 00674 00675 // Create a clipper when using GDI to draw on the primary surface 00676 if( FAILED( hr = m_pDD->CreateClipper( 0, &pClipper, NULL ) ) ) 00677 return hr; 00678 00679 pClipper->SetHWnd( 0, m_hWnd ); 00680 00681 if( FAILED( hr = m_pddsFrontBuffer->SetClipper( pClipper ) ) ) 00682 return hr; 00683 00684 // We can release the clipper now since g_pDDSPrimary 00685 // now maintains a ref count on the clipper 00686 SAFE_RELEASE( pClipper ); 00687 00688 return S_OK; 00689 } 00690 00691 00692 00693 00694 00695 //----------------------------------------------------------------------------- 00696 // Name: 00697 // Desc: 00698 //----------------------------------------------------------------------------- 00699 CSurface::CSurface() 00700 { 00701 m_pdds = NULL; 00702 m_bColorKeyed = NULL; 00703 } 00704 00705 00706 00707 00708 //----------------------------------------------------------------------------- 00709 // Name: 00710 // Desc: 00711 //----------------------------------------------------------------------------- 00712 CSurface::~CSurface() 00713 { 00714 SAFE_RELEASE( m_pdds ); 00715 } 00716 00717 00718 00719 00720 //----------------------------------------------------------------------------- 00721 // Name: 00722 // Desc: 00723 //----------------------------------------------------------------------------- 00724 HRESULT CSurface::Create( LPDIRECTDRAWSURFACE7 pdds ) 00725 { 00726 m_pdds = pdds; 00727 00728 if( m_pdds ) 00729 { 00730 m_pdds->AddRef(); 00731 00732 // Get the DDSURFACEDESC structure for this surface 00733 m_ddsd.dwSize = sizeof(m_ddsd); 00734 m_pdds->GetSurfaceDesc( &m_ddsd ); 00735 } 00736 00737 return S_OK; 00738 } 00739 00740 00741 00742 00743 //----------------------------------------------------------------------------- 00744 // Name: 00745 // Desc: 00746 //----------------------------------------------------------------------------- 00747 HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ) 00748 { 00749 HRESULT hr; 00750 00751 // Create the DDraw surface 00752 if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) ) 00753 return hr; 00754 00755 // Prepare the DDSURFACEDESC structure 00756 m_ddsd.dwSize = sizeof(m_ddsd); 00757 00758 // Get the DDSURFACEDESC structure for this surface 00759 m_pdds->GetSurfaceDesc( &m_ddsd ); 00760 00761 return S_OK; 00762 } 00763 00764 00765 00766 00767 //----------------------------------------------------------------------------- 00768 // Name: 00769 // Desc: 00770 //----------------------------------------------------------------------------- 00771 HRESULT CSurface::Destroy() 00772 { 00773 SAFE_RELEASE( m_pdds ); 00774 return S_OK; 00775 } 00776 00777 00778 00779 00780 //----------------------------------------------------------------------------- 00781 // Name: CSurface::DrawBitmap() 00782 // Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the 00783 // bitmap if nessasary 00784 //----------------------------------------------------------------------------- 00785 HRESULT CSurface::DrawBitmap( HBITMAP hBMP, 00786 DWORD dwBMPOriginX, DWORD dwBMPOriginY, 00787 DWORD dwBMPWidth, DWORD dwBMPHeight ) 00788 { 00789 HDC hDCImage; 00790 HDC hDC; 00791 BITMAP bmp; 00792 DDSURFACEDESC2 ddsd; 00793 HRESULT hr; 00794 00795 if( hBMP == NULL || m_pdds == NULL ) 00796 return E_INVALIDARG; 00797 00798 // Make sure this surface is restored. 00799 if( FAILED( hr = m_pdds->Restore() ) ) 00800 return hr; 00801 00802 // Get the surface.description 00803 ddsd.dwSize = sizeof(ddsd); 00804 m_pdds->GetSurfaceDesc( &ddsd ); 00805 00806 if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) 00807 return E_NOTIMPL; 00808 00809 // Select bitmap into a memoryDC so we can use it. 00810 hDCImage = CreateCompatibleDC( NULL ); 00811 if( NULL == hDCImage ) 00812 return E_FAIL; 00813 00814 SelectObject( hDCImage, hBMP ); 00815 00816 // Get size of the bitmap 00817 GetObject( hBMP, sizeof(bmp), &bmp ); 00818 00819 // Use the passed size, unless zero 00820 dwBMPWidth = ( dwBMPWidth == 0 ) ? bmp.bmWidth : dwBMPWidth; 00821 dwBMPHeight = ( dwBMPHeight == 0 ) ? bmp.bmHeight : dwBMPHeight; 00822 00823 // Stretch the bitmap to cover this surface 00824 if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) 00825 return hr; 00826 00827 StretchBlt( hDC, 0, 0, 00828 ddsd.dwWidth, ddsd.dwHeight, 00829 hDCImage, dwBMPOriginX, dwBMPOriginY, 00830 dwBMPWidth, dwBMPHeight, SRCCOPY ); 00831 00832 if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) 00833 return hr; 00834 00835 DeleteDC( hDCImage ); 00836 00837 return S_OK; 00838 } 00839 00840 00841 00842 00843 //----------------------------------------------------------------------------- 00844 // Name: CSurface::DrawText() 00845 // Desc: Draws a text string on a DirectDraw surface using hFont or the default 00846 // GDI font if hFont is NULL. 00847 //----------------------------------------------------------------------------- 00848 HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText, 00849 DWORD dwOriginX, DWORD dwOriginY, 00850 COLORREF crBackground, COLORREF crForeground ) 00851 { 00852 HDC hDC = NULL; 00853 HRESULT hr; 00854 00855 if( m_pdds == NULL || strText == NULL ) 00856 return E_INVALIDARG; 00857 00858 // Make sure this surface is restored. 00859 if( FAILED( hr = m_pdds->Restore() ) ) 00860 return hr; 00861 00862 if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) 00863 return hr; 00864 00865 // Set the background and foreground color 00866 SetBkColor( hDC, crBackground ); 00867 SetTextColor( hDC, crForeground ); 00868 00869 if( hFont ) 00870 SelectObject( hDC, hFont ); 00871 00872 // Use GDI to draw the text on the surface 00873 TextOut( hDC, dwOriginX, dwOriginY, strText, _tcslen(strText) ); 00874 00875 if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) ) 00876 return hr; 00877 00878 return S_OK; 00879 } 00880 00881 00882 00883 00884 //----------------------------------------------------------------------------- 00885 // Name: CSurface::ReDrawBitmapOnSurface() 00886 // Desc: Load a bitmap from a file or resource into a DirectDraw surface. 00887 // normaly used to re-load a surface after a restore. 00888 //----------------------------------------------------------------------------- 00889 HRESULT CSurface::DrawBitmap( TCHAR* strBMP, 00890 DWORD dwDesiredWidth, DWORD dwDesiredHeight ) 00891 { 00892 HBITMAP hBMP; 00893 HRESULT hr; 00894 00895 if( m_pdds == NULL || strBMP == NULL ) 00896 return E_INVALIDARG; 00897 00898 // Try to load the bitmap as a resource, if that fails, try it as a file 00899 hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP, 00900 IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight, 00901 LR_CREATEDIBSECTION ); 00902 if( hBMP == NULL ) 00903 { 00904 hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP, 00905 dwDesiredWidth, dwDesiredHeight, 00906 LR_LOADFROMFILE | LR_CREATEDIBSECTION ); 00907 if( hBMP == NULL ) 00908 return E_FAIL; 00909 } 00910 00911 // Draw the bitmap on this surface 00912 if( FAILED( hr = DrawBitmap( hBMP, 0, 0, 0, 0 ) ) ) 00913 { 00914 DeleteObject( hBMP ); 00915 return hr; 00916 } 00917 00918 DeleteObject( hBMP ); 00919 00920 return S_OK; 00921 } 00922 00923 00924 00925 00926 //----------------------------------------------------------------------------- 00927 // Name: 00928 // Desc: 00929 //----------------------------------------------------------------------------- 00930 HRESULT CSurface::SetColorKey( DWORD dwColorKey ) 00931 { 00932 if( NULL == m_pdds ) 00933 return E_POINTER; 00934 00935 m_bColorKeyed = TRUE; 00936 00937 DDCOLORKEY ddck; 00938 ddck.dwColorSpaceLowValue = ConvertGDIColor( dwColorKey ); 00939 ddck.dwColorSpaceHighValue = ConvertGDIColor( dwColorKey ); 00940 00941 return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck ); 00942 } 00943 00944 00945 00946 00947 00948 //----------------------------------------------------------------------------- 00949 // Name: CSurface::ConvertGDIColor() 00950 // Desc: Converts a GDI color (0x00bbggrr) into the equivalent color on a 00951 // DirectDrawSurface using its pixel format. 00952 //----------------------------------------------------------------------------- 00953 DWORD CSurface::ConvertGDIColor( COLORREF dwGDIColor ) 00954 { 00955 if( m_pdds == NULL ) 00956 return 0x00000000; 00957 00958 COLORREF rgbT; 00959 HDC hdc; 00960 DWORD dw = CLR_INVALID; 00961 DDSURFACEDESC2 ddsd; 00962 HRESULT hr; 00963 00964 // Use GDI SetPixel to color match for us 00965 if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK) 00966 { 00967 rgbT = GetPixel(hdc, 0, 0); // Save current pixel value 00968 SetPixel(hdc, 0, 0, dwGDIColor); // Set our value 00969 m_pdds->ReleaseDC(hdc); 00970 } 00971 00972 // Now lock the surface so we can read back the converted color 00973 ddsd.dwSize = sizeof(ddsd); 00974 hr = m_pdds->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); 00975 if( hr == DD_OK) 00976 { 00977 dw = *(DWORD *) ddsd.lpSurface; 00978 if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp 00979 dw &= ( 1 << ddsd.ddpfPixelFormat.dwRGBBitCount ) - 1; 00980 m_pdds->Unlock(NULL); 00981 } 00982 00983 // Now put the color that was there back. 00984 if( dwGDIColor != CLR_INVALID && m_pdds->GetDC(&hdc) == DD_OK ) 00985 { 00986 SetPixel( hdc, 0, 0, rgbT ); 00987 m_pdds->ReleaseDC(hdc); 00988 } 00989 00990 return dw; 00991 } 00992 00993 00994 00995 00996 //----------------------------------------------------------------------------- 00997 // Name: CSurface::GetBitMaskInfo() 00998 // Desc: Returns the number of bits and the shift in the bit mask 00999 //----------------------------------------------------------------------------- 01000 HRESULT CSurface::GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ) 01001 { 01002 DWORD dwShift = 0; 01003 DWORD dwBits = 0; 01004 01005 if( pdwShift == NULL || pdwBits == NULL ) 01006 return E_INVALIDARG; 01007 01008 if( dwBitMask ) 01009 { 01010 while( (dwBitMask & 1) == 0 ) 01011 { 01012 dwShift++; 01013 dwBitMask >>= 1; 01014 } 01015 } 01016 01017 while( (dwBitMask & 1) != 0 ) 01018 { 01019 dwBits++; 01020 dwBitMask >>= 1; 01021 } 01022 01023 *pdwShift = dwShift; 01024 *pdwBits = dwBits; 01025 01026 return S_OK; 01027 } 01028 01029 01030 01031

Generated on Fri May 21 19:22:36 2004 for LIBELL by doxygen 1.3.7