MFC API——》 SetWindowExt() 与SetViewportExt()


SetViewportExt(int   Pwidth,   int   Pheight)   //参数的单位为像素(Pixel),如果参数为负值表示viewport相应的坐标轴与device空间相反


百度文库:setwindoworg setviewportorg SetViewportExt
pDC->setmapmode(MM_ISOTROPIC);
pDC->SetWindowExt(10240,7680);
pDC->SetViewportExt(1024,768);
pDC->Rectangle(0,0,100,100);

就会画一个10pixels*10pixels的矩形,其本质就是,X方向,每个逻辑单位有1024/10240个像素,Y方向每个逻辑单位有768/7680个像素

(1)

CRect rect(0,0,200,200)

dc.rectangle(rect);

在屏幕的最左上角绘制一个正方形(因为此时逻辑坐标与设备坐标没有偏移)

(2)

dc.SetViewportOrg(100,100);

CRect rect(0,0,200,200);
dc.rectangle(rect);

将设备坐标的原点设置到(100,100);即设备坐标的原点不在(0,0)处,而是在(100,100)处,此时若执行映射的话,逻辑坐标的原点(0,0)需要与设备坐标的原点(100,100)重合,那么此时绘制的矩形(0,0,200,200)的坐标(为逻辑坐标)在设备坐标中就会映射为(100,100,300,300),最终我们在显示器上看到的会是一个向右下方偏移(100,100)的一个边长为200的正方形(用户看到的点是在设备坐标中的)。

(3)

dc.SetWindowOrg(100,100);

CRect rect(0,0,200,200);

dc.rectangle(rect);

将逻辑坐标的原点设置到(100,100),即逻辑坐标的原点不在(0,0)处,而是在(100,100)处,此时若执行映射的话,设备坐标的原点(0,0)需要与逻辑坐标的原点(100,100)重合;那么此时绘制的矩形(0,0,200,200)的坐标(为逻辑坐标)在设备坐标中就会映射为(-100,-100,100,100),最终我们在显示器上看到的会是一个只有1/4个大小的矩形的一部分(事实上,相当于左上方偏移(100,100)的一个边长为200的正方形。

 

http://hi.baidu.com/slqhappy/blog/item/3f61b8da2bee57d2b6fd48b1.html

按习惯,(0,0)就原点,原点就是(0,0),但是如果用此来理解windows的map mode,就会走弯路。其实,稍微改变一下观念,windows的map mode就比较好理解了。举例说明:

page space---->device space
pDC->SetMapMode(MM_LOMETRIC);
pDC->SetWindowOrg(40,0);  //这句“设定”page space的原点为(40,0),注意,
//这时(40,0)就是原点,原点就是(40,0)这个点,其实,(0,0)与原点没有必然联系。这
//一句对下面的画图函数在page space中所作的图不会有任何影响。一句话:SetWindowOrg
//就是指定一下,page space中哪个点为原点。
pDC->Rectangle(0,0,100,-100);
pDC->Rectangle(0,-100,50,-200);

同理,SetViewportOrg也是指定一下,device space中哪个点为原点,两个坐标系映射时,两个原点重合

SetWindowExt设定page space的大小,SetViewportOrg设定device space的大小,其实,真正有意义的只是两者的比例关系,例如,在一个1024*768的显示屏上:

pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(10240,7680);
pDC->SetViewportExt(1024,768);
pDC->Rectangle(0,0,100,100);//给出的是逻辑单位,但是具体绘制出来要转化为设备单位,转化比例由模式确定

  就会画一个10 pixels*10 pixels的矩形。其本质就是,X方向,每个逻辑单位有1024/10240个象素,Y方向每个逻辑单位有768/7680个象素。因此,下面的代码有相同的作用:

pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(102400,76800);
pDC->SetViewportExt(10240,7680);
pDC->Rectangle(0,0,100,100);

两者本质一样,前者更易于理解。
================================

SetWindowOrg和SetViewportOrg这两个函数比较难搞懂,经过本人的google和实践终于弄明白了这两个函数的本质区别。

1.SetWindowOrg(x, y) 是把设备坐标的原点(视口)映射到逻辑坐标的(X, Y)处

2.SetViewportOrg(x, y) 是把逻辑坐标的原点(窗口)映射到设备坐标的(X, Y)处

3. 设备原点永远是客户区的左上角顶点(upper left corner of the client area)。

(后面的一幅图显示了这两个函数的意义)
注意设备坐标和逻辑坐标的区别:

1.设备坐标的X, Y轴方向固定的,单位也是固定的,X轴向右递增,Y向下递增,单位都是像素

2.逻辑坐标的X, Y轴方向不固定单位不固定根据选择的映射模式而变化

有了以上的解释,相信大家应该能明白为什么下面的代码的现实结果会是这样的了吧。

void CEx05aView::OnDraw(CDC* pDC)
{
pDC->SetMapMode(MM_LOMETRIC);
pDC->SetWindowOrg(100, 100);
pDC->Rectangle(0, 0, 200, 200);

pDC->SetViewportOrg(100, 100);
pDC->SelectStockObject(GRAY_BRUSH);
pDC->Rectangle(0, 0, 200, 200);
}

建立一个合适的坐标系可以为我们的绘图带来很大的方便 。下面介绍一下如何在VC中建立我们想要的坐标系。
一 设备坐标和逻辑坐标
  设备坐标(Device Coordinate)又称为物理坐标(Physical Coordinate),是指输出设备上的坐标。通常将屏幕上的设备坐标称为屏幕坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的,设备坐标的X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。
  逻辑坐标(Logical Coordinate)是系统用作记录的坐标。在缺省的模式(MM_TEXT)下,逻辑坐标的方向和单位与设备坐标的方向和单位相同,也是以像素为单位来表示的,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。逻辑坐标和设备坐标即使在缺省模式下其数值也未必一致,除了在以下两种情况下:
  1. 窗口为非滚动窗口
  2. 窗口为滚动窗口,但垂直滚动条位于滚动边框的最上端,水平滚动条位于最左端,但如果移动了滚动条这两种坐标就不一致了。
  在VC中鼠标坐标的坐标位置用设备坐标表示,但所有GDI绘图都用逻辑坐标表示,所以用鼠标绘图时,那么必须将设备坐标转换为逻辑坐标,可以使用 CDC 函数DptoLP()将设备坐标转化为逻辑坐标,同样可以用LptoDP()将逻辑坐标转化为设备坐标。

二 坐标模式
  为了在不同的领域使用逻辑坐标,Windows提供了以下8种坐标模式:
  分别为MM_TEXT、MM_HIENGLISH、MM_LOENGLISH、MM_HIMETRIC、MM_LOMETRIC、MM_TWIPS、MM_ANISOTROPIC和MM_ISOTROPIC。

三 实例解析
  (一) 建立以左上角为原点,X轴和Y轴为1000的坐标,如下图
  我们可以用以下代码:
  void CTtView::OnDraw(CDC* pDC)
   {
    CTtDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    CRect rect;
    GetClientRect(&rect);

    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetViewportOrg(0,0);
    pDC->SetViewportExt(rect.right,rect.bottom);

    pDC->SetWindowOrg(0,0);
    pDC->SetWindowExt(1000,1000);

    pDC->MoveTo(50,50);
    pDC->LineTo(50,950);
    pDC->LineTo(950,950);
    pDC->LineTo(50,50);
   }
  代码分析:
  1. GetClientRect(&rect); 取得客户区矩形区域,将其存放在rect中
  2. 用pDC->SetMapMode(MM_ANISOTROPIC); 设置映射模式
  3. 通过pDC->SetViewportOrg(0,0);设置逻辑坐标的原点。
  4. 通过pDC->SetViewportExt(rect.right,rect.bottom);和
pDC->SetWindowExt(1000,1000);来确定逻辑坐标下和设备坐标下的尺寸对应关系
  5. 在MM_ANISOTROPIC模式下,X轴单位和Y轴单位可以不相同
  6. 坐标方向的确定方法是如果逻辑窗范围和视口范围符号相同,则逻辑坐标的方向和视口的方向相同,即X轴向右为正,Y轴向下为正。
  7. 如果将显示模式改为MM_ISOTROPIC,那么X轴单位和Y轴单位一定相同,感兴趣的读者可以自己使一下。
  (二) 建立以视窗中心为原点的坐标,如下:
  用如下代码:
  void CTtView::OnDraw(CDC* pDC)
   {
    CTtDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    CRect rect;
    GetClientRect(&rect);

    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetViewportOrg(rect.right/2,rect.bottom/2);
    pDC->SetViewportExt(rect.right,rect.bottom);

    pDC->SetWindowOrg(0,0);
    pDC->SetWindowExt(1000,-1000);

    pDC->MoveTo(150,150);
    pDC->LineTo(-150,-200);
    pDC->LineTo(150,-150);
    pDC->LineTo(150,150);
   }
 代码分析:
  1. 用 pDC->SetViewportOrg(rect.right/2,rect.bottom/2); 设置视口的原点。
2. 用pDC->SetViewportExt(rect.right,rect.bottom);和pDC->SetWindowExt(1000,-1000);来确定设备坐标和逻辑坐标的单位对应关系。把1000当做距离来看待,在本例中(500,-500)为窗口右下角
  3. 因为逻辑窗范围和视口范围的符号不一致,纵坐标取反,所以Y轴向上为正。

MM_LOENGLISH、MM_HIENGLISH、MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS这一组是Windows提供的重要的固定比例映射模式。

它们都是x值向右方向递增,y值向下递减,并且无法改变。它们之间的区别在于比例因子见下:(我想书上P53页肯定是印错了,因为通过程序实验x值向右方向也是递增的)

MM_LOENGLISH 0.01英寸
MM_HIENGLISH 0.001英寸
MM_LOMETRIC 0.1mm
MM_HIMETRIC 0.01mm
MM_TWIPS 1/1440英寸 //应用于打印机,一个twip相当于1/20磅,一磅又相当于1/72英寸。


http://blog.sina.com.cn/s/blog_5f853eb10100uesz.html

http://blog.csdn.net/benny5609/article/details/1845645

http://blog.sina.com.cn/s/blog_935e8c740100vmdr.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值