📄 directmanage.cpp
字号:
#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 + -