技术资料_Win9X下的GDI资源管理与图像库设计

Win9X下的GDI资源管理与图像库设计
与月共舞
2002.05.17

大家都知道,Win9X系列这个16/32位混合体,为了保持与16位应用程序的最大兼容,在很多方面与NT系列有很大的差别。虽然Win9X的寿命估计也没多久了,不过我想大家不会反对我在CnPack图像库中针对它进行优化设计吧:)

关于Win9X对USER和GDI资源管理方面的资料,网上能找到的很少,所以小弟也是一知半解,哪位成员有更多的资料还希望拿出来让大家分享。在此我简单谈谈Win9X下GDI资源的相关问题和与之相适应的设计,如有错误还请指正。

user子系统实现与窗口处理相关的功能,主要由user32.dll和16位的user.exe完成。user32的大部分功能都下移(thunk down)到16位的user中实现。

GDI(Graphics Device Interface)系统实现与图像绘制相关的功能,主要由GDI32.dll和16位的GDI.exe来完成。同样,只要有可能,GDI32函数也下移到16位的GDI中。

操作系统使用全局堆来存储所有的user对象和GDI对象,user.exe使用两个2M的32位堆和一个64K的16位堆存放窗口、菜单等user对象。GDI.exe使用一个32位堆和一个16位堆存放字体、位图、画刷、调色板等GDI对象。每一个对象实际上是一个特定数据结构的记录,保存在系统全局堆中,而对象的句柄(Handle)就是指向该对象在堆中具体位置的16位偏移量(操作系统也许会将其变换成32位)。其中WND和Menu分别存放在32位的user堆中,Font和regions存放在32位的GDI堆中,因为它们相对来说都较大。为了使16位代码能使用存放在32位堆中的数据,它们同时在16位堆中保存了其在32位堆中的偏移量,而句柄则指向该16位偏移量。

我们在“资源状况”中看到的三个百分值“系统资源”、“用户资源”、“GDI资源”含义如下:

  • “用户资源”即user资源,为两个32位堆和一个16位堆可用空间的百分比的最小值(通常总是16位堆的值)。
  • “GDI资源”为32位堆和16位堆可用空间的百分比的最小值(通常也总是16位堆的值)。
  • “系统资源”为前两者的最小值。

事实上,Win9X中,前面的百分比并不是真正的剩余空间百分比,而是剩余空间相对于总空间减去操作系统自身占用空间之比(一个干净的系统启动后通常系统资源为95%以上)。

GDI对象包括Bitmap、Brush、Palette、Font、Path、Pen和Region,我编写了一段代码在Win98SE下得到如下测试结果:
500个TBitmap(Width和Height设为10),占用GDI资源40%。
500个TBrush(Color各不相同,访问过Handle属性),占用GDI资源29%。
500个TPen(Color各不相同,访问过Handle属性),占用GDI资源29%。
500个16色的HPALETTE(用CopyPalette(SystemPalette16)创建),占用GDI资源44%。
500个256色的HPALETTE(用CreatePalette创建),占用GDI资源44%。

Delphi使用了一种精巧的方法来管理TBrush、TPen和TFont(参见Graphics.pas单元),两个参数完全一样的对象共享同一个句柄,所以这三种GDI对象在实际使用中消耗的资源并不多。

虽然Delphi也使用了基于引用的方法来实现位图共享,但TBitmap的实际使用中这种方法用处并不大。从测试数据中,我们可以看到Bitmap和Palette对GDI资源的占用是较大的,很多界面控件包在内部大量使用了Bitmap,做出来的程序其资源占用肯定也较多,这一点大家很容易证实。

基于以上的分析,我打算在CnPack图像库中进行如下设计:

  1. 图像库自身完全不使用GDI资源,位图对象不创建HBITMAP句柄,但内存数据格式与其保持兼容。
  2. 完全不使用调色板,只支持24位格式的位图和8位纯灰度位图(考虑32位)。
  3. 位图输入时,通过TBitmap或创建临时HBITMAP句柄,导入24位位图数据。
  4. 位图显示时使用SetDIBitsToDevice函数直接输出到DC。
  5. 图象绘制不使用Pen、Brush,不支持Canvas,而使用自已的代码来完成相关的功能。
  6. 文本显示使用平滑特效字绘制功能完成(参见平滑字体部分的设计说明)。
  7. 在图像库中实现透明、Alpha混合、抗锯齿等Win9X不提供的功能。
  8. 提供与TBitmap、DC和其它图像类的转换接口,如果需要使用GDI函数,用TBitmap、TCanvas或其它方式来实现。

关于user资源方面的更多说明,将在界面控件设计中描述(其实是现在我还不知道^o^)。

CNPACK开发中心