Windows程序设计

  • 格式:doc
  • 大小:574.50 KB
  • 文档页数:42

第8章 GDI编程1-绘图GDI(Graphics Device Interface,图形设备接口)是Windows操作系统的传统图形子系统,负责与设备无关的图形绘制,Win32 API为应用程序提供了丰富的绘图函数和功能,MFC对它们进行了C++类封装,参见图8-1。

图8-1 GDI与Windows操作系统(其中深色部分为操作系统)传统GDI是随Windows 1.0于1985年11月推出的,新式GDI+则是随Windows XP于2001年10月推出的GDI的改进版,增加了α混色、渐变画刷、样条曲线、矩阵变换、图像处理、持久路径等新功能。

随Windows Vista及.NET框架3.0微软于2006年11月又推出了基于DirectX和.NET框架的全新图形子系统WPF(Windows Presentation Foundation,视窗显示/展现基础),它统一了桌面和浏览器等客户端应用程序的图形界面,采用XAML声明式编程,将用户界面的设计和编程彻底分离开来,是Windows的新一代GUI显示系统。

本书从第8章到第11章,将详细讨论如何使用GDI进行传统的Windows图形编程,包括绘图、文字、图像、动画、图标、图元文件和打印等内容。

GDI+是建立在GDI之上的,计划在第14和15章中作简单介绍。

WPF则是以.NET框架为基础的,准备在第19和20章中再加以讨论。

在MFC应用程序中,绘图一般在视图类的(屏幕/打印机)绘图消息响应函数OnDraw 中进行,下面是自动生成的函数代码:void CDrawView::OnDraw(CDC* /*pDC*/) {CDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码} 每次需要重绘窗口时(如程序启动、窗口大小改变、全部或部分窗口重现、程序员调用函数RedrawWindow 或Invalidate/UpdateWindow ),应用程序框架都会调用此CWnd 消息响应成员函数(的覆盖)来绘制窗口客户区。

在Windows 中,绘图一般在框架窗口的客户区(对应于视图类C*View )中进行,使用的是封装在MFC 中的设备上下文(Device-Context ,DC )类CDC 中的各种绘图函数。

在绘图前,一般需先得到客户区大小和CDC 对象、设置绘图颜色(创建并选入笔刷对象),然后再根据文档数据或用户操作来(调用绘图函数)绘制各种图形(包括显示字符串)。

8.1 几何对象的结构和类为了使用绘图函数,应该先了解绘图所用到的几种表示几何对象的结构和类,包括点、大小和矩形,其中常用的是点和矩形。

这些结构和类被分别定义在头文件windef.h 和afxwin.h 中。

MFC 中的几何对象类都是独立的类(不是CObject 的派生类),是对API 中对应结构的C++封装,参见图8-2。

8.1.1 点点(point )在API 中的结构为POINT ,对应的MFC 类为CPoint 。

1.点结构POINTAPI 中的点数据结构POINT 用来表示一点的x 、y 坐标:typedef struct tagPOINT { LONG x; LONG y; } POINT;其中,类型LONG (32位整数)的定义为:typedef long LONG;2.点类CPointMFC 中的点类CPoint 为一个没有基类的独立类,封装了POINT 结构。

实际上,CPoint 类是直接从POINT 结构派生的:图8-2 GDI 几何对象的结构与类class CPoint : public tagPOINT与POINT结构一样,CPoint类也具有成员变量x和y。

另外还有如下5种构造函数:CPoint( ); // 默认CPoint( POINT initPt );CPoint( int initX, int initY ); // 常用CPoint( SIZE initSize );CPoint( LPARAM dwPoint ); // 低字设为x、高字设为yCPoint类还定义了3个平移和1个设置的成员函数:void Offset(int xOffset, int yOffset); void Offset(POINT point); void Offset(SIZE size); void SetPoint(int X, int Y);另外,CPoint类还重载了+、-、+=、-=、==、!= 等运算符,以支持CPoint对象和CPoint/CSize 对象及POINT/SIZE变量之间的运算。

8.1.2 大小大小(size,尺寸)在API中的结构为SIZE,在MFC中的类为CSize。

1.大小结构SIZE大小结构SIZE用来表示矩形的宽cx和高cy:typedef struct tagSIZE { LONG cx; LONG cy; } SIZE;2.大小类CSizeMFC中的大小类CSize也为一个没有基类的独立类,封装了SIZE结构。

实际上,CSize 类也是直接从SIZE结构派生的:class CSize: public tagSIZE与SIZE结构一样,CSize类也具有成员变量cx和cy,另外还有如下5种构造函数:CSize( ); // 默认CSize( SIZE initSize );CSize( int initCX, int initCY ); // 常用CSize( POINT initPt );CSize( DWORD dwSize ); // 低字设为cx、高字设为cyCSizet类也重载了+、-、+=、-=、==、!= 等运算符,来支持CSize对象和CPoint/CSize/CRect 对象及POINT/SIZE/RECT变量之间的运算。

8.1.3 矩形矩形(rectangle)在API中的结构为RECT,在MFC中的类为CRect。

1.矩形结构RECTAPI中的矩形结构RECT定义了矩形的左上角与右下角的坐标:typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom;} RECT;2.矩形类CRectMFC中的矩形类CRect也为一个没有基类的独立类,封装了RECT结构。

实际上,CRect 类也是直接从RECT结构派生的:class CRect : public tagRECT与RECT结构一样,CRect类也具有成员变量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 对象和CPoint/CSize/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; // 获取中心点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: 在此添加消息处理程序代码和/或调用默认值if ( rect.PtInRect(point) ) ... ...CView::OnLButtonUp(nFlags, point);}8.1.4 获得客户区大小绘图一般都是在框架窗口的客户区(对应于视图类)中进行的,而客户区的大小在运行时可由用户动态改变,为了使绘制的图形能随窗口大小而自动改变,需先得到当前客户区大小的数据(宽和高)。

获取客户区大小的方法有如下两种:1.OnSize获取客户区大小的第一种方法是通过消息响应函数OnSize获得。

可利用属性窗口的消息页,为视图类添加WM_SIZE消息的响应函数OnSize。

该函数会在窗口第一次显示或窗口大小被改变后会被系统自动调用。

其输入参数中的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获取客户区大小的第二种方法是调用窗口类CWnd的获取客户区矩形成员函数GetClientRect来得到,该函数的原型为:void GetClientRect( LPRECT lpRect ) const;其中,矩形结构的右(right)与底(bottom)就是当前客户区的宽与高(其左left与顶top 都为0)。