⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dxsurfacemgr.h

📁 dianzi shuju ,tai badao le ,my tian li a a
💻 H
📖 第 1 页 / 共 2 页
字号:
#pragma once

const HDC NULL_HDC = 0;

#include <atlbase.h>
#include <memory>
#include <ddraw.h>
#pragma comment(lib,"ddraw.lib")


BOOL DXErrorString(HRESULT hResult, LPTSTR lpszErrorBuff, DWORD cchError);

struct XRect : tagRECT
{
	XRect()
	{	}
	XRect(int l, int t, int r, int b)
	{ left = l; top = t; right = r; bottom = b; }
	XRect(const RECT& srcRect)
	{ ::CopyRect(this, &srcRect); }
	XRect(LPCRECT lpSrcRect)
	{ ::CopyRect(this, lpSrcRect); }
	XRect(POINT point, SIZE size)
	{ right = (left = point.x) + size.cx; bottom = (top = point.y) + size.cy; }
	XRect(POINT topLeft, POINT bottomRight)
	{   left = topLeft.x; top = topLeft.y;right = bottomRight.x; bottom = bottomRight.y; }
	
	int Width() const
	{ return right - left; }

	int Height() const
	{ return bottom - top; }
	
	operator LPRECT()
	{ return this; }
	
	operator LPCRECT() const
	{ return this; }
	
	BOOL IsRectEmpty() const
	{ return ::IsRectEmpty(this); }
	
	BOOL IsRectNull() const
	{ return (left == 0 && right == 0 && top == 0 && bottom == 0); }

	BOOL PtInRect(POINT point) const
	{ return ::PtInRect(this, point); }

	void operator=(const RECT& srcRect)
	{ ::CopyRect(this, &srcRect); }
	
	BOOL operator==(const RECT& rect) const
	{ return ::EqualRect(this, &rect); }
	
	BOOL operator!=(const RECT& rect) const
	{ return !::EqualRect(this, &rect); }

};

// this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
#define _RGB16BIT555(r,g,b) ((b%32) + ((g%32) << 5) + ((r%32) << 10))

// this builds a 16 bit color value in 5.6.5 format (green dominate mode)
#define _RGB16BIT565(r,g,b) ((b%32) + ((g%64) << 5) + ((r%32) << 11))

interface ClrConverter
{
	virtual DWORD Convert(int r, int g, int b) = 0;
};

struct CRGB8BIT : ClrConverter
{
	DWORD lastasked_,lastgot_;
	CComPtr<IDirectDrawSurface> srfc_;

	CRGB8BIT(IDirectDrawSurface* srfc)
		:srfc_(srfc), lastasked_(-1)
	{	}

	DWORD Convert(int r, int g, int b)
	{
		COLORREF dwGDIColor = RGB(r,g,b);
		if(lastasked_==dwGDIColor)
			return lastgot_;

		lastasked_ = dwGDIColor;
		COLORREF       rgbT;
		//  Use GDI SetPixel to color match for us
		HDC hdc;
		if( dwGDIColor != CLR_INVALID && srfc_->GetDC(&hdc) == DD_OK)
		{
			rgbT = GetPixel(hdc, 0, 0);     // Save current pixel value
			SetPixel(hdc, 0, 0, dwGDIColor);       // Set our value
			srfc_->ReleaseDC(hdc);
		}

		// Now lock the surface so we can read back the converted color
		DWORD dw = CLR_INVALID;
		DDSURFACEDESC  ddsd;
		ddsd.dwSize = sizeof(ddsd);
		HRESULT hr = srfc_->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
		if(SUCCEEDED(hr))
		{
			dw = *(DWORD *) ddsd.lpSurface; 
//			if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 ) // Mask it to bpp
				dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;  
			srfc_->Unlock(NULL);
		}

		//  Now put the color that was there back.
		if(dwGDIColor != CLR_INVALID && srfc_->GetDC(&hdc) == DD_OK)
		{
			SetPixel( hdc, 0, 0, rgbT );
			srfc_->ReleaseDC(hdc);
		}

		lastgot_ = dw;
		return dw;    
	}

};

struct CRGB24BIT : ClrConverter
{
	DWORD Convert(int r, int g, int b)
	{
		return ((b) + ((g) << 8) + ((r) << 16));
	}
};

struct CRGB32BIT : ClrConverter
{
	DWORD Convert(int r, int g, int b)
	{
		int a = 0;
		return ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24));
	}
};

struct CRGBTo16BIT565 : ClrConverter
{
	DWORD Convert(int r, int g, int b)
	{
		const int scale5 = 256/32;
		const int scale6 = 256/64;
		return _RGB16BIT565( r / scale5, g / scale6, b / scale5 );
	}
};

struct CRGBTo16BIT555 : ClrConverter
{
	DWORD Convert(int r, int g, int b)
	{
		const int scale5 = 256/32;
		return _RGB16BIT565( r / scale5, g / scale5, b / scale5 );
	}
};

struct CDDSURFACEDESC:DDSURFACEDESC
{
	CDDSURFACEDESC(DWORD Flags, DWORD Caps, int Width = 0, int Height = 0)
	{
		memset(this, 0,sizeof(CDDSURFACEDESC));
		this->dwSize = sizeof(DDSURFACEDESC);	
		this->dwFlags = Flags; 
		this->ddsCaps.dwCaps = Caps;
		if(Width > 0 && Height > 0)
		{
			this->dwHeight = Height; 
			this->dwWidth = Width; 
		}
	}
};

struct CDDPIXELFORMAT:DDPIXELFORMAT
{
	DWORD bitformat_;
	CDDPIXELFORMAT(IDirectDrawSurface* Surface)
		:bitformat_(0)
	{
		memset(this, 0,sizeof(DDPIXELFORMAT)); 
		this->dwSize = sizeof(DDPIXELFORMAT);
		if(SUCCEEDED(Surface->GetPixelFormat(this)))
		{
			bitformat_ = this->dwRGBBitCount; 
		}
	}

	bool IsValid()
	{
		return bitformat_ != 0?true:false;
	}

	DWORD GetBitCount() const 
	{
		return bitformat_;
	}

	bool InRGBMode() const 
	{
		return ( (this->dwFlags & DDPF_RGB) && !(this->dwFlags & DDPF_PALETTEINDEXED8)  ) ? true: false;
	}

	bool InPaletteMode() const 
	{
		return ((this->dwFlags & DDPF_PALETTEINDEXED8) || (this->dwFlags & DDPF_PALETTEINDEXEDTO8))? true: false;
	}
};


struct TDoBeginPaint
{
    PAINTSTRUCT m_ps;

	HDC BeginPaint(HWND h)
	{
		return ::BeginPaint(h, &m_ps);
	}

	BOOL EndPaint(HWND h)
	{
		return ::EndPaint(h, &m_ps);
	}
};

struct TDontBeginPaint
{
    PAINTSTRUCT m_ps;

	HDC hdc_;

	TDontBeginPaint()
		:hdc_(0)
	{	}

	HDC BeginPaint(HWND h)
	{ return hdc_;	}

	BOOL EndPaint(HWND h)
	{ return false;	}
};

template <class TBEGINPAINT = TDoBeginPaint>
class CDXSurfaceMgr : public TBEGINPAINT
{
	CComPtr<IDirectDraw> directdraw_;
	CComPtr<IDirectDrawSurface> primarysurface_, secondarysurface_;
	CComPtr<IDirectDrawClipper> clipper_;

	HWND window_;

	std::auto_ptr<ClrConverter> rgbconverter_;

	HDC current_hdc_;
	XRect current_rect_;

	IDirectDrawSurface* CreateSecondarySurface(const int Width, const int Height)
	{
		if(NULL!=primarysurface_.p)
		{
			IDirectDrawSurface* ss =NULL;
			CDDSURFACEDESC dds(DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH, DDSCAPS_OFFSCREENPLAIN, Width, Height);
			HRESULT hr = directdraw_->CreateSurface(&dds,&ss, NULL);
			if(SUCCEEDED(hr))
				return ss;
		}
		return NULL;
	}

	void fillclr(IDirectDrawSurface* surface, COLORREF BackFillColor)
	{
		DDBLTFX bltfx; memset(&bltfx, 0,sizeof(DDBLTFX)); bltfx.dwSize = sizeof(DDBLTFX);
		// convert the rgb given into what ever pixel format we may have
		bltfx.dwFillColor = rgbconverter_->Convert(GetRValue(BackFillColor),
												   GetGValue(BackFillColor),
												   GetBValue(BackFillColor));
		HRESULT hr = surface->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT,&bltfx);
	}

	BOOL ClientToScreen(LPRECT lpRect) const
	{
		if(!::ClientToScreen(window_, (LPPOINT)lpRect))
			return FALSE;
		return ::ClientToScreen(window_, ((LPPOINT)lpRect)+1);
	}

	bool SetPixel(int x, int y, UCHAR* pb, DDSURFACEDESC& ddsd, int Clr)
	{
		*((USHORT *)(pb + x*2 + y*ddsd.lPitch)) = Clr;
		return true;
	}

	IDirectDrawPalette* Build256Palette()
	{
		IDirectDrawPalette* ddp = 0;
		PALETTEENTRY pal[256];
		
		// setup static windows entries
		for(int i =0; i<10 ;i++)
		{
			//the first 10
			pal[i].peFlags = PC_EXPLICIT;
			pal[i].peRed = i;
			pal[i].peGreen = pal[i].peBlue = 0;

			// the last ten
			pal[i+246].peFlags = PC_EXPLICIT;
			pal[i+246].peRed = i+246;
			pal[i+246].peGreen = pal[i].peBlue = 0;
		}

		// default everything else	
		for(i=10; i<246 ;i++)
		{
			pal[i].peFlags = PC_NOCOLLAPSE;
			pal[i].peRed = pal[i].peGreen = pal[i].peBlue = 27;
		}

		HRESULT hr =directdraw_->CreatePalette(DDPCAPS_8BIT, pal, &ddp, NULL);
		return ddp;
	}

public:

	bool IsValid()
	{
		return (primarysurface_.p != NULL) ? true:false;
	}

	bool Initialise(HWND Window)
	{
		if(NULL==Window) return false;

		window_ = Window;
		
		// create DirectDrawObject
		HRESULT hr = ::DirectDrawCreate(NULL, &directdraw_.p,NULL);
		if (FAILED(hr)) return false;
		hr = directdraw_->SetCooperativeLevel(window_,DDSCL_NORMAL);
		if (FAILED(hr)) return false;
		// create primary surface
		CDDSURFACEDESC dds(DDSD_CAPS, DDSCAPS_PRIMARYSURFACE);
		hr = directdraw_->CreateSurface(&dds,&primarysurface_.p, NULL);
		if (FAILED(hr)) return false;
		// attach clipper to window all blits will 
		// then be clipped to the primary surface
		hr = directdraw_->CreateClipper(0, &clipper_.p, NULL);
		if (FAILED(hr)) return false;
		hr = clipper_->SetHWnd(0, window_);
		if (FAILED(hr)) return false;
		// attach clipper to primary surface
		hr = primarysurface_->SetClipper(clipper_);
		if (FAILED(hr)) return false;

		// work out the pixel format for colour conversions
		CDDPIXELFORMAT pf(primarysurface_.p);
		if(pf.IsValid())
		{
			if(pf.InRGBMode())
			{
				DWORD tst = pf.GetBitCount();
				if(15 == tst) // 16 bit 555
				{
					std::auto_ptr<ClrConverter> rgbconverter(new CRGBTo16BIT555);
					rgbconverter_ = rgbconverter;
				}
				if(16 == tst) // 16 bit 565
				{
					std::auto_ptr<ClrConverter> rgbconverter(new CRGBTo16BIT565);
					rgbconverter_ = rgbconverter;
				}
				if(24 == tst) // 24 bit
				{
					std::auto_ptr<ClrConverter> rgbconverter(new CRGB24BIT);
					rgbconverter_ = rgbconverter;
				}
				if(32 == tst) // 32 bit
				{
					std::auto_ptr<ClrConverter> rgbconverter(new CRGB32BIT);
					rgbconverter_ = rgbconverter;
				}
			}
			else if(pf.InPaletteMode())
			{
				std::auto_ptr<ClrConverter> rgbconverter(new CRGB8BIT(primarysurface_));
				rgbconverter_ = rgbconverter;
			}
			else
			{
				ATLTRACE("u r living on borrowed time - please retire now\n");
			}
		}

		return true;
	}

	HDC& BeginPaint(COLORREF BackFillColor = 0)
	{
		current_hdc_ = NULL_HDC;
		if(!IsValid()) return current_hdc_;

		TBEGINPAINT::BeginPaint(window_);

		XRect client; ::GetClientRect(window_, &client); ClientToScreen(&client);
 
		// only create new secondary surface if the window has changed size
		if(current_rect_!=client) 
		{
			secondarysurface_ = CreateSecondarySurface(client.Width(), client.Height());
			if(NULL==secondarysurface_.p) return current_hdc_;
			current_rect_ = client;
		}
		// fill the secondary surface 
		fillclr(secondarysurface_, BackFillColor);
		
		// GetDC will _lock_ the surface for us
		secondarysurface_->GetDC(&current_hdc_);
		return current_hdc_;
	}

	bool EndPaint()
	{
		if(NULL_HDC!=current_hdc_)
		{
			// ReleaseDC will unlock the surface
			secondarysurface_->ReleaseDC(current_hdc_);

			// copy all of the secondary surface onto the primary
			HRESULT hr = primarysurface_->Blt(&current_rect_, // destination
						  secondarysurface_, NULL,  // Source surface, Source rectangle NULL = entire surface
						  DDBLT_WAIT, NULL);
			if(SUCCEEDED(hr))
			{
				TBEGINPAINT::EndPaint(window_);
				return true;
			}
		}
		return false;
	}
};

typedef CDXSurfaceMgr<TDoBeginPaint> CDXSurfaceManager;
// use this one if you call your BeginPaint/EndPaint or use CDC
typedef CDXSurfaceMgr<TDontBeginPaint> CDXSurfaceManager_NBP;

static BOOL DXErrorString(HRESULT hResult, LPTSTR lpszErrorBuff, DWORD cchError)
{
	DWORD  cLen;
	LPTSTR lpszError;
	TCHAR  szMsg[1024];

	// Check parameters
	if (!lpszErrorBuff || !cchError)
	{
		// Error, invalid parameters
		return FALSE;
	}

	switch (hResult)
	{
	case DD_OK:
		// The request completed successfully.
		lpszError = TEXT("DD_OK");
		break;

	case DDERR_ALREADYINITIALIZED:
		// The object has already been initialized.
		lpszError = TEXT("DDERR_ALREADYINITIALIZED");
		break;

	case DDERR_BLTFASTCANTCLIP:
		// A DirectDrawClipper object is attached to a source surface 
		// that has passed into a call to the IDirectDrawSurface2::BltFast method. 
		lpszError = TEXT("DDERR_BLTFASTCANTCLIP");
		break;

	case DDERR_CANNOTATTACHSURFACE:
		// A surface cannot be attached to another requested surface. 
		lpszError = TEXT("DDERR_CANNOTATTACHSURFACE");
		break;

	case DDERR_CANNOTDETACHSURFACE:
		// A surface cannot be detached from another requested surface. 
		lpszError = TEXT("DDERR_CANNOTDETACHSURFACE");
		break;

	case DDERR_CANTCREATEDC:
		// Windows cannot create any more device contexts (DCs). 
		lpszError = TEXT("DDERR_CANTCREATEDC");
		break;

	case DDERR_CANTDUPLICATE:
		// Primary and 3D surfaces, or surfaces that are 
		// implicitly created, cannot be duplicated. 
		lpszError = TEXT("DDERR_CANTDUPLICATE");
		break;

	case DDERR_CANTLOCKSURFACE:
		// Access to this surface is refused because an 
		// attempt was made to lock the primary surface without DCI support. 
		lpszError = TEXT("DDERR_CANTLOCKSURFACE"); 
		break;

	case DDERR_CANTPAGELOCK:
		// An attempt to page lock a surface failed. 
		// Page lock will not work on a display-memory 
		// surface or an emulated primary surface.
		lpszError = TEXT("DDERR_CANTPAGELOCK"); 
		break;

	case DDERR_CANTPAGEUNLOCK:
		// An attempt to page unlock a surface failed. 
		// Page unlock will not work on a display-memory 
		// surface or an emulated primary surface. 
		lpszError = TEXT("DDERR_CANTPAGEUNLOCK");
		break;

	case DDERR_CLIPPERISUSINGHWND:
		// An attempt was made to set a clip list for a DirectDrawClipper 
		// object that is already monitoring a window handle. 
		lpszError = TEXT("DDERR_CLIPPERISUSINGHWND");
		break;

	case DDERR_COLORKEYNOTSET:
		// No source color key is specified for this operation
		lpszError = TEXT("DDERR_COLORKEYNOTSET");
		break;

	case DDERR_CURRENTLYNOTAVAIL:
		// No support is currently available. 
		lpszError = TEXT("DDERR_CURRENTLYNOTAVAIL");
		break;

	case DDERR_DCALREADYCREATED:
		// A device context (DC) has already been returned for this surface. 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -