| 
				 (4)在CDBufferView中添加成员变量: 
    int m_nDrawTool;    //绘图工具选择 
    int m_nButtonDown;  //按钮按下次数 
    Bitmap* m_pBitmap;  //虚拟画布 
    Graphics* m_pGP;    //虚拟画布图像对象指针 
    CArray<CPoint,CPoint> m_PointList; //记录图形各顶点坐标 
(5)在CDBufferView::CDBufferView()中添加初始化代码: 
    m_nDrawTool=0; 
    m_nButtonDown=0; 
    m_pBitmap=NULL; 
    m_pGP=NULL; 
    在CDBufferView::OnInitialUpdate()中创建虚拟画布(缓存): 
    m_pBitmap = new Bitmap(800,600,PixelFormat32bppARGB);//建立800×600的图像 
    m_pGP=new Graphics(m_pBitmap);//建立图像对象,用于在虚拟画布上绘制图像 
    m_pGP->Clear(Color::White);//必须有,用背景色填充画布; 
    在CDBufferView::~CDBufferView()中释放占用的资源: 
    if(m_pBitmap!=NULL) delete m_pBitmap; 
    if(m_pGP!=NULL) delete m_pGP; 
    if(m_PointList.GetCount()>0)m_PointList.RemoveAll(); 
(6)分别建立直线、矩形、椭圆和曲线的菜单命令方法: 
void CDBufferView::OnDrawLine() 
{   this->m_nDrawTool=0;} //当前状态设为画直线 
void CDBufferView::OnUpdateDrawLine(CCmdUI *pCmdUI) 
{   pCmdUI->SetCheck(this->m_nDrawTool==0);} 
void CDBufferView::OnDrawRectangle() 
{   this->m_nDrawTool=1;} //当前状态设为画矩形 
void CDBufferView::OnUpdateDrawRectangle(CCmdUI *pCmdUI) 
{   pCmdUI->SetCheck(this->m_nDrawTool==1);} 
void CDBufferView::OnDrawEllipse() 
{   this->m_nDrawTool=2;} //当前状态设为画椭圆 
void CDBufferView::OnUpdateDrawEllipse(CCmdUI *pCmdUI) 
{   pCmdUI->SetCheck(this->m_nDrawTool==2); } 
void CDBufferView::OnDrawCurve() 
{   this->m_nDrawTool=3;}//当前状态设为画曲线 
void CDBufferView::OnUpdateDrawCurve(CCmdUI *pCmdUI) 
{   pCmdUI->SetCheck(this->m_nDrawTool==3);} 
(7)建立鼠标左键按下事件响应函数,并添加如下代码: 
void CDBufferView::OnLButtonDown(UINT nFlags, CPoint point) 
{   if(m_nDrawTool>=0 && m_nDrawTool<=3) 
    { 
        if(m_nButtonDown==0) 
        {   if(m_PointList.GetCount()>0) m_PointList.RemoveAll();} 
        m_PointList.Add(point);//记录鼠标单击点 
        m_nButtonDown++; 
    } 
    CView::OnLButtonDown(nFlags, point); 
} 
(8)建立鼠标移动事件响应函数,并添加如下代码: 
void CDBufferView::OnMouseMove(UINT nFlags, CPoint point) 
{ 
    Bitmap* tempBitmap=m_pBitmap->Clone(0,0,m_pBitmap->GetWidth(), m_pBitmap->GetHeight(), PixelFormat32bppARGB); //建立虚拟画布副本 
    Graphics* pgp=new Graphics(tempBitmap); 
    PointF* tempPoint; 
    CPoint tempP; 
    switch(this->m_nDrawTool) 
    { 
    case 0: 
        if(m_nButtonDown>=1) 
        { 
            tempPoint=new PointF[2]; 
            tempP=m_PointList.GetAt(0); 
            tempPoint[0].X=(REAL)tempP.x; tempPoint[0].Y=(REAL)tempP.y; 
            tempPoint[1].X=(REAL)point.x; tempPoint[1].Y=(REAL)point.y; 
            Pen pen(Color::Black,1.0f); 
            pgp->DrawLine(&pen,tempPoint[0],tempPoint[1]);//画布副本上绘制直线 
            delete[] tempPoint; 
        } 
        break; 
    case 1: 
        if(m_nButtonDown>=1) 
        { 
            tempP=m_PointList.GetAt(0); 
            Pen pen(Color::Black,1.0f); 
            REAL tempX=(REAL)min(tempP.x,point.x); 
            REAL tempY=(REAL)min(tempP.y,point.y); 
            REAL tempW=(REAL)(tempP.x>point.x?tempP.x-point.x:point.x-tempP.x); 
            REAL tempH=(REAL)(tempP.y>point.y?tempP.y-point.y:point.y-tempP.y); 
            pgp->DrawRectangle(&pen,tempX,tempY,tempW,tempH);//副本画布上绘制矩形 
        } 
        break; 
    case 2://绘制椭圆,方法与矩形类似,省略 
        break; 
    case 3://绘制曲线,略 
        break; 
    } 
    Graphics gp(this->GetSafeHwnd()); 
    gp.DrawImage(tempBitmap,0,0);//将画布副本复制到屏幕 
    delete tempBitmap;  delete pgp; 
    CView::OnMouseMove(nFlags, point); 
} 
(9)建立鼠标左键按下事件响应函数,并添加如下代码: 
void CDBufferView::OnLButtonUp(UINT nFlags, CPoint point) 
{ 
    // TODO: Add your message handler code here and/or call default 
    ::SetCursor(s_Cross); 
    Graphics gp(this->GetSafeHwnd()); 
    PointF* tempPoint; 
    CPoint tempP; 
    switch(this->m_nDrawTool) 
    { 
    case 0://在虚拟画布上画直线并将虚拟画布复制到屏幕上 
        if(m_nButtonDown>=1) 
        { 
            tempPoint=new PointF[2]; 
            tempP=m_PointList.GetAt(0); 
            tempPoint[0].X=(REAL)tempP.x; 
            tempPoint[0].Y=(REAL)tempP.y; 
            tempPoint[1].X=(REAL)point.x; 
            tempPoint[1].Y=(REAL)point.y; 
            Pen pen(Color::Black,1.0f); 
            m_pGP->DrawLine(&pen,tempPoint[0],tempPoint[1]); 
            m_nButtonDown=0; 
            delete[] tempPoint; 
        } 
        gp.DrawImage(m_pBitmap,0,0);//复制缓存区数据到屏幕 
        break; 
    case 1://在虚拟画布画矩形并复制到屏幕上,略 
        break; 
    case 2://在虚拟画布画椭圆并复制到屏幕上,略 
        break; 
    } 
    CView::OnLButtonUp(nFlags, point); 
} 
程序在Visual Studio2005+Windows2003环境调试通过,下面是运行效果图,如图2,图3,图4,图5所示。 
| 
  
 
  
图2 画直线  | 
  
 
  
图3 画矩形  |  
| 
  
 
  
图4 画椭圆  | 
  
 
  
图5 画曲线  |   
    
六、总结 在交互式绘图系统中,使用橡皮筋技术是经常遇到的一个实际问题,而GDI+具有比GDI更方便的开发方法和更美观的图像效果,在软件开发中应用得越来越广泛。本文应用双缓存技术解决在GDI+绘图过程中的橡皮筋技术问题,使图形的绘制过程更加直观。			
				 |