#define STRICT #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #include #include #include #include #include #include #include KDirectDrawOverlay:: KDirectDrawOverlay() { m_bmp_file_name = new TCHAR[MAX_PATH]; } KDirectDrawOverlay:: ~KDirectDrawOverlay() { Discharge(); } HRESULT KDirectDrawOverlay:: Discharge() { m_backbuffer.Discharge(); m_overlay.Discharge(); delete m_bmp_file_name; return S_OK; } #define pDriverGUID NULL /************************************************** Save the Direct Draw state in the memeber variables and create the device and surfaces as requested. **************************************************/ HRESULT KDirectDrawOverlay:: SetupDirectDraw(HWND hTop, HWND hWnd, const TCHAR * bmp_file, int buf_count, bool full_screen, int w, int h, int bpp) { HRESULT hr; m_hTop = hTop; m_hWnd = hWnd; m_full_screen = full_screen; m_w = w; m_h=h; m_bpp=bpp; m_mode_changed = false; m_buf_count = buf_count; hr = DirectDrawCreateEx(pDriverGUID, (void **) &m_pDD, IID_IDirectDraw7, NULL); #ifdef KDEBUG e_dx.Test(hr, __FILE__, __LINE__, "DirectDrawCreateEx"); #endif memset(&m_ddcaps, 0, sizeof(m_ddcaps)); m_ddcaps.dwSize = sizeof(m_ddcaps); m_pDD->GetCaps(&m_ddcaps, NULL); Init(hTop, hWnd, full_screen, w, h, bpp); m_primary.CreatePrimarySurface(m_pDD, 0); bool b_ret; b_ret = m_overlay.Init(m_ddcaps, w, h, buf_count); #ifdef KDEBUG if(b_ret == false) { KException::KDxException e_dx; e_dx.SetErrCode(1); e_dx.SetErrString("Overlay support not available."); throw e_dx; } #endif m_overlay.CreateOverlaySurface(m_pDD); m_overlay.GetBackBuffer( m_backbuffer ); //KDirectDrawOverlay:: LoadBitmap(L"m_in_black_2.bmp"); KDirectDrawOverlay:: LoadBitmap(bmp_file); // Set overlay source color key. //DWORD color_black = m_overlay.ColorMatch(0x00, 0x00, 0x00); //m_overlay.SetOverlaySourceColorKey(m_ddcaps, color_black); return hr; } /************************************************** Set the cooperative level. **************************************************/ void KDirectDrawOverlay:: Init(HWND hTop, HWND hWnd, bool full_screen, DWORD w, DWORD h, DWORD bpp) { HRESULT hr; if(full_screen) { hr = m_pDD->SetCooperativeLevel(hTop, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); #ifdef KDEBUG e_dx.Test(hr, __FILE__, __LINE__, "Init:SetCooperativeLevel"); #endif hr = m_pDD->SetDisplayMode(w, h, bpp, 0, 0); #ifdef KDEBUG e_dx.Test(hr, __FILE__, __LINE__, "Init:SetDisplayMode"); #endif } else { hr = m_pDD->SetCooperativeLevel( 0, DDSCL_NORMAL ); #ifdef KDEBUG e_dx.Test(hr, __FILE__, __LINE__, "Init:SetCooperativeLevel"); #endif } } /************************************************** Before rendering each frame, call this function to test if the Direct Draw state has changed. If a change is detected, do all that is necessary to restore the state - release the resources, reallocate, recreate surfaces, and reload bitmaps. **************************************************/ bool KDirectDrawOverlay:: TestStateAndRecover(void) { HRESULT hr; hr = m_pDD->TestCooperativeLevel(); #ifdef KDEBUG e_dx.Test(hr, __FILE__, __LINE__, "TestStateAndRecover:TestCooperativeLevel"); #endif switch(hr) { case DDERR_INVALIDOBJECT: return false; case DDERR_EXCLUSIVEMODEALREADYSET: m_full_screen=false; do { Sleep(500); }while(m_pDD->TestCooperativeLevel() != DD_OK); m_full_screen=true; //m_primary.RestoreSurface(); //m_overlay.RestoreSurface(); m_pDD->RestoreAllSurfaces(); ReLoadBitmap(); return false; case DDERR_NOEXCLUSIVEMODE: m_full_screen=false; do { Sleep(500); }while(m_pDD->TestCooperativeLevel() != DD_OK); m_full_screen=true; //m_primary.RestoreSurface(); //m_overlay.RestoreSurface(); m_pDD->RestoreAllSurfaces(); ReLoadBitmap(); return false; case DDERR_WRONGMODE: DWORD w,h,bpp; GetDisplayMode(w,h,bpp); if((m_w != w) || (m_h != h) || (m_bpp != bpp)) { m_mode_changed=true; m_w=w; m_h=h; m_bpp=bpp; m_primary.Discharge(); m_overlay.Discharge(); Init(m_hTop, m_hWnd, m_full_screen, m_w, m_h, m_bpp); m_primary.CreatePrimarySurface(m_pDD, 0); m_overlay.Init(m_ddcaps, m_w, m_h, m_buf_count); m_overlay.CreateOverlaySurface(m_pDD); m_overlay.GetBackBuffer(m_backbuffer); if(m_overlay.OverlaySourceColorKeySet()) m_overlay.SetOverlaySourceColorKey(m_ddcaps, m_overlay.ColorMatch(0x00, 0x00, 0x00)); ReLoadBitmap(); } return false; case DD_OK: if(m_mode_changed) { m_mode_changed=false; GetDisplayMode(m_w,m_h,m_bpp); m_primary.Discharge(); m_overlay.Discharge(); Init(m_hTop, m_hWnd, m_full_screen, m_w, m_h, m_bpp); m_primary.CreatePrimarySurface(m_pDD, 0); m_overlay.Init(m_ddcaps, m_w, m_h, m_buf_count); m_overlay.CreateOverlaySurface(m_pDD); m_overlay.GetBackBuffer(m_backbuffer); if(m_overlay.OverlaySourceColorKeySet()) m_overlay.SetOverlaySourceColorKey(m_ddcaps, m_overlay.ColorMatch(0x00, 0x00, 0x00)); ReLoadBitmap(); } return true; } } void KDirectDrawOverlay:: LoadBitmap(const TCHAR * file_name) { StringCchCopy(m_bmp_file_name, (size_t)MAX_PATH, file_name); m_dib=::LoadBMPFile( file_name ); m_overlay.DrawBitmap( m_dib, 0, 0, m_dib->bmiHeader.biWidth-1, m_dib->bmiHeader.biHeight-1); } void KDirectDrawOverlay:: ReLoadBitmap(void) { m_dib=::LoadBMPFile( m_bmp_file_name ); m_overlay.DrawBitmap( m_dib, 0, 0, m_dib->bmiHeader.biWidth-1, m_dib->bmiHeader.biHeight-1); } void KDirectDrawOverlay:: GetDisplayMode(DWORD& w, DWORD& h, DWORD& bpp) { HRESULT hr; DDSURFACEDESC2 ddsd; memset(& ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; hr = m_pDD->GetDisplayMode( & ddsd ); #ifdef KDEBUG e_dx.Test(hr, __FILE__, __LINE__, "GetDisplayMode:GetDisplayMode"); #endif w = ddsd.dwWidth; h = ddsd.dwHeight; switch( ddsd.ddpfPixelFormat.dwFlags ) { case DDPF_PALETTEINDEXED1: bpp = 1; break; case DDPF_PALETTEINDEXED2: bpp = 2; break; case DDPF_PALETTEINDEXED4: bpp = 4; break; case DDPF_PALETTEINDEXED8: bpp = 8; break; case DDPF_RGB: bpp = ddsd.ddpfPixelFormat.dwRGBBitCount; break; } }