在Windows中绘图就需要使用到GDI 概念。GDI其实就是一个设备无关的图形包。这样的类似图形包有比如OpenGL,VTK等。不过GDI的特点就是其是二维的并且被封装进了Winows的API当中。不过Windows图形编程当中还有一个特点就是各个程序都有自己的输出窗口,每个程序间需要隔离,windows使用设备表述表表示。所以在做Windows图形编程的时候常要使用两个东西一个是DC(设备描述表)一个是GDI。
在早期的Windows图形编程当中方式给GDI传入DC句柄然后再绘图并且GDI返回DC句柄。
在windows MFC的编程当中,其按OO思想将DC抽象为对象,将GDI函数变成了DC方法。这个类就是CDC类。当然这个类如同CWND类一样只用一个DC的句柄而没有具体的DC数据结构。数据结构还是在windows当中。其次CDC类封装了很多GDIAPI有的就是直接调用。
所以DC的结构可以这样理解。每个程序DC都是由windows管理的CDC类通过得到一个句柄来操作DC绘图。所以DC数据结构是共享所以就导致了例如DC对象释放等问题。
所以一般而言获取DC方法如下:
GetDC()
/*绘图*/
ReleaseDC()
但是这个过程有些问题。一就是程序员如果遗忘释放导致错误,二就是在响应ON_WM_Paint消息的时候是调用这两个函数将是死循环。因为相应On_Paint消息必须有一对BeginPaint(),endPaint()所以这需要使用这种函数代替前面提到的函数。
不过MFC提供三个派生类。CPaintDC,CClientDC,CWindowsDC。这几个类将上诉工作封装在了构造函数和析构函数中来完成。看MFC的源码就知CPaintDC封装了BeginPaint ()endPaint()CClientDC 封了GetDC()ReleaseDC()CWindowsDC只是没有使用GetDC()而使用了GetWindowDC()
这样windows 图形编程就变成了构建一个DC实例调用DC的成员函数。
Windows 图形编程的另一个问题就是在于GDI对象。MFC提供了CPEN,CBRUSH的GDI对象。这些GDI对象是对于原有GDI 属性类抽象。其还是共用一个数据机构。看MFC的源码就知道其构造函数调用的还是GDIAPI。
其次DC中的另一个问题就是绘图模式/映射模式的问题。
所谓绘图模式就是将将物理坐标结果如何绘制的问题这个是一个图形学的基本问题windows 给与的包装。
所谓映射模式主要是有着两套坐标系统一个逻辑坐标系一个物理坐标系。映射模式就建立这两个坐标系的转化关系。默认的方式原点重合一个逻辑单位对应一个像素。但windows 还提供了很多其他的方式。也可以自定义方式。