第11课 图形的保存和重绘

CView类的OnPaint()
void CView::OnPaint()
{
     // standard paint routine
     CPaintDC dc(this);
     OnPrepareDC(&dc);
     OnDraw(&dc);
}
可见,视图类窗口重绘都会调用OnDraw(),所以,在视图类中重写OnDraw即可。

1. 创建 4  个菜单,为其添加消息响应,用成员变量保存绘画类型。添加 LButtonDownUp 消息。

2. 当窗口重绘时,如果想再显示原先画的数据,则需要保存数据。为此创建一个新类来记录绘画类型和两个点。
class CGraph 
{
public:
 CPoint m_ptOrigin;//  起点
 CPoint m_ptEnd;//  终点
 UINT m_nDrawType;//  绘画类型
 CGraph();
 CGraph(UINT m_nDrawType,CPoint m_ptOrigin,CPoint m_ptEnd);//  此为构造函数。
 virtual ~CGraph();};
    然后在void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)中加入如下代码
 //CGraph graph(m_nDrawType,m_ptOrigin,point);//  不能用局部变量
 //m_ptrArray.Add(&graph);//  加入这种指针数组中
/* OnPrepareDC(&dc);//  这个函数中可以重新设置窗口原点,对于滚动条中,保存数据前要调用此函数
 dc.DPtoLP(&m_ptOrigin);//  将设备坐标转换为逻辑坐标
 dc.DPtoLP(&point);//
 CGraph *pGraph=new CGraph(m_nDrawType,m_ptOrigin,point);//  在堆中创建新的对象
 m_ptrArray.Add(pGraph);*///  加入到指针数组中
GraphicView.h 中有如下代码
 CPtrArray m_ptrArray;
    OnDraw中重画时调出数据
 for(int i=0;i<m_ptrArray.GetSize();i++)

3. CView::OnPaint()  调用了OnDraw(),但在 void CGraphicView::OnPaint()MFC Wizard没有调用 OnDraw(),要注意这个区别。如果你此时想调用,必须手动添加代码。 OnDraw(&dc);

4. 让窗口具有滚动条的功能。
    1. CGraphicView的头文件中的CView全部替换成 CSrollView
    2.添加如下的代码
void CGraphicView::OnInitialUpdate()
{
 CScrollView::OnInitialUpdate();
 
 // TOD Add your specialized code here and/or call the base class
 SetScrollSizes(MM_TEXT,CSize(800,600));//  设置映射模式,设定窗口大小。 OK
}

5. 坐标系的转换,此处不再详细介绍,需要时请查阅相关资料。
SetWordTransform
几乎所有的GDI函数使用的坐标值都是采用逻辑坐标(所以,视图类的OnDraw()中使用的是逻辑坐标),Windows必须将罗技单位转换为设备单位(即像素)。
Windows对于所有的消息(WM_SIZE,WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_LBUTTONUP),所有的非GDI函数和少量GDI函数(如GetDeviceCaps函数),使用的是设备坐标。
“窗口”是基于逻辑坐标的,单位可以是像素,毫米,英寸,等。
“视口”是基于设备坐标(像素),通常,视口和客户区是对应的。
缺省映射模式是MM_TEXT,这时,逻辑单位和设备单位相同,都是像素。SetMapMode()可改变映射模式。
CView类的OnInitialUpdate()函数是在窗口创建后调用的第一个函数。该函数在OnDraw()之前调用。
CDC中提供了两个成员函数函数SetViewportOrg和SetWindowOrg,用来改变视口和窗口的原点。
OnPrepareDC(&dc) 会随时根据滚动窗口的位置来调整视口的原点。
DPToLP()将设备坐标转换成逻辑坐标。
LPToDP()将逻辑坐标转换成设备坐标。

6. 解决重绘时线跑到上面的问题。为什么会错位?因为逻辑坐标和设备坐标没有对应起来。
解决方法:
   OnLButtonDown 画完图后,保存之前。调用
OnPrepareDC(&dc);//  重新设置逻辑坐标的原点!!!
 dc.DPtoLP(&m_ptOrigin);//  设备坐标转化为逻辑坐标
 dc.DPtoLP(&point);
 CGraph *pGraph=new CGraph(m_nDrawType,m_ptOrigin,point);
 m_ptrArray.Add(pGraph);

7. 另外两种方法来保存数据。
一种是用 CMetaFileDC: CopyMetaFile保存元文件,GetMetaFile打开元文件。
另一种是利用 CreateCompatibleBitmap创建 兼容 DC ,重绘时利用 pDC->BitBlt(0,0,rect.Width(),rect.Height(),&m_dcCompatible,0,0,SRCCOPY);
将兼容  DC的图拷贝到屏幕DC上去。
CreateCompatibleBitmap返回的位图对象只包含相应设备描述表中的位图的位图信息头,不包含颜色表和象素数据块。因此,选入该位图对象的设备描述表不能像选入普通位图对象的设备描述表一样应用,必须在SelectObject函数之后,调用BitBlt将原始设备描述表的颜色表及象素数据块拷贝到兼容设备描述表。

猜你喜欢

转载自blog.csdn.net/zhang_zxk/article/details/52401918