深夜睡不着看书(CP的windows程序设计)看卡到了。求围观下。该怎么处理

深夜睡不着看书(CP的windows程序设计)看卡到了。求围观下。
《Windows程序设计》(第5版 珍藏版)
P620
这是问题代码:
C/C++ code
int ShowDib (HDC hdc, BITMAPINFO * pbmi, BYTE * pBits, int cxDib, int cyDib, 
             int cxClient, int cyClient, WORD wShow)
{
     switch (wShow)
     {
     case IDM_SHOW_NORMAL:
          return SetDIBitsToDevice (hdc, 0, 0, cxDib, cyDib, 0, 0, 
                                    0, cyDib, pBits, pbmi, DIB_RGB_COLORS) ;
               
     case IDM_SHOW_CENTER:
          return SetDIBitsToDevice (hdc, (cxClient - cxDib) / 2,
                                         (cyClient - cyDib) / 2, 
                                    cxDib, cyDib, 0, 0, 
                                    0, cyDib, pBits, pbmi, DIB_RGB_COLORS) ;

     case IDM_SHOW_STRETCH:
          SetStretchBltMode (hdc, COLORONCOLOR) ;

          return StretchDIBits (hdc, 0, 0, cxClient, cyClient, 
                                     0, 0, cxDib, cyDib,
                                pBits, pbmi, DIB_RGB_COLORS, SRCCOPY) ;

     case IDM_SHOW_ISOSTRETCH:
          SetStretchBltMode (hdc, COLORONCOLOR) ;
          SetMapMode (hdc, MM_ISOTROPIC) ;
          SetWindowExtEx (hdc, cxDib, cyDib, NULL) ;
          SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;
          //主要是下面两句看不懂如果代码中有一句我一般看的懂,两句一起来我就有点晕了。
          //我不知道这里是如何实现下面我问题描述中的功能的。
          //逻辑点(cxDib/ 2,cyDib/ 2)映像为设备点(0,0),即显示区域的左上角。
          SetWindowOrgEx (hdc, cxDib / 2, cyDib / 2, NULL) ;
          //逻辑点(0,0)将映像为设备点(cxClient/2,cyClient/2)。
          SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;

          return StretchDIBits (hdc, 0, 0, cxDib, cyDib, 
                                     0, 0, cxDib, cyDib,
                                pBits, pbmi, DIB_RGB_COLORS, SRCCOPY) ;
     }
     return 0 ;
}

函数描述:这个ShowDib函数,他根据菜单选项,按四种不同方式在客户区显示DIB.SetDIBitsToDevice函数可以把DIB显示在客户区左上角和客户区中央。StretchDIBits函数,也可以按两种方式显示DIB;拉伸到填满客户区(会变形),或者各个方向都按相同比例拉伸(不变形)。
问题描述:我就是第四种StretchDIBits实现不变形拉伸中原理看不懂,主要是SetWindowOrgEx (hdc, cxDib / 2, cyDib / 2, NULL) ;SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;见代码备注;
PS:贴MSDN的不要来,我是看了MSDN查了GOOGLE看了N小时N篇关于SetViewportOrgEx,SetWindowOrgEx讲解还没懂才来问的。GDI映射模式是哥心中永远的痛一直迷迷糊糊,从未弄懂。

------解决方案--------------------
http://topic.****.net/u/20110106/17/aed68793-a901-44ae-af4e-cc7716c77068.html
------解决方案--------------------
先不说windows
就说坐标映射
其实最基本就是两个问题
1、原点在哪
2、逻辑单位设定
以800,600的屏幕为例
默认原点在左上角
逻辑单位是像素
如果你要把图形画在屏幕中间
图形的中心坐标就是400,300
如果改变这种映射模式
我们把原点设置在400,300的位置
那么你要把图形输出在中心
你得绘制坐标就是0,0
基本上就是这个意思
理论的东西相信你已经很了解了
我就不班门弄斧了
------解决方案--------------------
我是来膜拜你的,深夜睡不着还能学习,如果是我,可能就看电影了。
------解决方案--------------------
SetViewportOrg和 SetWindowOrg都是基于物理设备坐标原点来设置视囗或窗囗的原点,只是SetViewportOrg使用的是设备单位,而SetWindowOrg使用的是逻辑单位;不论视囗和窗囗原点如何设置物理设备原点是固定不变的,并且窗囗原点最终会映设到视囗原点;
窗囗映射到视囗其实就是将窗囗坐标转为视囗坐标,其转换过程可用窗囗转视囗的公式表示;

简单点就是原点设到什么位置,它就在什么位置。这个两个 函数一个设置窗囗原点,一个设置视囗原点,,设置之后,窗囗和视囗的原点就不在一起了,只是在映射时总是将窗囗原点映射到视囗原点而已。 映射时要通过公式进行一些运算,,并不是简单的将窗囗原点挪到视囗原点。。其公式如下:
xdevice=(xpage-窗口原点x) * 视口范围x / 窗口范围x+视口原点x;
ydevice=(ypage-窗口原点y) * 视口范围y / 窗口范围y+视口原点y;


通常说的设备坐标指的就是视囗坐标,,逻辑坐标指的就是窗囗坐标。物理设备坐标就是永远不会被移动的那个设备坐标;
------解决方案--------------------
SetWindowOrgEx (hdc, cxDib / 2, cyDib / 2, NULL) ;
是设置窗口的起始位置,也就是将窗口的起始位置调整到图片的中央去
SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
是设置视口的其实位置,也就是将视口的起始位置调整到客户区的中央去

------解决方案--------------------
SetViewportOrgEx()函数是客户区不动,原点坐标移动。