| |
WindowsGDI和GDI+编程实例剖析 |
|
时间: 2005-11-11 来自:天极网 |
 |
|
|
3.GDI编程
"GDI"菜单下的"画线"子菜单单击事件消息处理函数的代码如下:
void CGdiexampleDlg::OnGdiDrawLine() { // TODO: Add your command handler code here CClientDC dc(this); //逻辑坐标与设备坐标变换 CRect rect; GetClientRect(&rect); dc.SetMapMode(MM_ANISOTROPIC); dc.SetWindowOrg(0, 0); dc.SetWindowExt(rect.right, rect.bottom); dc.SetViewportOrg(0, rect.bottom / 2); dc.SetViewportExt(rect.right, - rect.bottom); //创建绘制正旋曲线的pen并将其选入设备上下文 CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); HGDIOBJ oldObject = dc.SelectObject(pen.GetSafeHandle()); //绘制正旋曲线 dc.MoveTo(0, 0); for (int i = 0; i < rect.right; i++) { dc.LineTo(i, 100 *sin(2 *(i / (rect.right / 5.0)) *PI)); } //创建绘制x轴的pen并将其选入设备上下文 CPen penx(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(penx.GetSafeHandle()); //绘制X轴 dc.MoveTo(0, 0); dc.LineTo(rect.right, 0); //恢复原先的pen dc.SelectObject(oldObject); } | 单击这个按钮,会出现如图1所示的效果,我们来对此进行解读。
 图1 绘制正旋曲线 | 前文提到,GDI编程需进行设备坐标和逻辑坐标的转化。而屏幕上的设备坐标通常会按客户坐标给出,客户坐标依赖于窗口的客户区域,其起始位置位于客户区域的左上角。为示区别,图2给出了设备坐标和用户逻辑坐标的示例。
 图2 设备坐标与逻辑坐标 | 设备坐标与逻辑坐标的转换关系如下:

 公式中的<Xvorg, Yvorg>是设备空间中视口的原点,而< Xworg, Yworg >是逻辑空间中窗口的原点。 Xwext/Xvext和Ywext/Yvext分别是窗口与视口水平和垂直范围的比例。
因此,经过程序中的dc.SetWindowOrg (0,0) 和dc.SetViewportOrg (0,rect.bottom/2)语句我们设置了视口和窗口的原点;而经过程序中的dc.SetWindowExt (rect.right,rect.bottom) 和dc.SetViewportExt (rect.right,-rect.bottom) 语句我们设置了视口和窗口的范围。由于视口和窗口的纵坐标方向相反,设置视口的垂直范围为负值。这样我们得到了一个逻辑坐标原点为客户区水平方向最左边和垂直方向居中的坐标系,我们在这个坐标系上直接绘制正旋曲线,不需要再理睬Windows对话框客户区坐标了。
void CGdiexampleDlg::OnGdiDrawLine()函数中未指定逻辑设备和物理设备的映射模式,则为缺省的MM_TEXT。在这种模式下,一个逻辑单位对应于一个像素点。映射模式是GDI中的一个重要概念,其它的映射模式还有MM_LOENGLlSH、MM_HIENGLISH、MM_LOMETRIC和MM_HIMETRIC等。我们可以通过如下语句指定映射模式为MM_TEXT:
值得一提的是,从上述代码可以看出:在GDI编程中,几乎所有的操作都围绕设备上下文dc展开。的确,这正是GDI编程的特点!设备上下文是Windows 使用的一种结构,所有GDI操作前都需取得特定设备的上下文,函数中的CClientDC dc (this) 语句完成这一功能。
归纳可得,利用GDI进行图形、图像处理的一般操作步骤为:
1. 取得指定窗口的DC;
2. 确定使用的坐标系及映射方式;
3. 进行图形、图像或文字处理;
4. 释放所使用的DC。
4.GDI+编程
"GDI+"菜单下的"画线"子菜单单击事件消息处理函数的代码如下:
void CGdiexampleDlg::OnGdipDrawLine() { // TODO: Add your command handler code here CClientDC dc(this); //逻辑坐标与设备坐标变换 CRect rect; GetClientRect(&rect); dc.SetMapMode(MM_ANISOTROPIC); dc.SetWindowOrg(0, 0); dc.SetWindowExt(rect.right, rect.bottom); dc.SetViewportOrg(0, rect.bottom / 2); dc.SetViewportExt(rect.right, - rect.bottom);
//创建Graphics对象 Graphics graphics(dc); //创建pen Pen myPen(Color::Red); myPen.SetWidth(1); //画正旋曲线 for (int i = 0; i < rect.right; i++) { graphics.DrawLine(&myPen, i, 100 *sin(2 *(i / (rect.right / 5.0)) *PI), i + 1, 100 *sin(2 *((i + 1) / (rect.right / 5.0)) *PI)); } //画X轴 myPen.SetColor(Color::Blue); graphics.DrawLine(&myPen, 0, 0, rect.right, 0); } | 由于我们使用的是Visual C++6.0而非VS.Net,我们需要下载微软的GDIPLUS支持包。在微软官方网站下载时需认证Windows为正版,我们可从这个地址下载:http://www.codeguru.com/code/legacy/gdi/GDIPlus.zip。一个完整的GDI+支持包至少包括如下文件:
(1)头文件:gdiplus.h
(2)动态链接库的.lib文件:gdiplus.lib
(3)动态链接库的.dll文件:gdiplus.dll
少了(1)、(2)程序不能编译,少了(3)程序能以共享DLL的方式编译但是不能运行,运行时找不到.dll文件。
为使得Visual C++6.0支持GDI+,我们需要在使用GDI+对象的文件的开头添加如下代码:
#define UNICODE #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #endif #include "c:\gdiplus\includes\gdiplus.h" using namespace Gdiplus; #pragma comment(lib, "c:\\gdiplus\\lib\\gdiplus.lib") | 在Visual C++中使用GDI+必须先进行GDI+的初始化,我们在CWinApp派生类的InitInstance函数中进行此项工作是最好的:
///////////////////////////////////////////////////////////////////////////// // CGdiexampleApp initialization
BOOL CGdiexampleApp::InitInstance() { AfxEnableControlContainer();
// Standard initialization
#ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif
//初始化gdiplus的环境 GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; // 初始化GDI+. GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CGdiexampleDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK){} else if (nResponse == IDCANCEL){}
//关闭gdiplus的环境 GdiplusShutdown(gdiplusToken);
return FALSE; } | 单击"GDI+"菜单下的"画线"子菜单,也会出现如图1所示的效果。观察void CGdiexampleDlg::OnGdipDrawLine() 函数,我们发现用GDI+进行图形、图像操作的步骤为:
(1)创建 Graphics 对象:Graphics 对象表示GDI+绘图表面,是用于创建图形图像的对象;
(2)使用 Graphics 对象绘制线条和形状、呈现文本或显示与操作图像。
Graphics 对象是GDI+的核心,GDI中设备上下文dc和Graphics 对象的作用相似,但在GDI中使用的是基于句柄的编程模式,而GDI+中使用的则是基于对象的编程模式。Graphics封装了GDI+ 绘图面,而且此类无法被继承,它的所有成员函数都不是虚函数。
下面,我们来逐个用实际代码实现GDI+的新增功能,这些新增功能包括:渐变的画刷(Gradient Brushes)、基数样条函数(Cardinal Splines)、持久的路径对象(Persistent Path Objects)、变形和矩阵对象(Transformations &Matrix Object)、可伸缩区域(Scalable Regions)、Alpha混合(Alpha Blending)和丰富的图像格式支持等。
|
|
|
|
|
|
|
|