GDI坐标系统(下)

http://www.functionx.com/visualc/gdi/gdicoord.htm

自定义单位与坐标系

      到目前为止,这些映射模式允许我们设置坐标轴朝向。但我们不能设置单位长度。因为每一种模式(MM_TEXT, MM_HIENGLISH, MM_LOENGLISH, MM_HIMETRIC, MM_LOMETRIC, and MM_TWIPS) 都已经设置好了坐标轴朝向、单位长度等属性。如果你想自定义它们,应该怎么做呢(你使用过AutoCAD么)?

思考事件处理函数OnPaint。它绘制了200x200像素的方形,红色边框,浅绿色背景。为了更好的表示,此函数绘制了一条对角线,起点为原点(0,0)。

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.       
  5.     CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));  
  6.     CBrush BrushAqua(RGB(0, 255, 255));  
  7.   
  8.     dc.SelectObject(PenRed);  
  9.     dc.SelectObject(BrushAqua);  
  10.     // Draw a square with a red border and an aqua background  
  11.     dc.Rectangle(-100, -100, 100, 100);  
  12.   
  13.     CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));  
  14.     dc.SelectObject(BluePen);  
  15.     // Diagonal line at 45 degrees starting at the origin (0, 0)  
  16.     dc.MoveTo(0, 0);  
  17.     dc.LineTo(200, 200);  
  18. }  

如你所见,我们能看见右下角的部分方形。直线在第四象限内。

设想原点(0,0)点位于窗体中心。即将原点放在(340,220)处。你已经会使用CDC::SetViewportOrg()方法来指定原点。请看下面的例子(我们没有指定映射模式,因为MM_TEXT是默认映射模式)

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.       
  5.     dc.SetViewportOrg(340, 220);  
  6.   
  7.     CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));  
  8.     CBrush BrushAqua(RGB(0, 255, 255));  
  9.   
  10.     dc.SelectObject(PenRed);  
  11.     dc.SelectObject(BrushAqua);  
  12.     // Draw a square with a red border and an aqua background  
  13.     dc.Rectangle(-100, -100, 100, 100);  
  14.   
  15.     CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));  
  16.     dc.SelectObject(BluePen);  
  17.     // Diagonal line at 45 degrees starting at the origin (0, 0)  
  18.     dc.MoveTo(0, 0);  
  19.     dc.LineTo(200, 200);  
  20. }  

为了自定义你自己的坐标系,包括坐标轴的朝向和单位长度。可以使用MM_ISOTROPIC或MM_ANISOTROPIC模式。首先,你要调用CDC::SetMapMode()函数来指定其中一个(MM_ISOTROPIC或MM_ANISOTROPIC)。例子如下:

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.       
  5.     dc.SetMapMode(MM_ISOTROPIC);  
  6.     dc.SetViewportOrg(340, 220);  
  7.   
  8.     CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));  
  9.     CBrush BrushAqua(RGB(0, 255, 255));  
  10.   
  11.     dc.SelectObject(PenRed);  
  12.     dc.SelectObject(BrushAqua);  
  13.     // Draw a square with a red border and an aqua background  
  14.     dc.Rectangle(-100, -100, 100, 100);  
  15.   
  16.     CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));  
  17.     dc.SelectObject(BluePen);  
  18.     // Diagonal line at 45 degrees starting at the origin (0, 0)  
  19.     dc.MoveTo(0, 0);  
  20.     dc.LineTo(200, 200);  
  21. }  

    别认为,在传入参数MM_ISOTROPIC或MM_ANISOTROPIC参数调用CDC::SetMapMode()之后,就完毕了,别被上面图骗了。这两个模式的目的是让你控制坐标由的朝向或单位长度。

    两种模式的不同之处在于,当使用MM_ISOTROPIC模式时,水平轴的单位长度与竖直轴的单位长度相等。这里没有列举MM_ANISOTROPIC模式。此模式可使你为水平轴竖直轴设置不同的单位长度。

   所以,在使用MM_ISOTROPIC或MM_ANISOTROPIC参数调用SetMapMode之后,你必须调用函数CDC::SetWindowExt()。此函数决定了新单位长度的多少。新单位长度将与旧的或默认的单位长度相乘。CDC::SetWindowsExt()有两个版本。语法如下:

[cpp]  view plain copy
  1. CSize SetWindowExt(int cx, int cy);  
  2. CSize SetWindowExt(SIZE size);  
   如果使用第一个版本,第一个参数cx指定了水平轴逻辑转化乘子。第二个参数cy 指定了竖直轴逻辑转化乘子。如果你想使用SIZE对角指定逻辑宽和高,便 可以使用第二个版本的函数。(译注:cx,cy应该是指定了缩放框的大小。Windows根据绽放框的大小计算出缩放比例)

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.       
  5.     dc.SetMapMode(MM_ISOTROPIC);  
  6.     dc.SetViewportOrg(340, 220);  
  7.     dc.SetWindowExt(480, 480);  
  8.   
  9.     CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));  
  10.     CBrush BrushAqua(RGB(0, 255, 255));  
  11.   
  12.     dc.SelectObject(PenRed);  
  13.     dc.SelectObject(BrushAqua);  
  14.     // Draw a square with a red border and an aqua background  
  15.     dc.Rectangle(-100, -100, 100, 100);  
  16.   
  17.     CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));  
  18.     dc.SelectObject(BluePen);  
  19.     // Diagonal line at 45 degrees starting at the origin (0, 0)  
  20.     dc.MoveTo(0, 0);  
  21.     dc.LineTo(200, 200);  
  22. }  

      在调用SetWindowExt()函数之后,你可以调用SetViewporExt()函数。它的作用是指定水平轴和竖直轴的单位长度。语法如下:

[cpp]  view plain copy
  1. CSize SetViewportExt(int cx, int cy);  
  2. CSize SetViewportExt(SIZE size);  

为了使用第一个版本的函数,你必须提供水平轴的转化因子cx和竖直轴的转化因子cy。如果你知道高宽比,你可以使用第二个版本的函数。(译注:很明显SetWiewport是视口有关的函数)

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.       
  5.     dc.SetMapMode(MM_ISOTROPIC);  
  6.     dc.SetViewportOrg(340, 220);  
  7.     dc.SetWindowExt(480, 480);  
  8.     dc.SetViewportExt(440, -680);  
  9.   
  10.     CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));  
  11.     CBrush BrushAqua(RGB(0, 255, 255));  
  12.   
  13.     dc.SelectObject(PenRed);  
  14.     dc.SelectObject(BrushAqua);  
  15.     // Draw a square with a red border and an aqua background  
  16.     dc.Rectangle(-100, -100, 100, 100);  
  17.   
  18.     CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));  
  19.     dc.SelectObject(BluePen);  
  20.     // Diagonal line at 45 degrees starting at the origin (0, 0)  
  21.     dc.MoveTo(0, 0);  
  22.     dc.LineTo(200, 200);  
  23. }  

坐标轴箭头例子

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.   
  5.     CBrush bgBrush(BLACK_BRUSH);  
  6.     dc.SelectObject(bgBrush);  
  7.     dc.Rectangle(Recto);  
  8.   
  9.     dc.SetMapMode(MM_ISOTROPIC);  
  10.     dc.SetViewportOrg(0, 440);  
  11.     dc.SetWindowExt(480, 480);  
  12.     dc.SetViewportExt(440, -680);  
  13.   
  14.     CPen PenWhite(PS_SOLID, 1, RGB(255, 255, 255));  
  15.     dc.SelectObject(PenWhite);  
  16.   
  17.     dc.MoveTo(21, 20);  
  18.     dc.LineTo(21, 75);  
  19.     // Up arrow  
  20.     dc.MoveTo(16, 75);  
  21.     dc.LineTo(21, 90);  
  22.     dc.LineTo(26, 75);  
  23.     dc.LineTo(16, 75);  
  24.   
  25.     dc.MoveTo(21, 22);  
  26.     dc.LineTo(75, 22);  
  27.     // Right arrow  
  28.     dc.MoveTo(75, 17);                                
  29.     dc.LineTo(90, 22);  
  30.     dc.LineTo(75, 27);  
  31.     dc.LineTo(75, 17);  
  32.   
  33.     dc.SetBkMode(TRANSPARENT);  
  34.     dc.SetTextColor(RGB(255, 255, 255));  
  35.     dc.TextOut(16, 114, 'Y');  
  36.     dc.TextOut(100, 32, 'X');  
  37.     dc.Rectangle(15, 15, 30, 30);  
  38. }  

绘制线状网格

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.     CRect Recto;  
  5.   
  6.     GetClientRect(&Recto);  
  7.   
  8.     CBrush bgBrush(BLACK_BRUSH);  
  9.     dc.SelectObject(bgBrush);  
  10.     dc.Rectangle(Recto);  
  11.   
  12.     CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));  
  13.     dc.SelectObject(PenBlue);  
  14.   
  15.     for(int x = 0; x < Recto.Width(); x += 20)  
  16.     {  
  17.         dc.MoveTo(x, 0);  
  18.         dc.LineTo(x, Recto.Height());  
  19.     }  
  20.   
  21.     for(int y = 0; y < Recto.Height(); y += 20)  
  22.     {  
  23.         dc.MoveTo(0, y);  
  24.         dc.LineTo(Recto.Width(), y);  
  25.     }  
  26. }  

绘制点状网格

[cpp]  view plain copy
  1. void CExoDraw1View::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.     CRect Recto;  
  5.   
  6.     GetClientRect(&Recto);  
  7.   
  8.     CBrush bgBrush(BLACK_BRUSH);  
  9.     dc.SelectObject(bgBrush);  
  10.     dc.Rectangle(Recto);  
  11.   
  12.     for(int x = 0; x < Recto.Width(); x += 20)  
  13.     {  
  14.         for(int y = 0; y < Recto.Height(); y += 20)  
  15.         {  
  16.         dc.SetPixel(x, y, RGB(255, 255, 255));  
  17.         }  
  18.     }  
  19. }  

绘制正弦曲线

[cpp]  view plain copy
  1. void CExoView::OnPaint()   
  2. {  
  3.     CPaintDC dc(this); // device context for painting  
  4.       
  5.     // TODO: Add your message handler code here  
  6.     dc.SetMapMode(MM_ANISOTROPIC);  
  7.     dc.SetViewportOrg(340, 220);  
  8.     dc.SetWindowExt(1440, 1440);  
  9.     dc.SetViewportExt(-1440, -220);  
  10.   
  11.     CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));  
  12.     dc.SelectObject(PenBlue);  
  13.   
  14.     // Axes  
  15.     dc.MoveTo(-300,     0);  
  16.     dc.LineTo( 300,     0);  
  17.     dc.MoveTo(   0, -1400);  
  18.     dc.LineTo(   0,  1400);  
  19.   
  20.     // I am exaggerating with the PI value here but why not?  
  21.     const double PI = 3.141592653589793238462643383279;  
  22.       
  23.     // The following two values were chosen randomly by me.  
  24.     // You can chose other values you like  
  25.     const int MultiplyEachUnitOnX = 50;  
  26.     const int MultiplyEachUnitOnY = 250;  
  27.   
  28.     for(double i = -280; i < 280; i += 0.01)  
  29.     {  
  30.         double j = sin(PI / MultiplyEachUnitOnX * i) * MultiplyEachUnitOnY;  
  31.         dc.SetPixel(i, j, RGB(255, 0, 0));  
  32.     }  
  33.     // Do not call CView::OnPaint() for painting messages  
  34. }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值