
MFC中的CDC 绘图.doc
26页MFC中的CDC 绘图 绘图一般在视图类的(屏幕/打印机)绘图消息响应函数OnDraw中进行,例如:void CTestView::OnDraw(CDC* /*pDC*/) { CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: 在此处为本机数据添加绘制代码}每次需要重绘窗口时(程序启动/窗口大小改变/全部或部分窗口重现/程序员调用RedrawWindow或UpdateWindow),应用程序框架都会调用该CWnd的消息响应成员函数(的覆盖)来绘制窗口客户区在Windows中,绘图一般在视图窗口的客户区进行,使用的是MFC的设备上下文(DC = Device-Context)类CDC中各种绘图函数在绘图前,必须先得到客户区大小和DC、设置绘图颜色,然后再根据文档数据或用户操作来绘制图形1 几何对象的结构和类为了使用绘图函数,应该先了解绘图所用到的几种表示几何对象的结构和类这些结构和类分别定义在头文件windef.h和afxwin.h中。
1.点1)点结构POINT点数据结构POINT用来表示一点的x、y坐标:typedef struct tagPOINT { LONG x; LONG y; } POINT;2)点类CPoint点类CPoint为一个没有基类的独立类,封装了POINT结构,有成员变量x和y,其构造函数有5种:CPoint( );CPoint( int initX, int initY );CPoint( POINT initPt );CPoint( SIZE initSize );CPoint( LPARAM dwPoint ); // 低字设为x、高字设为yCPoint类还定义了4个平移和设置函数:void Offset(int xOffset, int yOffset);void Offset(POINT point);void Offset(SIZE size);void SetPoint(int X, int Y);CPoint类还重载了+、-、+=、-=、==、!=等运算符来支持CPoint对象和CPoint、POINT、SIZE对象之间的运算2.大小1)大小结构SIZE大小(size尺寸)结构SIZE用来表示矩形的宽cx和高cy:typedef struct tagSIZE { LONG cx; LONG cy;} SIZE;2)大小类CSize大小类CSize也为一个没有基类的独立类,封装了SIZE结构,有成员变量cx和cy,其构造函数也有5种:CSize( );CSize( int initCX, int initCY );CSize( SIZE initSize );CSize( POINT initPt );CSize( DWORD dwSize ); // 低字设为cx、高字设为cyCSizet类也重载了+、-、+=、-=、==、!=等运算符来支持CSize对象和CSize、POINT、SIZE、RECT对象之间的运算。
3.矩形1)矩形结构RECT矩形结构RECT定义了矩形的左上角与右下角的坐标:typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom;} RECT;2)矩形类CRect矩形类CRect也为一个没有基类的独立类,封装了RECT结构,有成员变量left、top、right和bottom,其构造函数有6种:CRect( );CRect( int l, int t, int r, int b );CRect( const RECT& srcRect );CRect( LPCRECT lpSrcRect );CRect( POINT point, SIZE size );CRect( POINT topLeft, POINT bottomRight );CRect类重载了=,+、-,+=、-=,==、!=,&、|,&=、|=等运算符来支持CRect对象和CRect、POINT、SIZE、RECT对象之间的运算还定义了转换符LPCRECT和LPRECT来自动完成CRect对象到矩形结构和类指针LPCRECT和LPRECT的转换。
CRect类中常用的属性和成员函数有:int Width( ) const;int Height( ) const;CSize Size( ) const;CPoint& TopLeft( );CPoint& BottomRight( );CPoint CenterPoint( ) const;void SwapLeftRight();BOOL IsRectEmpty( ) const;BOOL PtInRect( POINT point ) const;void SetRect( int x1, int y1, int x2, int y2 );void SetRect(POINT topLeft, POINT bottomRight);void OffsetRect(int x, int y);void MoveToXY(int x, int y);3) 判断点是否在矩形中有时需要判断某点(如鼠标位置)是否在某一矩形区域中,这可以调用CRect类的PtInRect函数来做:BOOL PtInRect( POINT point ) const;该函数当点point在其矩形区域内时,返回真。
注意,该矩形区域不包括矩形的右边界和底边界例如:CRect rect( 10, 10, 371, 267 );void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if ( rect.PtInRect( point ) ) {... ... }... ... CView::OnLButtonUp(nFlags, point);}2 客户区大小和DC在绘图前,必须先得到客户区大小和设备上下文DC1.获得客户区绘图一般都是在视图窗口的客户区进行,而客户区的大小在运行时可由用户改变,为了使绘制的图形能随窗口大小自动改变,必须先得到当前客户区大小的数据(宽w和高h)获取客户区大小的方法有如下两种:1)在消息响应函数OnSize中获得利用属性窗口的信息页,在视图类中添加WM_SIZE消息的响应函数OnSize该函数在窗口第一次显示或窗口大小被改变时会被Windows系统调用。
其输入参数中的cx和cy就是客户区大小的宽和高,可将它们赋值给类变量(如m_iW和m_iH)供绘图时使用例如void CDrawView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 m_iW = cx; m_iH = cy;}其中,nType的值为:SIZE_MAXIMIZED(窗口已被最大化)SIZE_MINIMIZED(窗口已被最小化)SIZE_RESTORED(窗口已被改变大小)SIZE_MAXHIDE(其他窗口被最大化)SIZE_MAXSHOW(其他窗口从最大化还原)2)调用成员函数GetClientRect得到可在绘图前,定义一个矩形变量rect,然后再调用CWnd类的成员函数GetClientRect:void GetClientRect( LPRECT lpRect ) const;得到当前客户区矩形的数据,其中的右(right)与底(bottom)就是客户区的宽与高(其左left与顶top都为0)。
例如: RECT rect; GetClientRect(&rect); int w = rect.right, h = rect.bottom;2.DC在Windows中,绘图使用的是MFC的DC(Device-Context, 设备上下文)类CDC中各种绘图函数0)CDC类CDC是CObject的直接派生类,CDC类自己也有若干派生类,其中包括窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响应函数的输入参数中使用的CPaintDC类、图元文件对应的CMetaFileDC类和整个窗口所对应的CWindowDC类CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等,将在后面陆续加以介绍1)获得DC可以从OnDraw函数的输入参数pDC或调用CWnd的成员函数GetDC:CDC* GetDC( );来获得DC的指针2)释放DC因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源因此,对每次获得的DC,在使用完成后必须立即释放从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。
但由GetDC所获得的DC,必须自己来释放,这可以通过调用CWnd的成员函数ReleaseDC来完成:int ReleaseDC( CDC* pDC ); // 成功返回非0例如:void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); if (m_bLButtonDown) { CDC* pDC = GetDC(); pDC->SelectObject(new CPen(PS_SOLID, 0, RGB(255, 0, 0))); pDC->SelectStockObject(NULL_BRUSH); pDC-> Ellipse (rect); ReleaseDC(pDC); m_bLButtonDown = FALSE; } CView::OnLButtonUp(nFlags, point);}3)类DC每次从OnDraw函数的输入参数或调用GetDC所获得的DC,都是一个全新的临时缺省DC。
它不能用类变量来长期保存,而且原来选入的各种GDI对象全都被作废,必须从头再来为了使选入的各种GDI对象一直有效,必须在视图类的PreCreateWindow函数中调用CWnd类的成员函数AfxRegisterWndClass:LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassSt。





![河南新冠肺炎文件-豫建科[2020]63号+豫建科〔2019〕282号](http://img.jinchutou.com/static_www/Images/s.gif)






