GDI坐标系统(下)

来源:互联网 发布:中文域名好吗 编辑:程序博客网 时间:2024/04/26 14:57

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)。

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);}

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

设想原点(0,0)点位于窗体中心。即将原点放在(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);}

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

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

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

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

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()函数之后,你可以调用SetViewporExt()函数。它的作用是指定水平轴和竖直轴的单位长度。语法如下:

CSize SetViewportExt(int cx, int cy);CSize SetViewportExt(SIZE size);

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

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);}

坐标轴箭头例子

void CExoDraw1View::OnPaint() {    CPaintDC dc(this); // device context for painting    CBrush bgBrush(BLACK_BRUSH);    dc.SelectObject(bgBrush);    dc.Rectangle(Recto);    dc.SetMapMode(MM_ISOTROPIC);    dc.SetViewportOrg(0, 440);    dc.SetWindowExt(480, 480);    dc.SetViewportExt(440, -680);    CPen PenWhite(PS_SOLID, 1, RGB(255, 255, 255));    dc.SelectObject(PenWhite);    dc.MoveTo(21, 20);    dc.LineTo(21, 75);    // Up arrow    dc.MoveTo(16, 75);    dc.LineTo(21, 90);    dc.LineTo(26, 75);    dc.LineTo(16, 75);    dc.MoveTo(21, 22);    dc.LineTo(75, 22);    // Right arrow    dc.MoveTo(75, 17);    dc.LineTo(90, 22);    dc.LineTo(75, 27);    dc.LineTo(75, 17);    dc.SetBkMode(TRANSPARENT);    dc.SetTextColor(RGB(255, 255, 255));    dc.TextOut(16, 114, 'Y');    dc.TextOut(100, 32, 'X');    dc.Rectangle(15, 15, 30, 30);}

绘制线状网格

void CExoDraw1View::OnPaint() {    CPaintDC dc(this); // device context for painting    CRect Recto;    GetClientRect(&Recto);    CBrush bgBrush(BLACK_BRUSH);    dc.SelectObject(bgBrush);    dc.Rectangle(Recto);    CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));    dc.SelectObject(PenBlue);    for(int x = 0; x < Recto.Width(); x += 20)    {        dc.MoveTo(x, 0);        dc.LineTo(x, Recto.Height());    }    for(int y = 0; y < Recto.Height(); y += 20)    {        dc.MoveTo(0, y);        dc.LineTo(Recto.Width(), y);    }}

绘制点状网格

void CExoDraw1View::OnPaint() {    CPaintDC dc(this); // device context for painting    CRect Recto;    GetClientRect(&Recto);    CBrush bgBrush(BLACK_BRUSH);    dc.SelectObject(bgBrush);    dc.Rectangle(Recto);    for(int x = 0; x < Recto.Width(); x += 20)    {        for(int y = 0; y < Recto.Height(); y += 20)        {dc.SetPixel(x, y, RGB(255, 255, 255));        }    }}

绘制正弦曲线

void CExoView::OnPaint() {CPaintDC dc(this); // device context for painting// TODO: Add your message handler code heredc.SetMapMode(MM_ANISOTROPIC);dc.SetViewportOrg(340, 220);dc.SetWindowExt(1440, 1440);dc.SetViewportExt(-1440, -220);CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));dc.SelectObject(PenBlue);// Axesdc.MoveTo(-300,     0);dc.LineTo( 300,     0);dc.MoveTo(   0, -1400);dc.LineTo(   0,  1400);// I am exaggerating with the PI value here but why not?const double PI = 3.141592653589793238462643383279;// The following two values were chosen randomly by me.// You can chose other values you likeconst int MultiplyEachUnitOnX = 50;const int MultiplyEachUnitOnY = 250;for(double i = -280; i < 280; i += 0.01){    double j = sin(PI / MultiplyEachUnitOnX * i) * MultiplyEachUnitOnY;    dc.SetPixel(i, j, RGB(255, 0, 0));}// Do not call CView::OnPaint() for painting messages}














原创粉丝点击