被SetMapMode、setWindowExt、SetViewportExt、SetViewportOrg、SetWindowOrg
这五个函数弄的晕头胀脑的,查了以前的一些帖子也没看到讲的很明白的,今天自己上机做了练习,发现一些很有趣的结果,干脆出几道题让大家做做。看看到底对映射模式掌握的如何。
题目:新建一个单文档程序后,在Ondraw函数中分别运行以下几段代码,不上机运行说出程序的运行结果,并说明原因。每题的第一个答对并说清理由者给10分:-)
OnDraw函数的公共代码部分:
void CTestView::OnDraw(CDC* pDC)
{
  CRect clientRect;
  GetClientRect(clientRect); 
  TRACE("The rect is left:%d ,top:%d,right:%d,bottom:%d\n",
      clientRect.left,
      clientRect.top,
      clientRect.right,
      clientRect.bottom);
}
运行后已发现每次开始运行后trace的运行结果均为
he rect is left:0 ,top:0,right:756,bottom:445,
并且屏幕的分辨率为1024*768像素,
在以上已知条件下请说出以下几段不同代码的初始运行结果和窗口最大化后的显示结果,答题前不许上机:-)
(1)
  pDC->Ellipse(-500,-500,500,500);
 (2)
  pDC->SetMapMode(MM_ISOTROPIC);
  pDC->Ellipse(-500,-500,500,500);
  (3)
   pDC->SetMapMode(MM_ISOTROPIC);
   pDC->SetWindowExt(1000,1000);
   pDC->Ellipse(-500,-500,500,500);
   (4)
   pDC->SetMapMode(MM_ISOTROPIC);
   pDC->SetViewportExt(clientRect.right,clientRect.bottom);
   pDC->Ellipse(-500,-500,500,500);
  (5)
   pDC->SetMapMode(MM_ISOTROPIC);
  pDC->SetWindowExt(1000,1000);
  pDC->SetViewportExt(clientRect.right,clientRect.bottom);
  pDC->Ellipse(-500,-500,500,500);
  (6)
   pDC->SetMapMode(MM_ISOTROPIC);
   pDC->SetViewportExt(clientRect.right,clientRect.bottom);
   pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);
   pDC->Ellipse(-500,-500,500,500);
   (7)
    pDC->SetMapMode(MM_ISOTROPIC);
   pDC->SetWindowExt(1000,1000);
  pDC->SetViewportExt(clientRect.right,-clientRect.bottom);
  pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);
  pDC->Ellipse(-500,-500,500,500);
  (8)
   pDC->SetMapMode(MM_ISOTROPIC);
  pDC->SetWindowExt(1000,1000);
  pDC->SetViewportExt(clientRect.right,clientRect.bottom);     //注意和7不同的是少了一个负号
  pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);
  pDC->Ellipse(-500,-500,500,500);
  (9)
  pDC->SetMapMode(MM_ISOTROPIC);
   pDC->SetWindowExt(1000,1000);
  pDC->SetViewportExt(clientRect.right,-clientRect.bottom);
  //pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);  //与7类似,这一句被注释掉了
  pDC->Ellipse(-500,-500,500,500);
  (10)
  pDC->SetMapMode(MM_ISOTROPIC);
   pDC->SetWindowExt(1000,1000);
   //pDC->SetViewportExt(clientRect.right,-clientRect.bottom); //与7类似,但这一句被注释掉了
   pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);   
  pDC->Ellipse(-500,-500,500,500); 

解决方案 »

  1.   

    忘了说一句,运行环境在win2k professional+vc6下
      

  2.   

    1.pDC->Ellipse(-500,-500,500,500);为整个圆的右下1/4个圆
      最大化也是一样
      

  3.   

    2.
    pDC->SetMapMode(MM_ISOTROPIC);
      pDC->Ellipse(-500,-500,500,500);
      比1的结果圆要小
      

  4.   

    3.
       pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetWindowExt(1000,1000);
       pDC->Ellipse(-500,-500,500,500);
    与1的结果一样
      

  5.   

    SetMapMode()来设置逻辑坐标系统,也可以调用CDC的SetViewpotOrg()函数来改变逻辑系的坐标原点
      

  6.   

    SetWindowExt()用户可以定义自己的逻辑坐标系
      

  7.   

    to carbon107(<软件开发思想.h>) :
      第一题你有一个小小的疏忽:我的客户区初始大小是
    left:0 ,top:0,right:756,bottom:445,
    因此刚运行时只能看到部分圆,最大化后才能看到1/4的圆弧,呵呵
      

  8.   

    2.
     pDC->SetMapMode(MM_ISOTROPIC);
      pDC->Ellipse(-500,-500,500,500);
      比1的结果圆要小
    答对了,但是能具体讲讲原因吗?或者,这个圆在屏幕上的真实尺寸(以像素为单位)是多少?已知客户区是756*445大小,分辨率为1024*768的条件下?
      

  9.   

    3.
       pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetWindowExt(1000,1000);
       pDC->Ellipse(-500,-500,500,500);
    //与1的结果一样,
    错了,实际结果这个圆比1中的小,比2中的大,你上机试试看:-)
      

  10.   

    1.如你好说
    2。
    CRect rectClient; //
    GetClientRect(rectClient);//返回客户区矩形的大小
    pDC->SetMapMode(MM_ISOTROPIC);//设定映射模式为MM_ANISOTROPIC
    pDC->SetWindowExt(1000,1000);
    pDC->SetViewportExt (rectClient.right ,-rectClient.bottom );
    //用SetWindowExt和SetViewportExt函数设定窗口为1000逻辑单位高和1000逻辑单位宽
    pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2 );//设定逻辑坐标原点为窗口中心
    pDC->Ellipse(CRect(-500,-500,500,500));//画一个撑满窗口的椭圆。
    这样就是一个圆,但是改为pDC->SetMapMode(MM_ANISOTROPIC)就是椭圆了
      

  11.   

    checkyvc6(checkyvc6) 
    公式在哪呢?
    //提醒你一句,千万别太往里面去,虽然搞懂不难但是没有意思没有意义的.
    谢谢您的提醒,但是我就是想弄明白。呵呵
      

  12.   

    其实无非就是用到这两个MM_ISOTROPIC,MM_ANISOTROPIC
    前几道都是在默认的情况下画了
    要结合SetWindowExt    SetViewportExt    SetViewportExt 来画出完整的圆pDC->SetMapMode(MM_ISOTROPIC);
      pDC->SetWindowExt(1000,1000);MM_ISOTROPIC 和MM_ANISOTROPIC 的 区 别 是 所 设 置 的x 轴 和y 轴 的 的 范 围 必 须 相 同, 而MM_ANISOTROPIC 所 设 置 的x 轴 和y 轴 的 的 范 围 可 以 不 同。isotropi 的 意 思 是" 在 所 有 方 向 相 同",anisotropic 的 意 思 正 相 反。 自 定 义 映 射 模 式 中 窗 口 和 视 口 的 原 点 和 范 围 都 可 以 改 变.
      

  13.   

    checkyvc6(checkyvc6) 说的是下面的公式对 于 所 有 映 射 模 式,Windows 都 用 下 面 两 个 公 式 将 窗 口 坐 标 转 换 成 视 口 坐 标: ---- xViewport = (xWindow - xWinOrg) * (xViewExt / xWinExt) + xViewOrg ---- yViewport = (yWindow - yWinOrg) * (yViewExt / yWinExt) + yViewOrg ---- 其 中,(xWindow, yWindows) 是 待 转 换 的 逻 辑 点,(xViewport, yViewport) 是 转 换 后 的 设 备 点。 如 果 设 备 坐 标 是 客 户 区 域 坐 标 或 全 窗 口 坐 标, 则Windows 在 画 一 个 对 象 前, 还 必 须 将 这 些 坐 标 转 换 成 屏 幕 坐 标。 ---- 这 两 个 公 式 使 用 了 分 别 指 定 窗 口 和 视 口 原 点 的 点:(xWinOrg, yWinOrg) 是 逻 辑 坐 标 的 窗 口 原 点;(xViewOrg, yViewOrg) 是 设 备 坐 标 的 视 口 原 点。 在 缺 省 的 设 备 环 境 中, 这 两 个 点 均 设 置 为(0, 0), 但 它 们 可 以 改 变。 此 公 式 意 味 着, 逻 辑 点(xWinOrg, yWinOrg) 总 被 映 射 为 设 备 点(xViewOrg, yViewOrg)。 ---- Windows 还 能 将 视 口( 设 备) 坐 标 转 换 为 窗 口( 逻 辑) 坐 标: ---- xWindow = (xViewport - xViewOrg) * (xWinExt / xViewExt) + xWinOrg ---- yWindow = (yViewport - yViewOrg) * (yWinExt / yViewExt) + yWinOrg ---- 可 以 使 用Windows 提 供 的 两 个 函 数DPtoLP 和LPtoDP 在 设 备 坐 标 及 逻 辑 坐 标 之 间 互 相 转 换。
      

  14.   

    carbon107(<软件开发思想.h>) 
      谢谢您列出的资料。事实上这些东西我也看过,但是用到具体的问题上就是不够的了,请您、checkyvc6(checkyvc6)还有其他高手一道题一道题的做,一定要每道题都做,肯定会发现一些与书上讲的不一样的东西:-)
      

  15.   

    呵呵,我都蒙了
    GIS地理信息系统里面讲的比较详细
      

  16.   

    7.8
    是一个随窗口变化的完整圆,对吧
        pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetWindowExt(1000,1000);
      pDC->SetViewportExt(clientRect.right,-clientRect.bottom);
      pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);
      pDC->Ellipse(-500,-500,500,500);
    但区别是一个在坐标系的第四向限,一个是在第一向限
    9.
    因为没有 pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);
    设定原点,所以默认以(0,0)所以看到的是1/4圆
    10
    因为你没有设定
      pDC->SetViewportExt(clientRect.right,-clientRect.bottom); 
    区域,又因为你的pDC->SetWindowExt(1000,1000);,所以看不到整个圆,如果你改为
    pDC->SetWindowExt(1500,1500);就看到了
      

  17.   

    4.   pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetViewportExt(clientRect.right,clientRect.bottom);
       pDC->Ellipse(-500,-500,500,500);
    1/4个圆,默认原点为0,0. 小于pDC->SetWindowExt(1000,1000);设定后的圆
    5.   pDC->SetMapMode(MM_ISOTROPIC);
      pDC->SetWindowExt(1000,1000);
      pDC->SetViewportExt(clientRect.right,clientRect.bottom);
      pDC->Ellipse(-500,-500,500,500);
    1/4个圆,默认原点为0,0.
    6.
       pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetViewportExt(clientRect.right,clientRect.bottom);
       pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);
       pDC->Ellipse(-500,-500,500,500);也是一个小圆.以clientRect.right/2,clientRect.bottom/2)为原点,在第一向限内的圆
                                 | 
                                 | 
                                 |  8题的圆在这里
                                 | 
                                 | 
                                 | (0,0)
    -----------------------------|--------------------------------------- 
                                 | 
                                 | 7题的圆在这里
                                 | 
                                 | 
                                 | 
                                 | 
                                 | 
                                 | 
                                 | 
      

  18.   

    SetViewportExt设定视口吧 ,  (+,+)就是第一向限的视,你要把屏幕的左下角当做(0, 0)
    (+, -)把你的屏幕的左上角当做(0, 0). 共四个视口,明白了吗???
                                 +
                                 | 
                                 |   8题的圆在这里
                                 | 
                                 | 
                                 | (0,0)
    - ---------------------------|--------------------------------------- +
                                 | 
                                 |   7题的圆在这里
                                 | 
                                 | 
                                 | 
                                 | 
                                 | 
                                 |
     
                                 -
      

  19.   

    (+, -)把你的屏幕的左上角当做(0, 0). 共四个视口,明白了吗?
    那为什么7中的setviewportorg里的参数还都是正的?
      

  20.   

    setviewportorg()那是相对于在本象限内的原点值,也就是脱离了什么象限的影响了.
      

  21.   

    按照你的解释
    pDC->SetMapMode(MM_ISOTROPIC);
    pDC->SetViewportExt(clientRect.right,clientRect.bottom);
    pDC->Ellipse(-500,-500,500,500);

    pDC->SetMapMode(MM_ISOTROPIC);
    pDC->SetViewportExt(clientRect.right,-clientRect.bottom);
    pDC->Ellipse(-500,-500,500,500);的输出应该不一样啊,
    为什么实际的输出结果一样?
      

  22.   

    (+,+)就是第一向限的视,你要把屏幕的左下角当做(0, 0)
    那么
    pDC->SetMapMode(MM_ISOTROPIC);
    pDC->SetViewportExt(clientRect.right,clientRect.bottom);
    pDC->Ellipse(-500,-500,500,500);
    看到的圆应该是第一象限的吧,但是这个1/4圆弧还是出现在了客户区的左上方而不是左下方:-)
      

  23.   

    pDC->SetMapMode(MM_ISOTROPIC);
    pDC->SetViewportExt(clientRect.right,clientRect.bottom);
    //这个时候到底原点是左上角还是左下角?
      

  24.   

    所以说我的理解就是
    SetViewportExt这个函数的作用就是设置视图的大小,无论写正写负,都是把视图的长宽设成参数的绝对值,参数的正负号不影响程序的运行结果。不知对吗?
      

  25.   

    其实,“先确定你的屏幕在第几象限”这正是我对SetViewportExt函数作用的原来的理解,而
    “再以你的窗口的左上角坐标原点为(0,0)”却是我所不能明白的。这样的话,确定象限又有什么意义呢,最后都处于第4象限了。
      

  26.   

    但是那本叫《XX技术内幕》的书非要把SetViewportExt的参数写成负的,真不知作者是怎么想的:-)
      

  27.   

    但是那本叫《XX技术内幕》的书非要把SetViewportExt的参数写成负的,真不知作者是怎么想的:-)//映射模式决定的
      

  28.   

    窗口和视区的范围不具有任何裁剪区的意义,它们用于确定将逻辑坐标系中的单位放大或缩小多少以适合设备坐标系中的单位。例如,如果窗口的X坐标范围是2,而视区的X坐标范围是4,则GDI将两个逻辑单位(按X轴计算)映射为一个设备单位。
      坐标范围也同样决定了两个坐标系(窗口和视区)的X轴和Y轴的相对定向关系。如果相关联的窗口和视区范围符号一致,则坐标轴方向相同,否则方向相反。例如,如果窗口和视区的X坐标范围分别是2和4,则GDI将逻辑坐标系的X轴的正半轴映射到该设备坐标系统的X轴正半轴;如果窗口和视区的Y坐标范围分别为2和-1,则GDI将逻辑坐标系统的Y轴的正半轴映射到设备坐标系的Y轴的负半轴。
      对于MM_ISOTROPIC映射方式,词“isotropic”表示在所有的方向都“相等”,即该方式的用途是在两个轴上保持相等的逻辑单位。
      

  29.   

    一种映射方式为MM_ANISOTROPIC,这种方式可以规定不同的长宽比例。在设置这中映射方式后必须调用CSize CDC::SetWindowExt( SIZE size )和CSize CDC::SetViewportExt( SIZE size )来设定长宽比例
      

  30.   

    pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetWindowExt(1000,1000);
       //pDC->SetViewportExt(clientRect.right,-clientRect.bottom); //与7类似,但这一句被注释掉了
       pDC->SetViewportOrg(clientRect.right/2,clientRect.bottom/2);   
      pDC->Ellipse(-500,-500,500,500);
    //因为比例设的pDC->SetWindowExt(1000,1000);
    你改为pDC->SetWindowExt(1500,1500);
    就看到了
      

  31.   

    pDC->SetWindowExt(a,b);a,b你设的大一点就可以看到了
      

  32.   

    SetWindowExt(1000, 1000)
    将映射模式设置成逻辑twips即一个逻辑单位等于1/1000逻辑英寸
      

  33.   

    那SetWindowExt(1500, 1500)
    是将映射模式设置成逻辑twips即一个逻辑单位等于1/1500逻辑英寸吗?