CGraph的增改

郁闷。一个年就几天过完了,好像什么感觉都没有。

热闹的时间不够长,很不爽啊。

明天是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色也太少了,不利于美工发挥……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值