windows中的坐标

1:
//这个函数用来设置坐标轴的朝向以及单位
int SetMapMode(
  HDC hdc,         // handle to device context
  int fnMapMode   // new mapping mode
);
MM_ANISOTROPIC:
MM_HIENGLISH:1逻辑单位是1/1000英寸,X是朝右,Y朝上
MM_HIMETRIC:1逻辑单位是1/100微米,X是朝右,Y朝上
MM_LOENGLISH:1逻辑单位是1/100英寸,X是朝右,Y朝上
MM_LOMETRIC:1逻辑单位是1/10微米,X是朝右,Y朝上
MM_TEXT:1逻辑单位是1设备像素,X是朝右,Y朝下(设备不同时,单位也不同)
MM_TWIPS:1逻辑单位是1打印点的1/20,即(1/1440英寸),X是朝右,Y朝上。

所谓的逻辑坐标就是指以具体的物理单位为实际的单位,从而大小跟具体的设备无关。所谓的设备坐标单位就是指像素了,windows对所有的消息,所有的GDI函数,甚至对一些GDI函数,永远使用设备坐标。

视端口是依据设备坐标,也就是像素
窗口时是依据逻辑坐标,可以使相似,毫米,英寸等。


逻辑点和设备点之间的相互转换
DPtoLP(hdc,pPoints,iNumber);//设备点转换为逻辑点
LPtoDP(hdc,pPoints,iNumber);//逻辑点转换为设备点

坐标原点的改变
SetViewportQrgEx(HDC hdc,int x,int y,LPPOINT lpPoint);//(x,y是设备单位,像素)
SetWindowOrgEx(HDC hdc,int x,int y,LPPOINT lpPoint);//(x,y是逻辑单位)
两个函数的lpPoint 参数是函数返回的原来坐标原点的值。

坐标原点获取
GetViewportOrgEx(HDC hdc,LPPOINT lpPoint);
GetWindowOrgEx(HDC hdc,LPPOINT lpPoint);

细节:
SetViewportOrgEx(hdc,cxClient/2,cyClient/2,&pt);
TextOut(hdc,0,10,TEXT("I Love You"),10);//显示在中间,pt为(0,0)
//SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);//还是显示在中间
SetViewportOrgEx(hdc,pt.x,pt.y,&pt);
TextOut(hdc,0,0,TEXT("What is it AB"),13);//显示在左上角

由以上程序的第3行可以看出,当第2次调用SetViewportOrgEx()时,里面的坐标点还是依据最初始的坐标原点,而不是相对于改变后的坐标原点。其实想想这样是非常合理的,如果要改变原点的次数很多的话,那么每次都要依靠前后两次的相对距离,这样会相当复杂的。(根据原书解释,不管视口和窗口怎么变换,设备点(0,0)始终为显示区域的左上角)



SetWindowOrgEx(hdc,-cxClient/2,-cyClient/2,&pt);
TextOut(hdc,0,0,TEXT("I Love You"),10);//此时显示在文本在中间
SetWindowOrgEx(hdc,pt.x,pt.y,NULL);
TextOut(hdc,0,0,TEXT("What is it AB"),13);//此时文本显示在左上角

由以上程序第1行可以看出对于做到相同的显示效果,视口坐标系和窗口坐标系所做的活动室完全相反的,这是因为当视口坐标系进行变换时,这个时候相当于移动的是内容,但是窗口不变。当窗口坐标系进行变换时,此时实际上是内容不动,但是窗口发生移动,从而造成内容产生对窗口的相对移动。此时还有一个问题就是在上面的TextOut(hdc,0,0,TEXT("I Love You"),10);中,坐标(0,0)到底指的什么坐标,它是相对于什么来讲的,如果说是窗口原点的话,这明显是不可能的,所以这种坐标应该是相对于视口原点来讲的。


所以说当移动视口时,设备点(0,0)是不会发生变化的,原因是窗口没有发生变化,但是当移动窗口时,设备点(0,0)发生了变化,不管怎样,设备点(0,0)都要保持和窗口左上端点重合。然后一些画图函数,文字函数等GDI函数,他们的坐标点都是相对于视口原点来说的,而不是相对于窗口。至于其单位当然可以使逻辑单位或者像素了。

再说说连续两次调用SetWindowOrgEx(……),我们再想想第二次调用SetWindowOrgEx(hdc,0,0,NULL)
时,这里的(0,0)坐标又是相对谁的,很明显,这样调用后显示的文字又是显示在左上顶端,说明了(0,0)就是之前的原点,所以对视口坐标系和窗口坐标系来讲,他们都保留一个最原始的坐标体系,
设置坐标原点的位置都是相对于这个最原始的坐标系来讲,这很明显能够避免复杂性。

GetWindowExtEx(hdc,&sz1);
GetViewportExtEx(hdc,&sz2);
SetWindowExtEx(hdc,nXExtent,nYExtent,lpsize);
SetViewportExtEx(hdc,nXExtent,nYExtent,lpsize);
这四个函数是用来改变视口坐标系以及窗口坐标系的坐标轴的范围,仅仅在MM_ISOTROPIC以及MM_ANISOTROPIC的模式下起作用。其他的六种模式下这四个函数将会被忽略,如果用
GetWindowExtEx(hdc,&sz1);
GetViewportExtEx(hdc,&sz2);来获取坐标范围,那么得到的值将是1.
**********************************************************************************************

1:Ellipse(hdc,-200,-200,200,200);

windows中的坐标

2:SetViewportOrgEx(hdc,200,200,NULL);

Ellipse(hdc,-200,-200,200,200);

windows中的坐标

3:

SetWindowOrgEx(hdc,-200,-200,NULL);

Ellipse(hdc,-200,-200,200,200);

windows中的坐标

这三个图充分说明了这些GDI函数里面的坐标是相对于视口坐标系而讲的,而不是针对设备坐标点以及窗口坐标系.

4:

      SetMapMode(hdc,MM_ANISOTROPIC);

      SetWindowExtEx(hdc,400,400,NULL);

      SetViewportExtEx(hdc,rc.right,rc.bottom,NULL);

      SetWindowOrgEx(hdc,-200,-200,NULL);

      Ellipse(hdc,-200,-200,200,200);

windows中的坐标

从上图明显可以看出,此时的圆明显变形了,原因就是在我们将窗口坐标设置为(0-400),(0-400),并且将其和设备区域的x,y轴的像素相对应,由于x,y轴不等长,所以其像素个数也不相等,但是其对应的逻辑长度都相等,这样就造成对于同一单位的X,Y,其占有的像素不等,因此就让圆扁了.

注意:windows,GDI函数对应的坐标长度单位是逻辑值,也就是实际的物理量度单位,但是最终在设备上显示的肯定都是以像素的形式表达出来,这里面就要涉及到逻辑值和像素值的对应关系。

 

对于SetWindowExtExhdcxylpsize);SetViewportExtExhdcxylpsize)的再深一步探讨。

对于SetWindowExtExhdcxylpsize);这里的xy到底表达的是神马东西,的确会让人产生误解,xy其实表达的就是窗口中xy的逻辑值,

SetViewportExtExhdcxylpsize)中的xy表达的就是相应的像素值,当xy对应的逻辑长度明确时(Length),此时对于SetWindowExtExhdcxylpsize),表达的意思就是这个Length长度内的逻辑值,这样Length内分别对于相应的像素值,对于相应的逻辑值,从而产生了逻辑值和像素值的比对关系。

在上面的这些东西都理解的情况下,咱们再来看windows程序设计中一段代码:

SetMapMode (hdc, MM_ISOTROPIC) ;

SetWindowExtEx (hdc, 16, 16, NULL) ;

SetViewportExtEx (hdc, GetDeviceCaps (hdc, LOGPIXELSX),

                        GetDeviceCaps (hdc, LOGPIXELSY), NULL) ;

解释:因为函数GetDeviceCaps (hdc, LOGPIXELSX)的意思即是1英寸内对应的像素值,所以SetWindowExtEx (hdc, 16, 16, NULL) ,这里的16表示的就是1英寸内对于的逻辑值,逻辑值=16,那么逻辑单位就是1/16英寸,从而做到了利用这两个函数来改变逻辑单位值的目的。因为我们的几乎所有GDI函数都是以逻辑单位为单位,那么当SetWindowExtEx (hdc, 16, 16, NULL) 中的16变得很大时,对应的画出来的图就越来越小了。

SetWindowExtEx()或者SetViewportExtEx()中出现(xy)中的一个为负值时,此时会造成坐标轴的翻转。如:

SetWindowExtEx (hdc, 276, -72, NULL)

SetViewportExtEx (hdc, cxClient, cyClient, NULL)

或者

SetWindowExtEx (hdc, 276, 72, NULL)

SetViewportExtEx (hdc, cxClient, -cyClient, NULL)

会造成:

windows中的坐标

原本的程序:

SetWindowExtEx (hdc, 276, 72, NULL)

SetViewportExtEx (hdc, cxClient, cyClient, NULL)

windows中的坐标

 

若再把程序改成这样

SetWindowExtEx (hdc, 276,-72, NULL)

SetViewportExtEx (hdc, cxClient, -cyClient, NULL)

 

windows中的坐标

你可能感兴趣的:(windows中的坐标)