刘宏才 深圳杰出青年:基于VC++的GDI常用坐标系统及应用 (4)
来源:百度文库 编辑:偶看新闻 时间:2024/05/10 08:14:34
四、自定义坐标系统 目前为止,我们使用的映射模式可以允许我们选择坐标轴的方向,但仅仅是Y轴的方向。而且,我们不能更改坐标系统的单位,这是因为各种映射模式(MM_TEXT, MM_HIENGLISH, MM_LOENGLISH, MM_HIMETRIC, MM_LOMETRIC, and MM_TWIPS)有固定的属性集,例如坐标轴的方向和坐标单位等。在CAD应用程序中,如果你需要灵活设置坐标轴方向及坐标单位的话,应该怎么做呢? 仔细研究下面的OnPaint()事件代码,它绘制了一个200X200像素大小的红边、浅绿色背景的正方形,这个正方形的顶点在(-100,-100)处,右底端位于(100,100)处。同时,从坐标原点处绘制一个45度的直线。 void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图十七、代码效果图 正如你所看到的,我们只得到了正方形的右下部分,同时直线指向时钟的三点到六点之间的方向。假定你想将坐标原点设置与窗口中央位置,或者是更精确一点,设置于点(340, 220)处,我们已经知道可以使用CDC::SetViewportOrg()(记住,这个函数只用来更改坐标原点,它并不影响坐标轴的方向及坐标单位。同时,需要注意的是,它使用的坐标单位是像素)函数,下面是一个例子(我们没有规定映射模式,所以程序使用的是默认的MM_TEXT映射模式)。 void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetViewportOrg(340, 220); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图十八、代码效果图 为了控制你自己应用程序中的坐标系统单位,坐标轴的方向,可以使用MM_ISOTROPIC 或MM_ANISOTROPIC映射模式。第一件事是调用CDC::SetMapMode()函数,并在两个常量中选择一个(MM_ISOTROPIC或 MM_ANISOTROPIC)。下面是例子代码:
void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetMapMode(MM_ISOTROPIC); dc.SetViewportOrg(340, 220); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图十九、代码效果图 先抛开上面的图片。当调用CDC::SetMapMode(),并使用MM_ISOTROPIC或 MM_ANISOTROPIC作为参数后,并没有结束,这两种映射方式允许我们改变坐标轴的正方向及坐标单位。这两种映射方式的区别在于:MM_ISOTROPIC映射方式中水平、垂直坐标轴的单位相等,MM_ANISOTROPIC映射方式可以随意控制水平及垂直方向的坐标单位长度。 所以,在调用SetMapMode()函数并规定了MM_ISOTROPIC或MM_ANISOTROPIC映射模式后,你必须调用CDC:SetWindowExt()函数,这个函数用来计算老的或默认的坐标系中一个单位的长度。这个函数有两个版本: CSize SetWindowExt(int cx, int cy); CSize SetWindowExt(SIZE size); 如果使用第一版本,第一个参数CX说明了水平坐标轴上按照新的逻辑单位代表的长度,CY代表了垂直坐标轴上按照新的逻辑单位代表的长度。 如果你知道按照新的坐标单位计算需要的逻辑尺寸的话,可以使用第二个版本的函数,例子代码如下: void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetMapMode(MM_ISOTROPIC); dc.SetViewportOrg(340, 220); dc.SetWindowExt(480, 480); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图二十、代码效果图 调用SetWindowExt()函数后,紧接着应调用SetViewportExt()函数,它的任务是规定水平及垂直坐标轴的单位。我们可以这样认为,SetWindowExt()函数对应着“窗口”,SetViewportExt()函数对应着“视口”。SetViewportExt()函数有两个版本: CSize SetViewportExt(int cx, int cy); CSize SetViewportExt(SIZE size); 上述两个函数中的参数与“窗口”中的尺寸是相互对应的,它的单位是像素。为了进一步说明这两个函数的使用,我对这两个函数进行了重新说明: SetWindowExt(int Lwidth, int Lheight) //参数的单位为逻辑单位(Logical); SetViewportExt(int Pwidth, int Pheight) //参数的单位为像素(Pixel); 以x轴为例(y轴类似),逻辑坐标系中的x轴的单位刻度=| Pwidth | / | Lwidth |。这表示x轴上一个逻辑单位等于多少个像素。比如我们先通过GetDeviceCap(LOGPIXELSX)获得在我们的显示器上每英寸等于多少个像素,设为p,然后我们将它赋给Pwidth,将Lwidth赋成2,即Pwidth / Lwidth=p / 2。那么,此时逻辑坐标系x轴上的单位刻度就是p / 2个像素;又由于p个像素是代表一个英寸的,所以此时的逻辑坐标系x轴上的单位刻度同时也是半个英寸。还有一点要注意的是,如果Lwidth与Pwidth同号,逻辑坐标的x轴方向与设备坐标系中的x轴方向相同,否则相反。 此外,当使用MM_ISOTROPIC模式时,如果通过计算window与viewport范围的比值得到两个方向的单位刻度值不同,那么将会以较小的那个为准。 下面是一个例子: void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetMapMode(MM_ISOTROPIC); dc.SetViewportOrg(340, 220); dc.SetWindowExt(480, 480); dc.SetViewportExt(440, -680); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图二十一、代码效果图
图十七、代码效果图 正如你所看到的,我们只得到了正方形的右下部分,同时直线指向时钟的三点到六点之间的方向。假定你想将坐标原点设置与窗口中央位置,或者是更精确一点,设置于点(340, 220)处,我们已经知道可以使用CDC::SetViewportOrg()(记住,这个函数只用来更改坐标原点,它并不影响坐标轴的方向及坐标单位。同时,需要注意的是,它使用的坐标单位是像素)函数,下面是一个例子(我们没有规定映射模式,所以程序使用的是默认的MM_TEXT映射模式)。 void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetViewportOrg(340, 220); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图十八、代码效果图 为了控制你自己应用程序中的坐标系统单位,坐标轴的方向,可以使用MM_ISOTROPIC 或MM_ANISOTROPIC映射模式。第一件事是调用CDC::SetMapMode()函数,并在两个常量中选择一个(MM_ISOTROPIC或 MM_ANISOTROPIC)。下面是例子代码:
void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetMapMode(MM_ISOTROPIC); dc.SetViewportOrg(340, 220); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图十九、代码效果图 先抛开上面的图片。当调用CDC::SetMapMode(),并使用MM_ISOTROPIC或 MM_ANISOTROPIC作为参数后,并没有结束,这两种映射方式允许我们改变坐标轴的正方向及坐标单位。这两种映射方式的区别在于:MM_ISOTROPIC映射方式中水平、垂直坐标轴的单位相等,MM_ANISOTROPIC映射方式可以随意控制水平及垂直方向的坐标单位长度。 所以,在调用SetMapMode()函数并规定了MM_ISOTROPIC或MM_ANISOTROPIC映射模式后,你必须调用CDC:SetWindowExt()函数,这个函数用来计算老的或默认的坐标系中一个单位的长度。这个函数有两个版本: CSize SetWindowExt(int cx, int cy); CSize SetWindowExt(SIZE size); 如果使用第一版本,第一个参数CX说明了水平坐标轴上按照新的逻辑单位代表的长度,CY代表了垂直坐标轴上按照新的逻辑单位代表的长度。 如果你知道按照新的坐标单位计算需要的逻辑尺寸的话,可以使用第二个版本的函数,例子代码如下: void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetMapMode(MM_ISOTROPIC); dc.SetViewportOrg(340, 220); dc.SetWindowExt(480, 480); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图二十、代码效果图 调用SetWindowExt()函数后,紧接着应调用SetViewportExt()函数,它的任务是规定水平及垂直坐标轴的单位。我们可以这样认为,SetWindowExt()函数对应着“窗口”,SetViewportExt()函数对应着“视口”。SetViewportExt()函数有两个版本: CSize SetViewportExt(int cx, int cy); CSize SetViewportExt(SIZE size); 上述两个函数中的参数与“窗口”中的尺寸是相互对应的,它的单位是像素。为了进一步说明这两个函数的使用,我对这两个函数进行了重新说明: SetWindowExt(int Lwidth, int Lheight) //参数的单位为逻辑单位(Logical); SetViewportExt(int Pwidth, int Pheight) //参数的单位为像素(Pixel); 以x轴为例(y轴类似),逻辑坐标系中的x轴的单位刻度=| Pwidth | / | Lwidth |。这表示x轴上一个逻辑单位等于多少个像素。比如我们先通过GetDeviceCap(LOGPIXELSX)获得在我们的显示器上每英寸等于多少个像素,设为p,然后我们将它赋给Pwidth,将Lwidth赋成2,即Pwidth / Lwidth=p / 2。那么,此时逻辑坐标系x轴上的单位刻度就是p / 2个像素;又由于p个像素是代表一个英寸的,所以此时的逻辑坐标系x轴上的单位刻度同时也是半个英寸。还有一点要注意的是,如果Lwidth与Pwidth同号,逻辑坐标的x轴方向与设备坐标系中的x轴方向相同,否则相反。 此外,当使用MM_ISOTROPIC模式时,如果通过计算window与viewport范围的比值得到两个方向的单位刻度值不同,那么将会以较小的那个为准。 下面是一个例子: void CExoDraw1View::OnPaint() { CPaintDC dc(this); // device context for painting dc.SetMapMode(MM_ISOTROPIC); dc.SetViewportOrg(340, 220); dc.SetWindowExt(480, 480); dc.SetViewportExt(440, -680); CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0)); CBrush BrushAqua(RGB(0, 255, 255)); dc.SelectObject(PenRed); dc.SelectObject(BrushAqua); // Draw a square with a red border and an aqua background dc.Rectangle(-100, -100, 100, 100); CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255)); dc.SelectObject(BluePen); // Diagonal line at 45 degrees starting at the origin (0, 0) dc.MoveTo(0, 0); dc.LineTo(200, 200); }
图二十一、代码效果图
3. 参照分布式和企业系统结构、及应用开发的重点明显地转向基于构件的应用开发
VC++开发应用系统的过程
参照分布式和企业系统结构、及应用开发的重点明显地转向基于构件的应用开发,讨论以下问题:
3种常用模具材料的名称,性能及应用
CDMA系统基于RAKE接收机的研究及设计
基于WEB数据库的应用
哪里有免费的毕业论文下载—基于vc的图像处理系统
VC的应用问题
门禁系统的原理及应用、破解
基于VC++的即时串口通信
VC++中基于对话框的编程。
vc中如何将BMP颜色的对比得到坐标系统??
单片机原理及应用中常用芯片的的型号及封装形式?
什么是基于客户机的网络电子地图应用系统?它有哪些主要实现技术?
4. 什么是基于客户机的网络电子地图应用系统?它有哪些主要实现技术
请问谁能够做一个基于uml的彩票销售及管理系统,急
基于delphi的试题库系统
开发商用的基于WEB的应用系统,比较大的.用什么语言开发比较好
在线等!用MFC设计一个基于单文档或对话框的应用系统,帮忙构思一下.
谁有数据库系统及应用的教学大纲啊??
有关“数据库系统及应用”的网页和网站
VC中基于对话框的编程如何改变按钮显示?
VC中基于对话框的编程如何改变按钮显示?
VC中基于对话框的编程如何获得按钮标题?