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

📄 directmanage.cpp

📁 应用程序向导已为您创建了这个 SH 应用程序。此应用程序不仅演示 Microsoft 基础类的基本使用方法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "StdAfx.h"
#include "SH.h"
#include "DirectManage.h"

CDirectManage::CDirectManage(void)
{
	m_lpDD = NULL;
	m_lpDDSPrimary = NULL;
	m_lpDDSBack = NULL;
}

CDirectManage::~CDirectManage(void)
{
	FreeDDraw();
}
void CDirectManage::SetDrawhWnd(HWND hWnd)
{
	m_hWnd = hWnd;
}
//初始化DirectDraw环境
BOOL CDirectManage::InitDDraw(void)
{
	DWORD			 dwFlags;
	DDSURFACEDESC	 ddsd;
	HRESULT          ddrval;

	//创建DirectDraw对象
	ddrval = DirectDrawCreate(NULL, &m_lpDD, NULL);
	if (FAILED( ddrval ) )
		return FALSE;
	
	if(theApp.m_iWindowMode == 1)
	{
		//设置协作级别为窗口模式
		dwFlags = DDSCL_NORMAL;
		m_lpDD->SetCooperativeLevel(m_hWnd, dwFlags);
		
		// 创建主页面
	    ddsd.dwSize = sizeof( ddsd );
		ddsd.dwFlags = DDSD_CAPS;
	    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
		ddrval = m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL );
		if( ddrval != DD_OK )
		{
			return FALSE;
		}

		//生成剪裁器
		CreateClipper();
		
		//生成背景页面
		CreateBitmap(m_lpDDSBack, theApp.m_iScreenWidth, theApp.m_iScreenHeight);
		
		// 测试像素格式是555还是565
		DDPIXELFORMAT DDPixelFormat;
		ZeroMemory(&DDPixelFormat, sizeof(DDPixelFormat));
		DDPixelFormat.dwSize = sizeof(DDPixelFormat);
		if (m_lpDDSPrimary->GetPixelFormat(&DDPixelFormat) != DD_OK)
			return 1;

		m_RMask=(WORD)DDPixelFormat.dwRBitMask;
		m_GMask=(WORD)DDPixelFormat.dwGBitMask;
		m_BMask=(WORD)DDPixelFormat.dwBBitMask;
		//扩展为32位 00000gggggg00000rrrrr000000bbbbb
		//下面的部分,看上面的注释好了,我就不再写了
		m_rgbMask=((DWORD)m_GMask<<16)|m_RMask|m_BMask;	
		if (m_GMask == 0x07e0 ) m_bIs555 = 0;
		if( m_bIs555 )
		{
			m_ColorKey16=0x00007c1f;	//00000|11111|00000|11111b    (255,0,255)
			m_RMove=10;					//R要向右10位
			m_GMove=5;					//G要向右5位
		}
		else
		{
			m_ColorKey16=0x0000f81f;
			m_RMove=11;					//R要向右11位
			m_GMove=6;					//注意这儿了,为什么是6呢?因为在进行灰度运算的时候,
		}								//一个6位和两个五位运算会超出5位,所以……呵呵,soft
										//在这儿一句注释都没有,把我可想苦了:)这下改明白了吧
	}

	return TRUE;
}
//创建一个GDI裁减器
BOOL CDirectManage::CreateClipper()
{
	LPDIRECTDRAWCLIPPER lpClipper;
	HRESULT ddrval;
	//创建一个剪裁器对象
	ddrval = m_lpDD->CreateClipper(0, &lpClipper, NULL);
	if ( ddrval != DD_OK)
	{
	    return FALSE;
	}
	//设置窗口句柄
	ddrval = lpClipper->SetHWnd(0, m_hWnd);
	if ( ddrval != DD_OK)
	{
		return FALSE;
	}
	//关联主页面,注意这个函数会增加引用计数
	ddrval = m_lpDDSPrimary->SetClipper(lpClipper);
	if ( ddrval != DD_OK)
	{
		return FALSE;
	}
	//理所当然要减少引用计数
	_RELEASE( lpClipper );
	return TRUE;
}
//*********************************
//功能:创建页面
//参数:要创建的页面指针,宽度,高度,文件名,内存标志
BOOL CDirectManage::CreateBitmap(LPDIRECTDRAWSURFACE &lpTemp,int x,int y,LPCTSTR BitmapFile, DWORD MemoryFlag )
{
	DDSURFACEDESC	 ddsd;
	HRESULT          ddrval;

	//获得位图文件的尺寸
	if( x == 0 && y == 0 )
		if( LoadBitmapFileInfo(m_hWnd, BitmapFile, x, y)==FALSE )
			return FALSE;
	//创建一个页面
	ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | MemoryFlag;
	ddsd.dwWidth = x;
	ddsd.dwHeight = y;
	ddrval = m_lpDD->CreateSurface( &ddsd, &lpTemp, NULL );
	if( ddrval != DD_OK )
	{
		return initFail(BitmapFile);
	}
	
	if( BitmapFile!=NULL )
		DDReLoadBitmap(lpTemp,BitmapFile);
	
	return TRUE;
}
//功能:获得位图文件的尺寸大小
//参数:窗口句柄,位图文件名,返回位图宽度,返回位图高度(引用参数)
BOOL CDirectManage::LoadBitmapFileInfo(HWND hwnd, LPCTSTR filename, int &dx, int &dy)
{
	char cFileName[MAX_PATH];
	ZeroMemory(cFileName,sizeof(cFileName));
	theApp.m_CPublicFun.WCharToMByte(filename,cFileName);

	FILE *fp;
	if( (fp=fopen(cFileName, "rb"))==NULL )
	{
		CString strErr = L"";
		strErr.Format(L"Error open BMP file:%s",filename);
		AfxMessageBox(strErr);
		return FALSE;
	}
	//读入文件头
	BITMAPFILEHEADER bmpFileHeader;		
	fread(&bmpFileHeader, sizeof(bmpFileHeader), 1, fp);
	//检查BM标志
	char *ptr=(char*)&bmpFileHeader.bfType;
	if(*ptr!='B' || *++ptr!='M')
	{
		AfxMessageBox(L"Invalid bitmap file!");
		return FALSE;
	}
	//信息头
	BITMAPINFOHEADER bmpInfoHeader;
	fread(&bmpInfoHeader, sizeof(bmpInfoHeader), 1, fp);
	fclose(fp);
	//宽度,高度
	dx=bmpInfoHeader.biWidth;
	dy=bmpInfoHeader.biHeight;
	return TRUE;
}
//初始化失败的处理函数
BOOL CDirectManage::initFail(LPCTSTR str)
{
    FreeDDraw();
	CString strErr = L"";
	strErr.Format(L"Init Fail:%s",str);
    AfxMessageBox( str );
    return FALSE;

} 
//释放系统的DirectDraw对象
HRESULT CDirectManage::FreeDDraw()
{
	if (m_lpDD)
	{
		//恢复协作级
		m_lpDD->SetCooperativeLevel(m_hWnd,DDSCL_NORMAL);
		m_lpDD->Release();
		m_lpDD = NULL;
	}
	return DD_OK;
}
//显示一个bmp到一个页面
HRESULT CDirectManage::DDReLoadBitmap(IDirectDrawSurface *pdds, LPCTSTR szBitmap)
{
    HBITMAP             hbm;
    HRESULT             hr;
	//当一个资源来加载
    hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, 0, 0, 
					LR_CREATEDIBSECTION);
	//失败,当一个文件加载
    if (hbm == NULL)
        hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0, 
				LR_LOADFROMFILE|LR_CREATEDIBSECTION);
	//仍然失败
    if (hbm == NULL)
    {
		CString strDebug = L"";
		strDebug.Format(L"handle is null [%s]\n", szBitmap);
		OutputDebugString(strDebug.GetBuffer(0));
        return E_FAIL;
    }
	//把图片显示到页面
    hr = DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
    if (hr != DD_OK)
    {
        OutputDebugString(L"ddcopybitmap failed\n");
    }


    DeleteObject(hbm);
    return hr;
}
//在一个页面上显示一个bmp图片
HRESULT CDirectManage::DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm, int x, int y, int dx, int dy)
{
    HDC                 hdcImage;
    HDC                 hdc;
    BITMAP              bm;
    DDSURFACEDESC       ddsd;
    HRESULT             hr;

    if (hbm == NULL || pdds == NULL)
        return E_FAIL;

    pdds->Restore();
	//创建一个和当前屏幕相关的 memory device context 
    hdcImage = CreateCompatibleDC(NULL);
    if (!hdcImage)
        OutputDebugString(L"createcompatible dc failed\n");
    SelectObject(hdcImage, hbm);
	//得到bmp的大小
    GetObject(hbm, sizeof(bm), &bm);    
    dx = dx == 0 ? bm.bmWidth  : dx;    // 只要传进来的参数不是0,就使用传进来的参数
    dy = dy == 0 ? bm.bmHeight : dy;
	//得到页面的大小
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
    pdds->GetSurfaceDesc(&ddsd);
	
    if ((hr = pdds->GetDC(&hdc)) == DD_OK)
    {
		//缩放blt
        StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y, dx, dy, SRCCOPY);
        pdds->ReleaseDC(hdc);
    }

    DeleteDC(hdcImage);

    return hr;
}
//***********************************************************
//功能:位图拷贝
//参数:目标表面,目标x,目标y,原表面,拷贝范围,是否带透明色
void CDirectManage::Blt(LPDIRECTDRAWSURFACE SS,int x,int y,
		 LPDIRECTDRAWSURFACE DS,RECT rcRect,DWORD Flag)
{
	HRESULT				ddrval;
	//边界检查
	if( x<0 ) 
	{  
		rcRect.left = rcRect.left - x; 
		x=0; 
	}
	else 
		if( x+ rcRect.right - rcRect.left > theApp.m_iScreenWidth ) 
		{ 
			rcRect.right = rcRect.left + theApp.m_iScreenWidth - x; 
		}

	if( y<0 ) 
	{  
		rcRect.top  = rcRect.top - y; 
		y=0; 
	}
	else 
		if( y+ rcRect.bottom - rcRect.top > theApp.m_iScreenHeight ) 
		{ 
			rcRect.bottom = rcRect.top + theApp.m_iScreenHeight - y; 
		}
	
	while( 1 )
	{
		ddrval = SS->BltFast( x, y, DS, &rcRect, Flag);

		if(	ddrval == DD_OK )
		{
			return;
		}
		
		if( ddrval == DDERR_SURFACELOST )
		{
		    ddrval = restoreAll();
		    if( ddrval != DD_OK )
		    {
				return;
		    }
		}
		
		if( ddrval != DDERR_WASSTILLDRAWING )
		{
		    return;
		}
    }
}
//********************
//功能:恢复系统页面
HRESULT CDirectManage::restoreAll( void )
{
    HRESULT	ddrval;
	
	if( m_lpDDSPrimary )
		ddrval = m_lpDDSPrimary->Restore();

	if( m_lpDDSBack )
		ddrval = m_lpDDSBack->Restore();
    return ddrval;
}
//************************************
//开页面缓冲区,然后直接在缓冲区中操作
BOOL CDirectManage::BeginDraw(LPDIRECTDRAWSURFACE lpSur)

⌨️ 快捷键说明

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