- DOS和WINDOWS图形输出区别:
- DOS:在DOS系统中,如果在文本模式下显示信息,只需要把内容拷贝到 B8000h 处的内存中;显示图形信息,可以把图形拷贝到 A0000h 处的内存中。
- WHindows中,GDI接口把程序和硬件分割开来,在Win32编程中,再也不能通过直接向视频缓冲区拷贝数据的办法来显示信息了,那通过什么? 答案是通过“设备环境”来输出信息。
- “设备环境”介绍:
- 代码效果演示:(该效果在虚拟机中(windows7 64位)显示不出来,所以以照片的形式现实,代码照样解读就好)
- 代码初步解读:
这里,有很多地方我们之后会介绍,先说一下原理,首先创建窗口,绘制窗口,绘制窗口时会发送WM_PAINT消息,接收该消息会初始化中间一个字符串。然后设置定时器,定时器每0.1秒把右边窗口的图像绘制到左边去,注意,定时器过程里面的绘制图像函数,其直接绘制不通过WM_PAINT消息,所以,在窗口过程中也不会发现其更新代码。 - “环境设备理解”:
- 现在用其他程序将右边窗口的客户区的一部分覆盖掉,通过左边窗口的变化可以惊奇地发现,右边窗口客户区的内容并不是程序自己输出到客户区的那句文本,而是以客户区为矩形区域的屏幕上的内容,它竟然包括其他窗口覆盖在上面的内容。这就意味着,扫雷游戏和纸牌游戏通过自己的客户区对应的设备环境图形,图形数据竟然画到了 DcCopy 窗口客户区对应的设备环境。
- 这个例子验证了“设备环境”只是“环境”而不是“设备”,它并不存储发给它的图形数据,图形数据透过它所描述的“设备”上,每个窗口客户区的“设备环境”对应的设备都是屏幕,但由于它们在位置上可能重叠,所以向一个窗口的客户区写数据相当于同时写了下层窗口的客户区。
理解这句话:“每个窗口客户区的’设备环境'对应的设备都是屏幕”,其每个设备都有一个“设备环境”,向环境设备中写入数据,就相当于向屏幕上写入内容,这样就能做到很好的隔离,其通过设备环境句柄来进行写入操作,写入并不代表一定能输出,最后还有一层过滤装置,在决定谁能输出到屏幕上。注意:设备环境并不存储数据,你可以认为“窗口向设备环境写入就相当于屏幕写入,但是中间加了一层Windows过滤”。
- 深入理解:
- 经过Windows过滤,并不是所有内容都会写道屏幕上,只有没有背其他窗口覆盖的才会写到屏幕上。
- “设备环境”只是一个环境,是设备属性的一组定义,程序输出的图形数据透过“设备环境”定向到了具体设备上,“设备环境”本身不存储这些数据。
- 桌面不是一层层纸,而是一个用粉笔写的公告黑板,一个窗口相当于划了一块空间写公告,写另一个告示时需要把牢告示的内容擦去一部分以便写新内容,擦去的内容也就不存在了,如果要恢复老告示,那么必须把擦去的部分重新写上去。
注意:去“图形数据”是“数据”而不是“图画”,所以,发送的时候当然是全部发送,而不是只发送无效区域的图像, 所以,从这个角度来讲,其相当于一张张纸发送给操作系统,操作系统作为管理员根据实际情况绘制到黑板上,当 黑板需要修改一个区域,操作系统根据新的纸张重新绘制。对应窗口来说,其根本不关系如何绘制,绘制成啥样, 它只负责将图形数据完好无损的发送给操作系统,剩下的由操作系统来解决。
- 获取设备环境句柄:
- 介绍:
想要对任何设备绘图,首先必须获取设备的“设备环境句柄”(hDC),几乎所有的GDI绘制的操作目标都是 hDC,在程序中获得一个hDC有以下几种方法。 - 获取hDC的方法:
- BeginPaint 函数得到hdc:最常用的方法是WM_PAINT消息中用 BeginPaint 函数得到hdc,下面是WM_PAINT的一般操作:
函数解读:
1. 该函数返回的仅仅是需要刷新区域的hDC,即无效区域的hDC, 无法用它绘制到其他地方去。
2. 由于窗口过程每次接收的WM_PAINT消息时无效区域可能都不同,所以这个hDC的值仅仅在 WM_PAINT 消息中有效,程序不应该保存它并在其WM_PAINT以外的代码中使用。
3. 基于同样的道理,BeginPaint和EndPaint函数只能在WM_PAINT消息中使用,因为只有这时候才有无效区域。 - GetDC获取 hDC:程序中常常有这种需求,就是在非WM_PAINT消息中主动绘画客户区,由于BeginPaint和EndPaint函数必须在WM_PAINT消息中使用,所以这时必须采用另外的方法获取hDC,可以采用以下方法:
函数解读:
1. GetDC函数返回的 hDC 对应窗口的整个客户区,当时用完毕的时候,hDC 必须用 ReleaseDC 函数释放。
2. 对于GetDC获取的 hDC, Windows 建议使用的范围仅限于单条消息内,即程序处理某条消息,“获取-使用-释放”,当下次消息,再“获取-使用-释放”。- CreateDC 函数 创建一个DC:上面两种方法都是获取窗口的hDC,如果要操作的是其他的对象,如打印机、位图等,就不能使用上面这两种函数了。当绘图的对象是一个设备的时候,可以用 CreateDC函数来建立一个DC:
- pwszDriver 指向设备名称,如显示设备的设备名是DISPLAY,打印机一般的设备名是WINSPOOL。
- 下面这几句代码建立的DC是对应着整个屏幕:
- CreateCompatibleDC 创建一个与位图对象关联的句柄:当绘图对象是位图的时候,同样需要一个与位图句柄相联系的DC,这时可以用函数CreateCompatibleDC 来创建一个显示表面且仅存在于内存中的DC:
参数中的hDC是一个参考的DC句柄,如果指定的参数为NULL,那么建立的DC将和当前的设置兼容,为了用 CreateCompatibleDC 建立的DC 绘制一个位图,还需要用 selectObject 函数将 hDC 和位图句柄联系起来。在这之后,通过hDC进行的挥之操作将像素更新到位图中。 - DeleteDC删除:用 CreateDC 和 CreateCompatibleDC 函数建立的 hDC 在使用结束后,必须用 DeleteDC函数删除,注意这里不能用 ReleaseDC,这个函数是GetDC配合实用的。
- 函数使用时间:用 BeginPaint 和 EndPaint,以及GetDC 获取的 hDC 的使用时间不能超过本条消息,而 CreateDC 和 CreateCompatibleDC 建立的 hDC 则没有这种限制,可以在任何适合建立它并且一直使用到不再需要为止。
- CreateDC 函数 创建一个DC:上面两种方法都是获取窗口的hDC,如果要操作的是其他的对象,如打印机、位图等,就不能使用上面这两种函数了。当绘图的对象是一个设备的时候,可以用 CreateDC函数来建立一个DC:
- BeginPaint 函数得到hdc:最常用的方法是WM_PAINT消息中用 BeginPaint 函数得到hdc,下面是WM_PAINT的一般操作:
- 介绍:
win32 7.1 设备环境
最新推荐文章于 2022-01-12 10:51:14 发布