郁闷。一个年就几天过完了,好像什么感觉都没有。
热闹的时间不够长,很不爽啊。
明天是2.14情人节。嗯...不关我事,该做什么做什么。明晚又是一个人在家,找点什么娱乐?
没有吧。来来去去都是那几样了...war3, coding, film, tv, music...etc.
看着框架逐渐发展起来感觉非常的爽啊~~
这次无论如何总应该做出点什么来了吧。
代码帖上来先。
如果这个Blog有关键字自动着色就好了。。。
#include "StdAfx.h"
#include "./graph.h"
CGraph::CGraph(void)
: m_WinHeight(0)
, m_WinWidth(0)
, m_ColorDepth(0)
{
}
CGraph::~CGraph(void)
{
}
// 初始化DirectDraw
bool CGraph::InitDDraw(int nWidth, int nHeight, int nColorDepth,bool bFullScreen)
{
if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK )
return false;
// Set CooperativeLevel
DWORD dwFlags;
if (bFullScreen)
{
dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
this->bIsWindowMode = false;
}else{
dwFlags = DDSCL_NORMAL;
this->bIsWindowMode = true;
}
if (lpDD->SetCooperativeLevel(hWnd,dwFlags) != DD_OK)
return false;
//Set DisplayMode
m_WinHeight = nHeight;
m_WinWidth = nWidth;
m_ColorDepth = nColorDepth;
if(bFullScreen)
if(lpDD->SetDisplayMode(nWidth,nHeight,nColorDepth) != DD_OK)
return false;
//Set Window Style
SetWindowStyle();
//Init Primary and back Buffers
DDSURFACEDESC ddsd;
HRESULT ddrval;
if(bFullScreen)
{
//Fullscreen mode
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
//Create Primary surface.
ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
if( ddrval != DD_OK )
return false;
//Create BackBuffer surface
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
if ( lpDDSPrimary->GetAttachedSurface (&ddsd.ddsCaps, &lpDDSBack) != DD_OK )
return false;
}else{
//Window mode
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
//Create Primary surface.
if( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) != DD_OK )
{
return false;
}
//Create BackBuffer surface
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = m_WinWidth;
ddsd.dwHeight = m_WinHeight;
if( lpDD->CreateSurface( &ddsd, &lpDDSBack, NULL ) != DD_OK )
{
return false;
}
//设置关键色
SetColorKey(lpDDSBack,RGB(255,0,0));
}
//建立裁剪器
CreateClipper();
return true;
}
// 释放DirectDraw对象
void CGraph::FreeDDraw(void)
{
MessageBox(hWnd,"Releasing...","Release",MB_OK);
if (lpDD != NULL)
{
_RELEASE( lpClipper );
_RELEASE( lpDDSBack );
_RELEASE( lpDDSPrimary );
_RELEASE( lpDD );
}
}
// 设置窗口风格与当前显示模式匹配
bool CGraph::SetWindowStyle(void)
{
if(this->bIsWindowMode)
{
SetWindowLong(hWnd,GWL_EXSTYLE, WS_EX_OVERLAPPEDWINDOW);
SetWindowLong(hWnd,GWL_STYLE, WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX);
SetWindowPos(hWnd,HWND_NOTOPMOST, 0,0,m_WinWidth,m_WinHeight,SWP_SHOWWINDOW | SWP_NOMOVE );
}else{
SetWindowLong(hWnd,GWL_EXSTYLE,WS_EX_TOPMOST);
SetWindowLong(hWnd,GWL_STYLE, WS_POPUP);
SetWindowPos(hWnd,HWND_TOPMOST,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),SWP_SHOWWINDOW);
}
return true;
}
// 建立裁剪器
bool CGraph::CreateClipper(void)
{
if( lpDD->CreateClipper( 0, &lpClipper, NULL ) != DD_OK)
{
#ifdef _DEBUG
myTrace.Write("CGraph::CreateClipper() CreateClipper Error!/n");
#endif
return false;
}
if(lpDDSPrimary->SetClipper(lpClipper) != DD_OK)
{
#ifdef _DEBUG
myTrace.Write("CGraph::CreateClipper() SetClipper Error!/n");
#endif
return false;
}
return true;
}
// 设置关键色
HRESULT CGraph::SetColorKey(IDirectDrawSurface * pdds, COLORREF rgb)
{
DDCOLORKEY ddck;
ddck.dwColorSpaceLowValue = ColorMatch(pdds, rgb);
ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
}
// 获得指定颜色对应的调色板索引
DWORD CGraph::ColorMatch(IDirectDrawSurface * pdds, COLORREF rgb)
{
COLORREF rgbT;
HDC hdc;
DWORD dw = CLR_INVALID;
DDSURFACEDESC ddsd;
HRESULT hres;
if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
{
rgbT = GetPixel(hdc, 0, 0); // 保存当前值
SetPixel(hdc, 0, 0, rgb);
pdds->ReleaseDC(hdc);
}
ddsd.dwSize = sizeof(ddsd);
while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
;
if (hres == DD_OK)
{
dw = *(DWORD *)ddsd.lpSurface; // 转化为DWORD
dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1; // mask it to bpp
pdds->Unlock(NULL);
}
if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
{
SetPixel(hdc, 0, 0, rgbT); //恢复原来值
pdds->ReleaseDC(hdc);
}
return dw;
}
// 创建一个离屏Surface并加载bmp图片到页面
IDirectDrawSurface * CGraph::LoadBitmap(IDirectDraw * pdd, LPCSTR szBitmap , int dx , int dy)
{
HBITMAP hbm;
BITMAP bm;
DDSURFACEDESC ddsd;
IDirectDrawSurface *pdds;
//首先尝试作为资源加载
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx, dy,
LR_CREATEDIBSECTION);
//资源加载失败,作为文件加载
if (hbm == NULL)
hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
if (hbm == NULL)
return NULL;
//获取图片大小
GetObject(hbm, sizeof(bm), &bm);
//创建Surface
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = bm.bmWidth;
ddsd.dwHeight = bm.bmHeight;
if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
return NULL; //创建Surface失败
//加载图片
CopyBitmap(pdds, hbm, 0, 0, 0, 0);
DeleteObject(hbm);
return pdds;
}
// 把hbm位图Copy到目标Surface
HRESULT CGraph::CopyBitmap(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("createcompatible dc failed/n");
SelectObject(hdcImage, hbm);
// 得到bmp大小
GetObject(hbm, sizeof(bm), &bm);
dx = dx == 0 ? bm.bmWidth : dx; // 只要参数指定了大小,则用指定大小, 否则用图片默认大小
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;
}
// 加载一个Bitmap到页面(与LoadBitmap不同的是,这个函数不会创建Surface)
HRESULT CGraph::ReloadBitmap(IDirectDrawSurface * pdds, LPCSTR szBitmap)
{
HBITMAP hbm;
HRESULT hr;
// 注释看LoadBitmap函数,相当接近.
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)
{
char str[128];
sprintf(str, "handle is null [%s]/n", szBitmap);
OutputDebugString(str);
return E_FAIL;
}
hr = CopyBitmap(pdds, hbm, 0, 0, 0, 0);
if (hr != DD_OK)
{
OutputDebugString("ddcopybitmap failed/n");
}
DeleteObject(hbm);
return hr;
}
// 功能测试函数
void CGraph::Test(void)
{
}
大致上就是这样了,中间有几个函数是从微软的ddutil.cpp中抄回来的,只是少了DD两个字符。
省略了一个从Bitmap文件读取调色板的函数,因为我打算做的game是最少24bit色彩的,用不上调色板。
16bit色要判断555,565很麻烦。也不用了,再说65536色也太少了,不利于美工发挥……
![](http://blog.csdn.net/Emoticons/77_77.gif)