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

📄 gscreen.cpp

📁 用FREE BASIC做的演示程序
💻 CPP
字号:
#include"GScreen.h"
#include<windows.h>

__int64 GetCPUFrequency()
{
	__int64 qwFreq;
	::QueryPerformanceFrequency((LARGE_INTEGER*)&qwFreq);
	return qwFreq;
}
GScreen::GScreen()
{
	m_pDD=NULL;
	m_pDSPrimary=NULL;
	m_pDSBack=NULL;

	m_pBuffer=NULL;
	m_dwFPS=0;
	m_dwBufSize=0;
	m_bDefaultPal=true;
	m_bUseVideoMemory=true;
	for(int i=0;i<256;i++)
	{
		m_pPal[i]=i|(i<<8);
	}
}
GScreen::~GScreen()
{
	DestroySurface();
	if(m_pDD)
	{
		m_pDD->Release();
		m_pDD=NULL;
	}
	if(m_pBuffer)
	{
		delete [] m_pBuffer;
		m_pBuffer=NULL;
	}
}
void GScreen::DestroySurface()
{
	if(m_pDSBack)
	{
		m_pDSBack->Release();
		m_pDSBack=NULL;
	}
	if(m_pDSPrimary)
	{
		m_pDSPrimary->Release();
		m_pDSPrimary=NULL;
	}
}

HRESULT GScreen::RestoreSurface()
{
	HRESULT hr;
	if(m_pDSPrimary)
	{
		hr=m_pDSPrimary->Restore();
	}
	if(m_pDSBack)
	{
		hr=m_pDSBack->Restore();
	}
	return hr;
}

void GScreen::Present()
{
	HRESULT hr;
	static __int64 ddwOldTime=0,ddwNewTime;
	static int frames=0;
	static __int64 s_ddFreq=GetCPUFrequency();
	QueryPerformanceCounter((LARGE_INTEGER*)&ddwNewTime);
	if(ddwNewTime-ddwOldTime<s_ddFreq)
	{
		frames++;
	}
	else
	{
		ddwOldTime=ddwNewTime;
		m_dwFPS=frames;
		frames=0;
	}

	DDSURFACEDESC2 ddsd;
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	hr=m_pDSBack->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
	while(DD_OK!=hr)
	{
		if(DDERR_SURFACELOST==hr)
			RestoreSurface();
		else
			return;
		hr=m_pDSBack->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
	}
	unsigned char*pSourBuf=(unsigned char*)m_pBuffer;
	
	if(m_bDefaultPal)
	{
		//由于初学mmx,还不会作优化~代码见笑了~
		unsigned long dwResPitch=ddsd.lPitch-(m_nWidth<<1);	
		unsigned char*pBuf=(unsigned char*)ddsd.lpSurface;
		unsigned long dwHeight=m_nHeight;
		unsigned long loopTime=m_nWidth>>5;		//一次处理32个索引点
		{
			_asm
			{
				mov esi,pSourBuf;
				mov edi,pBuf;
				mov edx,dwHeight;
rowLoop:
				cmp edx,0;
				je end;
				mov ecx,loopTime;
mmxdraw:
				movq mm0,[esi];						//8个索引点
				movq mm2,[esi+8];					//后8个索引点
				movq mm4,[esi+16];
				movq mm6,[esi+24];
				movq mm1,mm0;
				movq mm3,mm2;
				movq mm5,mm4;
				movq mm7,mm6;
				punpcklbw mm0,mm0;					//0-3个索引的值
				punpckhbw mm1,mm1;					//4-7
				punpcklbw mm2,mm2;					//8-11
				punpckhbw mm3,mm3;					//12-15
				punpcklbw mm4,mm4;
				punpckhbw mm5,mm5;
				punpcklbw mm6,mm6;
				punpckhbw mm7,mm7;

				movq [edi],mm0;
				movq [edi+8],mm1;
				movq [edi+16],mm2;
				movq [edi+24],mm3;
				movq [edi+32],mm4;
				movq [edi+40],mm5;
				movq [edi+48],mm6;
				movq [edi+56],mm7;

				add esi,32;
				add edi,64;
				loop mmxdraw;
				dec edx;
				add edi,dwResPitch;
				jmp rowLoop;
end:
				emms;
			}
		}
	}
	else
	{
		unsigned long dwResPitch=(ddsd.lPitch>>1)-m_nWidth;	
		unsigned short*pBuf=(unsigned short*)ddsd.lpSurface;
		for(register int i=0;i<m_nHeight;i++)
		{
			for(register int j=0;j<m_nWidth;j++)
			{
				*pBuf=m_pPal[*pSourBuf];
				pBuf++;
				pSourBuf++;
			}
			pBuf+=dwResPitch;
		}
	}
	m_pDSBack->Unlock(NULL);
	
	if(m_bFullScreen)
	{
#ifdef NOFLIP
		hr=m_pDSPrimary->Blt(NULL,m_pDSBack,NULL,DDBLT_WAIT,NULL);	
		while(DD_OK!=hr)
		{
			if(DDERR_SURFACELOST==hr)
				RestoreSurface();
			else
				return;
			hr=m_pDSPrimary->Blt(NULL,m_pDSBack,NULL,DDBLT_WAIT,NULL);	
		}
#else
		hr=m_pDSPrimary->Flip(NULL,DDFLIP_WAIT);
		while(DD_OK!=hr)
		{
			if(DDERR_SURFACELOST==hr)
				RestoreSurface();
			else
				return;
			hr=m_pDSPrimary->Flip(NULL,DDFLIP_WAIT);	
		}
#endif
	}
	else
	{	
		RECT rtWindow;
		::GetClientRect(m_hWnd,&rtWindow);
		::ClientToScreen(m_hWnd,(POINT*)&rtWindow);
		::ClientToScreen(m_hWnd,(POINT*)&rtWindow+1);

		
		hr=m_pDSPrimary->Blt(&rtWindow,m_pDSBack,NULL,DDBLT_WAIT,NULL);
  
		while(DD_OK!=hr)
		{
			if(DDERR_SURFACELOST==hr)
				RestoreSurface();
			else
				return;
			hr=m_pDSPrimary->Blt(&rtWindow,m_pDSBack,NULL,DDBLT_WAIT,NULL);	
		}
	}
}
bool GScreen::CreateDirectDrawObject()
{
	if(m_pDD)
		return true;
	HDC hdc=GetDC(GetDesktopWindow());
	m_nDesktopBpp=GetDeviceCaps(hdc,PLANES)*GetDeviceCaps(hdc,BITSPIXEL);
    ReleaseDC(GetDesktopWindow(),hdc);
	HRESULT hr=DirectDrawCreateEx(NULL,(void**)&m_pDD,IID_IDirectDraw7,NULL);
	if(FAILED(hr))
	{
		return false;
	}
	return true;
}

bool GScreen::CreateFullScreen(HWND hWnd,int width,int height)
{
	m_nWidth=width;
	m_nHeight=height;
	m_nBpp=16;
	m_hWnd=hWnd;
	if(!CreateDirectDrawObject())
		return false;
	DestroySurface();
	
	HRESULT hr;
	hr=m_pDD->SetCooperativeLevel(m_hWnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT);
	if(FAILED(hr))
	{
		return false;
	}
	hr=m_pDD->SetDisplayMode(m_nWidth,m_nHeight,m_nBpp,0,0);
	if(FAILED(hr))
	{
		return false;
	}
#ifdef NOFLIP
	DDSURFACEDESC2 ddsd;
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS;
	ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
	
	hr=m_pDD->CreateSurface(&ddsd,&m_pDSPrimary,NULL);
	if(FAILED(hr))
	{
		return false;
	}
	ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
	ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
	
	ddsd.dwWidth=m_nWidth;
	ddsd.dwHeight=m_nHeight;
	
	hr=m_pDD->CreateSurface(&ddsd,&m_pDSBack,NULL);
	if(FAILED(hr))
	{
		return false;
	}
#else
	DDSURFACEDESC2 ddsd;
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
	ddsd.dwBackBufferCount=1;
	
	if(m_bUseVideoMemory)
		ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY;
	else
		ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_SYSTEMMEMORY;
	
	hr=m_pDD->CreateSurface(&ddsd,&m_pDSPrimary,NULL);
	if(FAILED(hr))
	{
	    return false;
	}	
	ZeroMemory(&ddsd.ddsCaps,sizeof(ddsd.ddsCaps));
	ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER;
	hr=m_pDSPrimary->GetAttachedSurface(&ddsd.ddsCaps,&m_pDSBack);
	if(FAILED(hr))
	{
		return false;
	}
#endif	
	if(NULL==m_pBuffer)
	{
		m_pBuffer=new unsigned char[m_nWidth*m_nHeight];
		if(!m_pBuffer)
		{
			MessageBox(m_hWnd,"Out of memory!","Error",MB_OK);
			return false;
		}
	}
	m_bFullScreen=true;
	m_dwBufSize=m_nWidth*m_nHeight;
	return true;
}

bool GScreen::CreateWindowed(HWND hWnd,int width,int height)
{
	m_nWidth=width;
	m_nHeight=height;
	m_nBpp=16;
	m_hWnd=hWnd;
	if(!CreateDirectDrawObject())
		return false;
	if(m_nBpp!=m_nDesktopBpp)
	{
		MessageBox(m_hWnd,"您的桌面不是16位色的,不能在窗口模式下运行","ERROR",MB_OK);
		return false;
	}
	m_pDD->RestoreDisplayMode();
	DestroySurface();
	
	HRESULT hr;
	hr=m_pDD->SetCooperativeLevel(m_hWnd,DDSCL_NORMAL);
	if(FAILED(hr))
	{
		return false;
	}
	unsigned long dwStyle=GetWindowLong(m_hWnd,GWL_STYLE);
    dwStyle &= ~WS_POPUP;
    dwStyle|=WS_SYSMENU|WS_MINIMIZEBOX;
    SetWindowLong(m_hWnd,GWL_STYLE,dwStyle );


    SetWindowPos(m_hWnd,NULL,0,0,m_nWidth,m_nHeight,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
    SetWindowPos(m_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
	
	MoveWindow(m_hWnd,(GetSystemMetrics(SM_CXSCREEN)-m_nWidth)/2,
						(GetSystemMetrics(SM_CYSCREEN)-m_nHeight)/2,
						m_nWidth,
						m_nHeight,
						true);
	
	DDSURFACEDESC2 ddsd;
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS;
	ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;

	hr=m_pDD->CreateSurface(&ddsd,&m_pDSPrimary,NULL);
	if(FAILED(hr))
	{
		return false;
	}
	ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
	ddsd.ddsCaps.dwCaps=DDSCAPS_3DDEVICE|DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;

	ddsd.dwWidth=m_nWidth;
	ddsd.dwHeight=m_nHeight;

	hr=m_pDD->CreateSurface(&ddsd,&m_pDSBack,NULL);
	if(FAILED(hr))
	{
		ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
		hr=m_pDD->CreateSurface(&ddsd,&m_pDSBack,NULL);
		if(FAILED(hr))
		{
			return false;
		}
	}
	
	LPDIRECTDRAWCLIPPER pClipper;

	hr=m_pDD->CreateClipper(0,&pClipper,NULL);
	if(FAILED(hr))
	{
  		return false;
	}
	hr=pClipper->SetHWnd(0,m_hWnd);
    if(FAILED(hr))
    {
        pClipper->Release();
  		return false;
    }
	hr=m_pDSPrimary->SetClipper(pClipper);
    if(FAILED(hr))
    {
        pClipper->Release();
  		return false;
    }
    pClipper->Release();

	if(NULL==m_pBuffer)
	{
		m_pBuffer=new unsigned char[m_nWidth*m_nHeight];
		if(!m_pBuffer)
		{
			MessageBox(m_hWnd,"Out of memory!","Error",MB_OK);
			return false;
		}
	}
	m_bFullScreen=false;
	m_dwBufSize=m_nWidth*m_nHeight;
	return true;
}
bool GScreen::SwitchDisplayMode()
{
	if(m_bFullScreen)
	{
		return CreateWindowed(m_hWnd,m_nWidth,m_nHeight);
	}
	else
	{
		return CreateFullScreen(m_hWnd,m_nWidth,m_nHeight);
	}
}

void GScreen::ClearPrimary()
{
	DDBLTFX ddbltfx;
	ZeroMemory(&ddbltfx,sizeof(ddbltfx));
	ddbltfx.dwSize=sizeof(ddbltfx);
	ddbltfx.dwFillColor=0;
	m_pDSPrimary->Blt(NULL,NULL,NULL,DDBLT_COLORFILL,&ddbltfx);
}
void GScreen::TextOutDC(int x,int y,unsigned long dwColor,unsigned long dwLineChar,char*str,...)
{
	POINT pt={x,y};

	::ClientToScreen(m_hWnd,&pt);
	x=pt.x;
	y=pt.y;
	
	char txt[1024];
	va_list vl;
	va_start(vl,str);
	wvsprintf(txt,str,vl);
	va_end(vl);
	
	char strtmp[256];
	
	HDC hdc;
	m_pDSPrimary->GetDC(&hdc);
	::SetBkMode(hdc,TRANSPARENT);
	::SetTextColor(hdc,dwColor);
	
	TEXTMETRIC tm;
	::GetTextMetrics(hdc,&tm);
	int nTextIndex;
	int i=0;
	while(txt[i]!='\0')
	{
		memset(strtmp,0,256);
		nTextIndex=0;
		
		while(txt[i]!='\0' && nTextIndex< (int)dwLineChar)
		{
			if((char)txt[i]<0)													//如果是汉字
			{
				strtmp[nTextIndex++]=txt[i++];
				strtmp[nTextIndex++]=txt[i++];
			}
			else
			{
				strtmp[nTextIndex++]=txt[i++];
			}
		}
		::TextOut(hdc,x,y,strtmp,strlen(strtmp));
		y+=tm.tmHeight;
	}
	m_pDSPrimary->ReleaseDC(hdc);
}

⌨️ 快捷键说明

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