54
1 返返 第 8 第 第第第第第第 1. 第第第第DC 第第第第 )。 2. 第第第第第第第第第第第 CPaintDC CClientDC CWin dowDC 第 CMetaFileDC 第第第第第第第第第第第第第第第第第第3.GDI 第第第第第第第第第第第第第 CGdiObject CPen CB rush Cfont 第 CBitmap 第第第第第第第第第第第第第第第第第第第 第第4.Windows 第第第第第第第第第第第第第第第第第第第第第第第5. 第第第第第 Windows 第第第第第第第第第第第第第第第6. 第第第第第第第第第第第第第 第第第 第第第第第第第第第第第第 、、。

第 8 章 图形图像处理

  • Upload
    tender

  • View
    78

  • Download
    0

Embed Size (px)

DESCRIPTION

第 8 章 图形图像处理. 1. 设备环境( DC )的概念。 2. 常用的几个设备环境类如 CPaintDC 、 CClientDC 、 CWindowDC 和 CMetaFileDC 类的主要特点及它们在使用方法上的区别。 3.GDI 的概念及常用的绘图设备类如 CGdiObject 、 CPen 、 CBrush 、 Cfont 和 CBitmap 等的对象的创建和将其引入到设备环境中的方法。 4.Windows 下的坐标映像方式和特点以及如何设置坐标映像方式。 5. 几种常见的 Windows 的坐标映像方式下的坐标转换方法。 - PowerPoint PPT Presentation

Citation preview

Page 1: 第 8 章 图形图像处理

1返回返回

第 8章 图形图像处理 1. 设备环境( DC )的概念。2. 常用的几个设备环境类如 CPaintDC 、 CClientDC 、CWindowDC 和 CMetaFileDC 类的主要特点及它们在使用方法上的区别。3.GDI 的概念及常用的绘图设备类如 CGdiObject 、 CPen 、 CBrush 、 Cfont 和 CBitmap 等的对象的创建和将其引入到设备环境中的方法。4.Windows 下的坐标映像方式和特点以及如何设置坐标映像方式。5. 几种常见的 Windows 的坐标映像方式下的坐标转换方法。6. 几种常见的基本图形元素如点、直线、矩形和文字等的绘制方式。

Page 2: 第 8 章 图形图像处理

2返回返回

8.1 设备环境( DC ) ( 1 )在 Windows 中,显示工作是基于设备环境的。

所谓设备环境( DC )是一种 Windows 数据结构,该结构包含应用程序设备输出时所需要的信息。

( 2 )在使用任何绘图函数之前必须建立一个设备环境对象。

 ( 3 )在 Visual C++ 6.0的MFC中提供了设备环境类CDC,它封装了绘图所需要的所有函数,其中包括了大多数的Windows API中的 GDI函数。

Page 3: 第 8 章 图形图像处理

3返回返回

8.1.1 设备环境类1. CDC 类 ( 1 ) CDC 类是 CObject 类的派生类,也是所有设备

环境类的基类。 CDC 类定义了一个设备描述对象,并提供了对设备描述对象进行操作的成员函数以及对与窗口客户区有关的显示区进行操作的成员函数。

 ( 2 ) CDC 类提供的成员函数可以用于操作设备描述对象、使用绘图工具、选择图形设备界面,以及操作颜色和调色板,还用于取得和设置绘图属性、映射方式、视图和窗口范围的操作、坐标的转换、区域的使用、剪取、画线以及绘制图形和文字等操作。

8.1 设备环境( DC )

Page 4: 第 8 章 图形图像处理

4返回返回

2. CPaintDC 类( 1 ) CPaintDC 类是 CDC 类的一个派生类,该类一般

用在响应 WM_PAINT 消息的函数 OnPaint() 中。( 2 ) WM_PAINT 消息是当窗口的某个区域需要重画时

激发的窗口消息。当程序中的消息循环接到 WM_PAINT 消息时就自动调用消息处理函数 OnPaint() ,如果在 OnPaint 函数内定义了 CPaintDC 类的对象,通过这个类对象就可以使用 CDC 类的成员函数完成视图客户区中的图形绘制操作。

8.1 设备环境( DC )

Page 5: 第 8 章 图形图像处理

5返回返回

3. CClientDC 类CClientDC 类也是 CDC 类的派生类。它只能在窗口的客

户区(即窗口中除了边框、标题栏、菜单栏以及状态栏外的中间部分)中进行绘图,坐标点( 0,0 )通常指的是客户区的左上角。它的构造函数调用 GegDC 函数,而析构函数调用 ReleaseDC 函数。

4. CWindowDC 类CWindowDC 类也是 CDC 类的派生类。其成员函数可以

在窗口的客户区和非客户区(即窗口的边框、标题栏、菜单栏以及状态栏)中绘图,坐标点( 0,0 )是指整个屏幕的左上角。同 CClientDC 类一样,它的构造函数调用 GegDC 函数,而析构函数调用 ReleaseDC 函数。

8.1 设备环境( DC )

Page 6: 第 8 章 图形图像处理

6返回返回

5. CMdtaFileDC 类CMetaFileDC 类提供了一个面向 Windows 图元文件的

设备环境,封装了在一个 Windows 图元文件中绘图的方法。图元文件是一个与设备无关的图片的集合,由于它对图像的保存比像素更精确,因而往往在要求较高的场合下使用,例如 AutoCAD 的图形保存等。

8.1 设备环境( DC )

Page 7: 第 8 章 图形图像处理

7返回返回

8.1.2 几个设备环境类的主要差别1. CWindowDC 类与 CPaintDC 、 CClientDC 类的区别其区别主要有以下两个方面:( 1 )用 CPaintDC 和 CClientDC 类的对象绘制图形时,

绘制区只能在客户区,而不能在非客户区;而 CwindowDC 类既可以在窗口的客户区也可以在非客户区进行图形绘制。

( 2 )在 CWindowDC 绘图类下,坐标系是建立在整个屏幕上的,在像素坐标方式下,坐标原点在屏幕的左上角;而在 CPaintDC 和 CClientDC 绘图类下,坐标系是建立在客户区上的,在像素坐标方式下,坐标原点在客户区的左上角。

8.1 设备环境( DC )

Page 8: 第 8 章 图形图像处理

8返回返回

2. CPaintDC 类与 CClientDC 类的区别 CPaintDC 类的对象应用在 OnPaint 函数中,以响应

Windows 的 WM_PAINT 消息;而 CClientDC 类的对象应用在非响应消息 WM_PAINT 的情况下。

CPaintDC 类响应 WM_PAINT 消息,并自动完成绘制,这对维护图形的完整性有着重要的作用。 CClientDC类可以实时地将图形绘制到屏幕上,不需要重画;而如果用 CPaintDC 类的对象完成同样的工作,只能发出消息让屏幕上包含这条直线的区域重画,以把这条直线绘制到屏幕上。

8.1 设备环境( DC )

Page 9: 第 8 章 图形图像处理

9返回返回

8.1.3 设备环境类的使用方法1. CDC 类因为 CDC 类不能用窗口对象指针初始化对象,所以,一般不直接定

义对象。2. CPaintDC 类CPaintDC 类一般用在窗口类 OnPaint 函数中,可采用如下代码定义

一个 CPaintDC 类对象:CPaintDC dc(this);以上代码定义了一个 CPaintDC 类的对象 dc ,并用当前的窗口对象

指针 this 对对象进行了初始化。 CClientDC 和 CWindowDC 类也采用这样的方法。

3. CClientDC 类可利用以下代码定义一个对象: CClientDC dc(this);4. CWindowDC 类利用以下代码创建一个 CWindowDC 类的对象: CWindowDC dc(thi

s);

8.1 设备环境( DC )

Page 10: 第 8 章 图形图像处理

10返回返回

8.2 绘图设备类 Windows为设备环境提供了各种各样的绘图工具,如【画笔】、【画刷】以及【字体】等。在 MFC 中封装了这些工具,这些类称为 GDI 类,它们有一个共同的抽象基类 CGdiObject ,可以将这些绘图设备类创建的对象选入到设备环境中,完成有关的操作。

在 MFC 中主要的绘图设备类有: CGdiObject 、 CPen 、 CBrush 、CFont 、 CBitmap 、 CRgn 和 CPalette 等。

 在选择绘图设备类对象( GDI 对象)进行绘图时,一般可按下列步骤进行:

( 1 )定义一个 GDI 对象,然后调用相应的函数(如 CreatePen 、CreateSolidBrush 等)创建此 GDI 对象。

( 2 )将已构造出的 GDI 对象利用设备环境类对象的成员函数 SelectObject 选入到当前环境中,并同时将原来的 GDI 对象保存起来。

( 3 )绘图结束后,恢复当前设备环境中原来的 GDI 对象。注意:在 Windows 系统中 包 含 了 一些库存的 GDI 对 象 , 在第

( 3 )步中可直接利用设备环境类( CDC )的成员函数 SelectStockObject 将一个 Windows库存的 GDI 对象选入,系统可自动将原来选入的 GDI 对象从设备环境中分离出来。

Page 11: 第 8 章 图形图像处理

11返回返回

8.2.1 CGdiObject 类CGdiObject 类派生于 CObject 类,它是 CGdiObject 、 CPen 、 C

Brush 、 Cfont 和 CBitmap 等的基类。用户不能直接生成一个 CGdiObject 类,而必须在它的某种设备继承类中生成一个 CGdiObject 类的派生类。

8.2.2 CPen 类CPen 类是 CGdiObject 类的一个派生类,它封装了 Windows 图形

设备接口( GDI )中有关画笔的操作。 CPen 类的定义如下:class CPen: public CGdiObject{DECLARE_DYNAMIC(CPen) public:

8.2 绘图设备类

Page 12: 第 8 章 图形图像处理

12返回返回

static CPen* PASCAL FromHandle(HPEN hpen);// 构造函数CPen( );CPen(int nPenStyle, int nWidth,COLORREF crColor);#ifndef_MACCPen(int nPenStyle, int nWidth, const LOGBRUSH * pLogBrush,int nSty

leCount=0, const DWORD * lpStyle=NULL);#endifBOOL CreatePen(int nPenStyle, int nWidth, COLORREF crColor);#ifndef_MACBOOL CreatePen(int nPenStyle, int nWidth, const LOGBRUSH * pLogBr

ush, int nStyleCount=0, const DWORD * lpStyle=NULL);#endifBOOL CreatePenIndirect(LPLOGPEN lpLogPen);//其他部分省略};

8.2 绘图设备类

Page 13: 第 8 章 图形图像处理

13返回返回

8.2.2.1 创建 CPen 对象创建一个 CPen 对象可以有以下几种方法:( 1 )定义一个 CPen 对象,用其成员函数 CreatePen或 CreatePen

Indirect 对其进行初始化。如:   CPen pen;   Pen.CreatePen(PS_SOLID,1,RGB(255,0,0));( 2 )定义一个 CPen 对象,并一次性地初始化它的所有参数。如:   CPen pen(PS_SOLID,1,RGB(255,0,RGB(255,0,0));( 3 )动态地创建一个 CPen 对象。如:   CPen *pen;   Pen=new CPen(PS_SOLID,1,RGB(255,0,0));  在一个函数中多次创建一个 CPen 对象时可以采用这种方法。应

用这种方法时,特别注意操作完毕后要删除分配的 CPen 对象,即:delete pen;

8.2 绘图设备类

Page 14: 第 8 章 图形图像处理

14返回返回

参数 nPenStyle 用于设置画笔画线的线型其取值如下表:

线 型 风 格

PS_SOLID 创建一个实线画笔

PS_DASH 创建一个虚线画笔

PS_DOT 创建一个点线画笔

PS_DASHDOT 创建一个虚线和点线交替的画笔

PS_DASHDOTDOT 创建一个虚线和双点线交替的画笔

PS_NULL 创建一个空的画笔

PS_INSIDEFRAME 创建一个在封闭矩形框中使用的画笔

8.2 绘图设备类

Page 15: 第 8 章 图形图像处理

15返回返回

注意:线型 PS_DASH 、 PS_DOT 、 PS_DASHDOT 和PS_DASHDOTDOT 只有在画笔宽度为1个逻辑单位时才有效。

参数 nWidth :设置以逻辑单位衡量的线宽,如果 nWidth为 0 ,则设备自动将画笔设置为一个像素宽,而不管当前的映射方式。

参数 crColor:设置画笔的颜色,其颜色通过 RGB宏来确定:

COLORREF RGB(cRed,cGreen,CBlue);参数 cRed 、 cGreen 、 CBlue 分别指定红、绿、蓝 3 色

的相对亮度,每个参数均可以被赋予 0 到 255 之间的值。

8.2 绘图设备类

Page 16: 第 8 章 图形图像处理

16返回返回

8.2.2.2 在设备环境中选入画笔已创建的画笔可以利用 CDC 类对象的成员函数 SelectO

bject 将其选入到当前设备环境中,如:void OnDraw(CDC * pDC){CPen pen(PS_SOLID,1,RGB(255,0,0));CPen * pOldPen=pDC->SelectObject(&pen);……// 省略各种绘制操作代码pDC->SelectObject(pOldPen);}

8.2 绘图设备类

Page 17: 第 8 章 图形图像处理

17返回返回

8.2.3 CBrush 类CBrush 类是 CGdiObject 类的一个派生类,它封装了 Win

dows 图形设备界面( GDI )中有关画刷的操作。 CBrush 类的用法与 CPen 类似。

8.2 绘图设备类

Page 18: 第 8 章 图形图像处理

18返回返回

8.2.3.1 创建 CBrush 对象利用 CBrush 类的构造函数可创建 Cbrush 对象。1. 实心画刷用实心画刷进行图形填充时,以这种画刷的颜色实心填充。其创建方法

如下:( 1 )定义 CBrush 对象,用函数 CreateSolidBrush 对对象进行初始化。

   CBrush brush;   brush.CreateSolidBrush(RGB(255,0,0));( 2 )定义 CBrush 类对象,并利用构造函数对对象的参数进行初始化。   CBrush   brush(RGB(255,0,0));( 3 )动态创建。用这种方法定义时,在操作完成后要删除创建的 CBr

ush 对象。   CBrush *brush;   Brush=new CBrush(RGB(255,0,0));  ……   delete brush;

8.2 绘图设备类

Page 19: 第 8 章 图形图像处理

19返回返回

2. 影线画刷影线画刷不是用画刷的颜色实心填充图形,而是用不同

的阴影图案来填充,填充方式如下表。影 线 风 格

HS_BDIACONAL 建立一个 45° 网格线的画刷(从右向左)

HS_CROSS 建立一个水平和垂直交叉网格线的画刷

HS_DIAGCROSS 建立一个两条 45° 垂直交叉网格线的画刷

HS_FDIAGONAL 建立一个 45° 网格线的画刷(从左向右)

HS_HORIZONTAL 建立一个水平网格线的画刷

HS_VERTICAL 建立一个垂直网格线的画刷

8.2 绘图设备类

Page 20: 第 8 章 图形图像处理

20返回返回

影线画刷的创建方法同实心画刷一样:( 1 )定义对象,用函数初始化。如:CBrush brush;brush.CreateSolidBrush(PS_SOLID,RGB(255,0,0));( 2 )一次性创建。如:CBrush brush ( HS_HORIZONTAL,RGB(255,0,0) ) ;( 3 )动态创建。如:用这种方法创建的 CBrush 对象,在操作完成后要删除 CBr

ush 对象。CBrush * brush;Brush=new CBrush(HS_HORIZONTAL,RGB(255,0,0));……delete brush;

8.2 绘图设备类

Page 21: 第 8 章 图形图像处理

21返回返回

3. 位图画刷位图画刷是用位图图像来填充图形的。函数 CreatPatter

nBrush 用来初始化一个位图画刷。以下代码创建一个位图画刷(其中, pBitmap 指向一个位图对象):

CBrush brush;brush.CreatPatternBrush(pBitmap);

8.2 绘图设备类

Page 22: 第 8 章 图形图像处理

22返回返回

8.2.3.2 在设备环境中选入画刷在设备环境中选入画刷,即 CBrush 对象的操作是与选入

画笔的操作相同的。如:void OnDraw(CDC * pDC){CBrush brush(HS_CROSS,RGB(255,0,0)); CBrush* pOldBrush=Pdc->SelectObject(&brush);……// 省略以下的绘制操作pDC->SelectObject(pOldBrush);}

8.2 绘图设备类

Page 23: 第 8 章 图形图像处理

23返回返回

8.2.4 CFont 类及创建 CFont 类对象的方法CFont 类是 CGdiObject 类的一个派生类,它封装了逻辑

字体及方法。8.2.4.1 创建 CFont 对象CFont 类只有一个构造函数,在定义了一个 CFont 类对

象之后,必须用成员函数 CreateFont或 CreateFontIndirect来初始化 CFont 对象的参数。

CreateFont 函数的参数非常多 , 可查阅MSDN 。

8.2 绘图设备类

Page 24: 第 8 章 图形图像处理

24返回返回

8.2.4.2 在设备环境中选入字体下面介绍创建 CFont 对象和在设备环境中选入字体的过

程。 void CDrawView::OnDraw(CDC * pDC){Cfont   font;font.CreateFont(30,15,0,0,200,0,0,0,255,0,0,2,DEFAUL

T_PITCH,”VC”);CFont* pOldFont= pDC->SelectObject(&font); ……// 省略进行文字绘制的部分pDC->SelectObject(pOldFont);}

8.2 绘图设备类

Page 25: 第 8 章 图形图像处理

25返回返回

8.2.5 CBitmap 类和 Cpen 、 CBrush 类一样, CBitmap 类是 CGdiObject 类的派生类,它封装

了使用 Windows GDI 进行图形绘制中关于位图的操作。在 CBitmap 类中重载了两个 LoadBitmap 函数,用于加载位图资源:( 1 )通过资源的 ID号加载一个位图资源。其定义如下:BOOL LoadBitmap(UINT nIDResource);( 2 ) LoadBitmap 的另一种形式用于加载位图文件资源,如:CString m_str;CBitmap m_bitmap;……CString sFilter=”Bitmap Files(* .bmp)|*.bmp||”;CFileDialog m_Dlg(TRUE,NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,(LPCTSTR)sFilter,NULL);m_Dlg.DoModal( );m_str=m_Dlg.GetPathName( );m_Bitmap.LoadBitmap(_T(m_str));也可以使用位图文件的绝对路径作为参数直接调用位图文件。

8.2 绘图设备类

Page 26: 第 8 章 图形图像处理

26返回返回

在 Visual C++ 6.0 中进行 Windows 图形应用程序设计时,可以采用多种不同的坐标映射方式,即不同的坐标系。

8.3.1 Windows 映像方式及其设置方法8.3.1.1 Windows 映像方式 Windows 映像方式就是 Windows 下的逻辑坐标方式。

一个实际物理屏幕是由像素组成的。 为了方便各种情况下的程序开发和减轻程序开发的负担,

Windows 提供了几种映像方式,每一种映像方式提供不同的测量单位和坐标原点。详见下表:

8.3 坐标映射方式

Page 27: 第 8 章 图形图像处理

27返回返回

映像方式 映像识别码 逻辑单位 X 和 Y 轴正向

MM_TEXT 1 Pixels 右下MM_LOMETRIC 2 0.1mm 右上

MM_HIMETRIC 3 0.01mm 右上MM_LOENGLISH 4 0.1inch 右上MM_HIENGLISH 5 0.01inch 右上

MM_TWIPS 6 1/1440inch 右上MM_ISOTROPIC 7 可变( x 等 于

y) 变化的MM_ANISOTROPIC 8 可变( x 不等

于 y) 变化的

8.3 坐标映射方式

Page 28: 第 8 章 图形图像处理

28返回返回

8.3.1.2 Windows 映像方式的设置方法在 MFC 应用程序中,通过调用 CDC 类的 SetMapMode

() 函数来设置映像方式。如:pDC->SetMapMode(n);其中, n 是在上表中列出的映像方式的识别码。该函数的原型为:virtual int SetMapMode( int nMapMode );

8.3 坐标映射方式

Page 29: 第 8 章 图形图像处理

29返回返回

8.3.2 逻辑坐标和设备坐标的转换所谓设备坐标是针对屏幕或其他显示设备而言的。以屏

幕为例,其原点在屏幕上的左上角; X轴的正方向向右; Y轴的正方向向下;坐标单位为像素。

而逻辑坐标是在内存中虚拟的一个坐标系,其原点在屏幕的左上角, X轴的正方向向右, Y轴的正方向向上,其单位随着映像方式的不同而改变。

8.3 坐标映射方式

Page 30: 第 8 章 图形图像处理

30返回返回

8.3.2.1 设备无关性Windows系统提供了坐标映像方式,并实现了设备无关

性。所谓设备无关性指的是只要设定了映像方式,那么就会在不同的设备上显示出同样大小的图形。

对于 MM_TEXT 映像方式来说,因为其单位是像素且长度不固定(即一个像素所占的实际长度随着设备的不同而不同),所以,在不同的显示和输出设备上不能保证其图形的大小一样。

8.3 坐标映射方式

Page 31: 第 8 章 图形图像处理

31返回返回

8.3.2.2 逻辑坐标和像素的转换方法为了完成在各种映像方式下逻辑坐标和设备坐标的转换, VC 中提供了两个成员函数:

DPtoLP(LPPOINT lpPoints); // 实现从设备坐标转换到逻辑坐标LPtoDP(LPPOINT lpPoints); // 实现从逻辑坐标转换到设备坐标如:CPoint point;point.x=50;point.y=50; // 给点 point赋一坐标值 PDC->DPtoLP(&point) //将点 point从设备坐标转换成逻辑坐标( 1 )大多数的 CDC 类的成员函数要以逻辑坐标作为参数。( 2 ) CWnd 类的成员函数要以设备坐标作为参数。( 3 )所有选中测试操作和区域的定义要以设备坐标来表示。( 4 )将一些长期使用的坐标值用逻辑坐标来保存。

8.3 坐标映射方式

Page 32: 第 8 章 图形图像处理

32返回返回

8.4 窗口和视口 8.4.1 窗口和视口的概念 窗口指的是虚拟存在的一个屏幕,而视口指的是在屏幕

上看到的视图客户区域。在 Windows 中绘制图形时,并不是把图形直接绘制到屏幕上,而是以各种映像方式下的逻辑坐标系将图形绘制到虚拟的窗口中,然后再将这个窗口中的内容映像到视口中。如果是映像到屏幕上就实现了图形的显示;如果是映像到打印机等输出设备上就实现了图形的打印输出。

因此,窗口原点、视口原点和坐标系中的原点 3者的概念是不同的。窗口原点和视口原点指的是同一个点在窗口逻辑坐标和视口设备坐标系的坐标值,它决定了图形由窗口映射到视口时的相对位置。

Page 33: 第 8 章 图形图像处理

33返回返回

8.4.2 窗口和视口有关的操作函数在 CWnd 类中与窗口和视口有关的操作函数如下:1. SetWindowOrg 函数SetWindowOrg 函数用来设置一个与设备环境有关的窗

口原点。 CPoint SetWindowOrg(int x,int y); CPoint SetWindowOrg(POINT point);2. SetViewportOrg 函数SetViewportOrg 函数用来设置一个与设备环境有关的视

口原点。 CPoint SetViewportOrg(int x,int y); CPoint SetViewportOgr(POINT point);

8.4 窗口和视口

Page 34: 第 8 章 图形图像处理

34返回返回

3. SetWindowExt 函数SetWindowExt 函数用来设置与设备环境有关的窗口在 x和 y方向

的幅度。只有在 MM_ISOTROPIC 映像方式下该函数才有效。 virtual CSize SetWindowExt(int cx,int cy); virtual CSize SetWindowExt(SIZE size);4. SetViewportExt 函数SetViewportExt 函数用来设置与设备环境有关的视口在 x和 y方向

的幅度。只有在 MM_ISOTROPIC 映像方式下该函数才有效。 virtual CSize SetViewporExt(int cx,int cy); virtual CSize SetViewporExt(SIZE size);

必须注意,在 MM_ISOTROPIC 映像方式下,必须先设置窗口幅度,再设置视口幅度。

8.4 窗口和视口

Page 35: 第 8 章 图形图像处理

35返回返回

8.4.3 窗口逻辑坐标和视口设备坐标的转换窗口和视口的作用是为了实现设备无关性。8.4.3.1 逻辑坐标和设备坐标的转换方法假定一个点在窗口逻辑坐标为( x1,y1 ) , 在视口设备像

素坐标为( x2,y2 ) , 在两个坐标系 Y轴同向的情况下,根据在窗口和视口中这个点到原点的距离相等,则有如下转换关系:

(x1-a1)=(x2-a2)*n (y1-b1)=(y2-b2)*n在两个坐标系 Y 轴反向的情况下,则有如下的转换关系: (x1-a1)=(x2-a2)*n (y1-b1)=-(y2-b2)*n

8.4 窗口和视口

Page 36: 第 8 章 图形图像处理

36返回返回

8.4.3.2 MM_TEXT 映像方式的坐标转换在 MM_TEXT 映像方式下,因为在窗口和视口中都采用

像素坐标,所以 n 等于 1 。依据以上讨论的坐标转换公式可得到窗口逻辑坐标到视口设备坐标的转换关系:

x2=x1-a1+a2;y2=y1-b1+b2;同样,可以得到视口设备坐标到窗口逻辑坐标的转换公

式:x1=x2+a1-a2;y1=y2+b1-b2;

8.4 窗口和视口

Page 37: 第 8 章 图形图像处理

37返回返回

8.4.3.3 MM_LOMETRIC 等 4 种映像方式下的坐标转换这 4 种坐标映像方式除了逻辑坐标单位不一样外,其他

方面都一样,现在就以 MM_LOMETRIC 映像方式为例,讨论这 4 种映像方式下的坐标转换问题。

因为 MM__LOMETRIC 映像方式逻辑坐标与设备坐标 Y轴反向,所以得到逻辑坐标到设备坐标的转换公式为:

x2=(x1-a1)/n+a2;y2=-(y1-b1)/n+b2;在 MM_LOEMTRIC 等 4 种映像方式下,虽然移动窗口原

点和视口原点都可以达到移动图形的目的,但移动量是不一样的。移动窗口原点时,移动量是以逻辑坐标为单位的;而移动视口原点时,移动量是以设备坐标(像素)为单位的。

8.4 窗口和视口

Page 38: 第 8 章 图形图像处理

38返回返回

8.4.3.4 MM_ISOTROPIC 和 MM_ANISOTROPIC 映 像方式的坐标转换

在这两种映像方式下,映像后图形的大小要发生变化,视口中的坐标也不再以像素为单位,而窗口中的逻辑坐标则是以像素为单位。

在 MM_ISOTROPIC 映像方式下, x和 y 两方向同比例缩放,而在 MM_ANISOTROPIC 映像方式下,允许两方向不同比例放缩。

8.4 窗口和视口

Page 39: 第 8 章 图形图像处理

39返回返回

8.5 设置绘图模式 绘图模式指定了画笔颜色和被填充物体内部颜色

是如何与显示平面的颜色相混合的。绘图模式只能应用于光栅类设备,而不能用于矢量设备。

设置绘图模式是利用 CDC 类的成员函数 SetROP2来完成的,该函数的原型为:

int SetROP2( int nDrawMode );其中:参数 nDrawMode表示新的绘图模式,该

函数的返回值是原先的绘图模式。能够采用的绘图模式如下表。

Page 40: 第 8 章 图形图像处理

40返回返回

绘图模式取值 含 义R2_BLACK 像素总是黑色R2_WHITE 像素总是白色R2_NOP 像素颜色保持不变R2_NOT 像素颜色为屏幕颜色的反色R2_COPYPEN 像素颜色为画笔的颜色R2_NOTCOPYPEN 像素颜色为画笔颜色的反色R2_MERGEPENNOT

像素颜色是画笔的颜色与屏幕颜色反色的组合R2_MASKPENNOT 像素颜色是画笔的颜色与屏幕颜色的反色中共有颜色的组合R2_MERGENOTPEN

像素颜色是屏幕颜色和画笔颜色的反色的组合R2_MASKNOTPEN 像素颜色是屏幕颜色和画笔颜色的反色中共有颜色的组合R2_MERGEPEN 像素颜色是屏幕颜色与画笔颜色的组合R2_NOTMERGEPEN

像素颜色是屏幕颜色和画笔颜色的组合颜色的组合R2_MASKPEN 像素颜色是画笔颜色和屏幕颜色中共有的颜色的组合R2_NOTMASKPEN 像素颜色是画笔颜色和屏幕颜色中共有的颜色的组合颜色的反色

R2_XORPEN 像素颜色是既属于画笔颜色又属于屏幕颜色,但并不是两种颜色的公共部分的组合颜色

R2_NOTXORPEN 像素颜色是既属于画笔颜色又属于屏幕颜色,但并不是两种颜色的公共部分的组合颜色的反色

Page 41: 第 8 章 图形图像处理

41返回返回

8.6 图形元素的绘制所谓图形元素主要是指点、直线、曲线和文字等。在 Visual C++ 的

MFC 的设备环境类 CDC 中提供了相应的成员函数来完成这些基本图形元素的绘制工作。

8.6.1 画点利用 CDC 类的成员函数 SetPixel来完成点的绘制工作,该函数的原型为:

COLORREF SetPixel( int x, int y, COLORREF crColor );COLORREF SetPixel( POINT point, COLORREF crColor );其中,参数 x、 y及 point均表示逻辑坐标系下所要绘制的点的坐

标值,参数 crColor表示要绘制的点的颜色。该函数的返回值为实际绘制点的 RGB 颜色值。

Page 42: 第 8 章 图形图像处理

42返回返回

8.6.2 画直线利用 CDC 类的成员函数 LineTo来完成直线的绘制工作,该函数的原型为:

BOOL LineTo( int x, int y );BOOL LineTo( POINT point );其中,参数 x、 y和 point 是指要画直线的终点端点坐标值。如果

绘制直线成功,则该函数返回非零值;否则,返回 0 。 该函数的功能是从当前点为直线的起始点、以( x,y)或 point为终

点画一条直线。还有一个与画线有关的 CDC 类的成员函数 MoveTo ,该函数的原型为:

CPoint MoveTo( int x, int y );CPoint MoveTo( POINT point );

8.6 图形元素的绘制

Page 43: 第 8 章 图形图像处理

43返回返回

8.6.3 画矩形利用 CDC 类的成员函数 Rectangle来完成矩形的绘制工

作,该函数的原型为:BOOL Rectangle( int x1, int y1, int x2, int y2 );BOOL Rectangle( LPCRECT lpRect );其中,参数 x1 、 y1 是要绘制的矩形左上角的坐标, x2 、y2 是矩形右下角的坐标。参数 lpRect 指定要绘制的矩形区域。

8.6 图形元素的绘制

Page 44: 第 8 章 图形图像处理

44返回返回

8.6.4 画圆角矩形利用 CDC 类的成员函数 RoundRect来完成圆角矩形的绘制工作,

该函数的原型为:BOOL RoundRect( int x1, int y1, int x2, int y2, int x3, int y3 );BOOL RoundRect( LPCRECT lpRect, POINT point );其中,参数 x1 、 y1 指定圆角矩形左上角的坐标,参数 x2 、 y2 指

定圆角矩形右下角的坐标, x3表示用来画圆角的椭圆的宽度, y3表示该椭圆的高度。

8.6.5 画扇形利用 CDC 类的成员函数 Pie来完成扇形的绘制工作,该函数的原型为:

BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd );各参数的含义可参见圆角矩形。

8.6 图形元素的绘制

Page 45: 第 8 章 图形图像处理

45返回返回

  8.6.6 画多边形利用 CDC 类的成员函数 Polygon来完成多边形的绘制工作,该函数

的原型为:BOOL Polygon( LPPOINT lpPoints, int nCount );其中,参数 lpPoints 是一个指向多边形各顶点坐标的矩阵,参数 n

Count表示多边形的顶点总数。8.6.7 绘制文本利用 CDC 类的成员函数 TextOut 可完成文字的绘制输出工作,该函

数的原型为:virtual BOOL TextOut( int x, int y, LPCTSTR lpszString, int nCoun

t );BOOL TextOut( int x, int y, const CString& str );其中,参数 x、 y 表示输出文字的起始坐标位置, lpszString或 str表示要输出的文字, nCount表示输出 lpszString 所指出的字符串中的字符个数。

8.6 图形元素的绘制

Page 46: 第 8 章 图形图像处理

46返回返回

与文字的输出有关系的 CDC 类的成员函数还有:输出文字:virtual int DrawText( LPCTSTR lpszString, int nCount, LPRECT lp

Rect, UINT nFormat ); int DrawText( const CString& str, LPRECT lpRect, UINT nFormat

); 设置文字输出的颜色 :virtual COLORREF SetTextColor( COLORREF crColor );设置文字的对齐方式 :UINT SetTextAlign( UINT nFlags );设置文字间输出的间隙 :int SetTextCharacterExtra( int nCharExtra );

8.6 图形元素的绘制

Page 47: 第 8 章 图形图像处理

47返回返回

8.7 在视图中交互绘图 本例的基本思想是:首先创建一个 SDI 应用程序,当程序运行时,把鼠标指针移动到窗口客户区中,则鼠标光标的形状呈十字形,当按下鼠标左键并在视图窗口中拖动到另外一点时放开鼠标,则可以在按下鼠标的位置到放开鼠标时的位置间画一条直线。

步骤 1:启动 Visual C++ 6.0 。步骤 2:创建一个单文档的应用程序框架。步骤 3:在视图类中添加 4 个成员变量,它们分别是:m_Drag变量,是一个标志变量,用于表示目前用户是否正在拖动鼠标。

m_Cursor变量,用于存放鼠标光标形状的句柄。m_StartPoint变量,用于记录当用户按鼠标左键时的光标所在位置

的坐标。m_OldPoint变量,用于存放光标的当前位置。

Page 48: 第 8 章 图形图像处理

48返回返回

步骤 4:在视图类的构造函数中加入以下代码来对其成员变量m_Drag 和 m_Cursor 进行初始化。

CDrawView::CDrawView(){// TODO: add construction code herem_Drag=0;m_Cursor=AfxGetApp()->LoadStandardCursor(IDC_CROSS);

}步骤 5:利用 ClassWizard 向导向视图类 CDrawView 中添加消息

处理函数。在此,需要处理的 3 个消息是:按下鼠标时的 WM_LBUTTONDOWN 消息、移动鼠标时的 WM_MOUSEMOVE消息和放开鼠标时的 WM_LBUTTONUP 消息。

8.7 在视图中交互绘图

Page 49: 第 8 章 图形图像处理

49返回返回

步骤 5:对消息 WM_LBUTTONDOWN 进行消息映射并编写消息处理函数的代码,如下所示:

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) {

m_StartPoint=point;m_OldPoint=point;SetCapture();m_Drag=1;RECT Rect;GetClientRect(&Rect);ClientToScreen(&Rect);::ClipCursor(&Rect);CView::OnLButtonDown(nFlags, point);

}

8.7 在视图中交互绘图

Page 50: 第 8 章 图形图像处理

50返回返回

步骤 6:按步骤五的方法向 OnMouseMove() 函数中添加对鼠标消息 WM_MOUSEMOVE的处理,代码如下:

void CDrawView::OnMouseMove(UINT nFlags, CPoint point) {

::SetCursor(m_Cursor);if(m_Drag){

CClientDC mydc(this);mydc.SetROP2(R2_NOT);mydc.MoveTo(m_StartPoint);mydc.LineTo(m_OldPoint);mydc.MoveTo(m_StartPoint);mydc.LineTo(point);m_OldPoint=point;

}CView::OnMouseMove(nFlags, point);

}

8.7 在视图中交互绘图

Page 51: 第 8 章 图形图像处理

51返回返回

步骤 7:按步骤 5 的方法向 OnMouseUp() 函数中添加对鼠标消息 WM_LBUTTONUP 的处理,代码如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) {

if(m_Drag){

m_Drag=0;::ReleaseCapture();::ClipCursor(NULL);CClientDC thedc(this);thedc.SetROP2(R2_NOT);thedc.MoveTo(m_StartPoint);thedc.LineTo(m_OldPoint);thedc.SetROP2(R2_COPYPEN);thedc.MoveTo(m_StartPoint);thedc.LineTo(point);

}CView::OnLButtonUp(nFlags, point);

}

8.7 在视图中交互绘图

Page 52: 第 8 章 图形图像处理

52返回返回

步骤 8 :编译并运行此程序,可见,当鼠标在客户区中时,鼠标光标呈十字形状,拖动鼠标可画直线。

8.7 在视图中交互绘图

Page 53: 第 8 章 图形图像处理

53返回返回

本章小结本章主要介绍了以下内容:1. 设备环境( DC )的概念及常用的的几个设备环境类

如 CPaintDC 、 CClientDC 、 CWindowDC 和 CMetaFileDC 类的主要特点及它们在使用方法上的区别。

2. 绘图设备类( GDI )的概念及常用的绘图设备类如 CGdiObject 、 CPen 、 CBrush 、 Cfont 和 CBitmap等的对象的创建和引入到设备环境中的方法。

3. Windows 下的坐标映像方式、设备方法及几种不同的坐标映像方式下的坐标转换方法。

  4. 几种常见的基本图形元素如点、直线、矩形和文字等的绘制方式及相应的 CDC 类的绘图函数。

Page 54: 第 8 章 图形图像处理

54返回返回