#pragma once
#include "CDCEx.h"
class MFC_2D
{
public:
static HRGN createTriangle(const POINT i_POINT[3], int i_iDx);
MFC_2D(void);
virtual ~MFC_2D(void);
bool initDialogScene(CWnd* i_pDlg, int i_iSceneW, int i_iSceneH);
bool initDialogScene(CDC* i_pcdcSrc, int i_iSceneW, int i_iSceneH);
bool initDialogScene(CDC* i_pcdcSrc, CRect rtSrc);
bool beginScene();
bool SaveScene();
bool RecoverScene();
void endScene(CPaintDC& dc);
template<class T>
static void delObject(T* pData)
{
if( NULL != pData)
{
TRACE1("del Object: %08x/n", pData);
pData->DeleteObject();
delete pData;
}
pData = NULL;
}
template<class T>
static void delEx(T* pData)
{
if( NULL != pData)
{
TRACE1("del %08x/n", pData);
delete pData;
}
pData = NULL;
}
protected:
CDCEx* m_pobjMem; //声明用于缓冲作图的内存DC
private:
CBitmap* m_pbmpBackground; //由于保存固定画面(可叠加)以提高渲染速度
};
#include "StdAfx.h"
#include "MFC_2D.h"
#include "WinCE600.h"
#include "AFX.h"
#include <vector>
MFC_2D::MFC_2D(void):
m_pobjMem(NULL),
m_pbmpBackground(NULL)
{
}
MFC_2D::~MFC_2D(void)
{
delObject(m_pbmpBackground);
delEx(m_pobjMem);
}
bool MFC_2D::initDialogScene(CWnd* i_pDlg, int i_iSceneW, int i_iSceneH)
{
CDC* pDC = i_pDlg->GetDC();
if( NULL == pDC)
return false;
bool bRet = initDialogScene(pDC,i_iSceneW,i_iSceneH);
ReleaseDC(i_pDlg->m_hWnd,*pDC);
return bRet;
}
bool MFC_2D::initDialogScene(CDC* i_pcdcSrc, int i_iSceneW, int i_iSceneH)
{
CRect rtSrc(0,0,i_iSceneW,i_iSceneH);
return initDialogScene(i_pcdcSrc, rtSrc);
}
bool MFC_2D::initDialogScene(CDC* i_pcdcSrc, CRect rtSrc)
{
delEx(m_pobjMem);
try
{
m_pobjMem = new CDCEx(CSize(rtSrc.Width(),rtSrc.Height()),i_pcdcSrc,rtSrc);
}
catch (std::exception *e)
{
char exp[512];
strcpy(exp,e->what());
a2w wE(exp);
TRACE(wE);
m_pobjMem = NULL;
return false;
}
//TRACE1("new %08x/n", m_pobjMem);
return true;
}
bool MFC_2D::beginScene()
{
if( NULL == m_pobjMem)
return false;
CBrush br(RGB(240,180,170));
((CDC*)*m_pobjMem)->FillRect(CRect(0,0,m_pobjMem->m_iSceneW,m_pobjMem->m_iSceneH),&br);
br.DeleteObject();
return true;
}
bool MFC_2D::SaveScene()
{
delObject(m_pbmpBackground);
m_pbmpBackground = m_pobjMem->save(CSize(m_pobjMem->m_iSceneW,m_pobjMem->m_iSceneH),CRect(0,0,m_pobjMem->m_iSceneW,m_pobjMem->m_iSceneH));
if( NULL != m_pbmpBackground)
return true;
return false;
}
bool MFC_2D::RecoverScene()
{
if( NULL != m_pbmpBackground && NULL != m_pobjMem)
{
m_pobjMem->draw(CRect(0,0,m_pobjMem->m_iSceneW,m_pobjMem->m_iSceneH),m_pbmpBackground,CRect(0,0,m_pobjMem->m_iSceneW,m_pobjMem->m_iSceneH));
return true;
}
return false;
}
void MFC_2D::endScene(CPaintDC& dc)
{
dc.BitBlt(0,0,m_pobjMem->m_iSceneW,m_pobjMem->m_iSceneH,(CDC*)*m_pobjMem,0,0,SRCCOPY);
}
HRGN MFC_2D::createTriangle(const POINT i_POINT[3], int i_iDx = 1)
{
HRGN hRGN = NULL;
hRGN = CreateRectRgn(0, 0, 0, 0);
struct TRIANGLE_LINE
{
double k;
double b;
int minX;
int maxX;
void initLine(const POINT& i_POINT1,const POINT& i_POINT2)
{
if( i_POINT1.x == i_POINT2.x)
{
k = b = 999;
minX = maxX = i_POINT1.x;
}
else
{
k = (double)(i_POINT2.y-i_POINT1.y)/(i_POINT2.x-i_POINT1.x);
b = i_POINT1.y-k*i_POINT1.x;
if( i_POINT1.x < i_POINT2.x)
{
minX = i_POINT1.x;
maxX = i_POINT2.x;
}
else
{
minX = i_POINT2.x;
maxX = i_POINT1.x;
}
}
}
bool getY(int& o_iY, const int i_iX)
{
if( i_iX<minX || i_iX>maxX || (k >= 998 && k <= 1000))
{// 越界或者k==0
//TRACE3("%d, %d, %0.3f/n",minX,maxX,k);
return false;
}
else
{
//TRACE3("%d, %d, %0.3f/n",minX,maxX,k);
o_iY = k*i_iX + b;
return true;
}
}
};
TRIANGLE_LINE tgLine[3];
tgLine[0].initLine(i_POINT[0],i_POINT[1]);
tgLine[1].initLine(i_POINT[0],i_POINT[2]);
tgLine[2].initLine(i_POINT[1],i_POINT[2]);
int iStartX = tgLine[0].minX;
int iEndX = tgLine[0].maxX;
for(int i=1; i<3; i++)
{
if( iStartX > tgLine[i].minX)
iStartX = tgLine[i].minX;
if( iEndX < tgLine[i].maxX)
iEndX = tgLine[i].maxX;
}
int iPosX = iStartX;
hRGN = CreateRectRgn(0,0,0,0);
while( iPosX<=iEndX)
{
int iStartY = -1, iEndY = -1;
int iTemp;
for(int i=0; i<3; i++)
{
if( tgLine[i].getY(iTemp,iPosX))
{
if( iStartY > iTemp || -1 == iStartY)
iStartY = iTemp;
if( iEndY < iTemp || -1 == iEndY)
iEndY = iTemp;
}
}
if( iStartY >= 0 && iEndY >= 0)
{
HRGN rgnTemp = NULL;
int iRectX = iPosX+i_iDx;
iRectX = (iRectX > iEndX)?iEndX:iRectX;
rgnTemp = CreateRectRgn((int)iPosX, (int)iStartY, (int)iRectX, (int)iEndY);
CombineRgn(hRGN,hRGN,rgnTemp,RGN_OR);
DeleteObject(rgnTemp);
}
if( iPosX < iEndX)
{
iPosX += i_iDx;
iPosX = (iPosX > iEndX)? iEndX:iPosX;
}
else break;
}
return hRGN;
}