小弟初学GDI+,对坐标系之间的转换不是很明白,下面是我粗浅的理解,希望各路前辈和高人指出其中的错误,不甚感激!


在GDI/GDI+中有三种坐标系:世界坐标系,页面坐标系,设备坐标系
世界坐标系:在画布中的坐标系,原点默认为窗口工作区的左上角,原点位置可以改变(移动,旋转,缩放,翻转和单位度量的改变)。
页面坐标系:在窗口中的坐标系,原点为窗口工作区的左上角,原点位置固定,不可改变(可改变单位度量)。
设备坐标系:在屏幕中的坐标系,原点为窗口工作区的左上角,原点位置固定,不可改变。计算机绘图的本质:点亮屏幕上相应像素,对于底层的驱动程序来说,只需要知道两个东西:绘图的原点和像素的相对原点的偏移量。所以,必须将世界坐标转化为设备坐标,而设备坐标的原点固定为窗口工作区的左上角(默认情况下,程序每次启动时窗口的位置是不一样的,但是可以精确设置),所以只需要算出每个像素的偏移量。转换过程:先进行世界变换,在进行页面变换。世界变换:将世界坐标转化为页面坐标,即:画布中的坐标转换到窗口中。
特别说明:世界坐标系和页面坐标系使用的单位由画布的PageUnit(GDI+)属性决定,即:两者使用同一种单位度量(这从侧面说明为什么一块画布必须和一个窗口相关联。)
实例:
假定您想使用原点位于工作区的主体而非左上角的坐标系统。例如,您需要让原点位于距工作区左边缘 100 像素、距顶部 50 像素的位置。下图显示了这样的坐标系统。当调用 myGraphics.DrawLine(myPen, 0, 0, 160, 80) 时,可得到下面的插图中所显示的线条。下表显示了三种坐标空间中线条终点的坐标:
世界
(0, 0) 到 (160, 80)(单位为像素)
页面
(100, 50) 到 (260, 130)(单位为像素)
设备
(100, 50) 到 (260, 130)(单位为像素)
C#
myGraphics.TranslateTransform(100, 50);
myGraphics.DrawLine(myPen, 0, 0, 160, 80);
页面变换:将页面坐标转换为设备坐标,即:窗口坐标转换为屏幕坐标。
特别说明:设备坐标必须以像素为单位,所以页面变换就是将页面坐标像素化的过程。(因为页面坐标和世界坐标可以用英寸、厘米等作单位)。
实例:
下面的示例从 (0, 0) 至 (2, 1) 绘制线条,其中点 (2, 1) 位于点 (0, 0) 的右边 2 英寸和下边 1 英寸处:(世界坐标和页面坐标以英寸为单位。)
C#
myGraphics.PageUnit = GraphicsUnit.Inch;                    //设置世界坐标和页面坐标以英寸为单位
myGraphics.DrawLine(myPen, 0, 0, 2, 1);
Pen myPen = new Pen(Color.Black, 1 / myGraphics.DpiX);     //此时钢笔的宽度以英寸描
世界
(0, 0) 到 (2, 1)(单位为英寸)
页面
(0, 0) 到 (2, 1)(单位为英寸)
设备
(0, 0) 到 (192, 96)(单位为像素)综合实例:
可以合并世界变换和页面变换,以实现多种效果。例如,假定使用英寸作为度量单位,并且想让坐标系统的原点距工作区左边缘 2 英寸、距工作区顶部 1/2 英寸。下面的示例绘制一条从 (0, 0) 到 (2, 1) 的直线:
C#
myGraphics.TranslateTransform(2, 0.5f);        //移动世界坐标系的原点
myGraphics.PageUnit = GraphicsUnit.Inch;       //设置世界坐标系和页面坐标系的单位。
//特别说明:GDI/GDI+在内部维护了一组状态,只要在绘图之前某些状态发生了变化,就会影响其后的状态,而跟其改变的时间顺序无关。
myGraphics.DrawLine(myPen, 0, 0, 2, 1);
下图显示了线条和坐标系统。假定显示设备在水平方向和垂直方向每英寸都有 96 个点,则上例中直线的终结点在三个坐标空间中分别具有以下坐标:
世界
(0, 0) 到 (2, 1)(单位为英寸)
页面
(2, 0.5) 到 (4, 1.5)(单位为英寸)
设备
(192, 48) 到 (384, 144)(单位为像素)默认情况下,世界坐标系、页面坐标系和设备坐标系原点均为窗口工作区的左上角,以像素为单位,所以三者的值一样。(但是意义不一样。)