调色板工作原理

来源:互联网 发布:php到底是做什么的 编辑:程序博客网 时间:2024/04/19 13:47
调色板工作原理
显示器可以被设置成16、256、64K、真彩色等显示模式,前两种模式需要调色板。在16或256色模式下,程序必须将想要显示的颜色正确地设置到调色板中,这样才能显示出预期的颜色。

      如图为一个256色显示模式中的调色板的工作原理




      Windows是一个多任务操作系统,可以同时运行多个程序。如果有几个程序都要设置调色板,就有可能产生冲突。为了避免这种冲突,Windows使用逻辑调色板来作为使用颜色的应用程序和系统调色板(物理调色板)之间的缓冲。

      在Windows中,应用程序是通过一个或多个逻辑调色板来使用系统调色板(物理调色板)。在256色系统调色板中,Windows保留了20种颜色作为静态颜色,这些颜色用作显示Windows界面,应用程序一般不能改变。缺省的系统调色板只包含这20种静态颜色,调色板的其它项为空。应用程序要想使用新的颜色,必须将包含有所需颜色的逻辑调色板实现到系统调色板中。在实现过程中,Windows首先将逻辑调色板中的项与系统调色板中的项作完全匹配,对于逻辑调色板中不能完全匹配的项,Windows将其加入到系统调色板的空白项中,系统调色板总共有236个空白项可供使用,若系统调色板已满,则Windows将逻辑调色板的剩余项匹配到系统调色板中尽可能接近的颜色上。

  每个设备上下文都拥有一个逻辑调色板,缺省的逻辑调色板只有20种保留颜色,如果要使用新的颜色,则应该创建一个新的逻辑调色板并将其选入到设备上下文中。但光这样还不能使用新颜色,程序只有把设备上下文中的逻辑调色板实现到系统调色板中,新的颜色才能实现。在逻辑调色板被实现到系统调色板时,Windows会建立一个调色板映射表。当设备上下文用逻辑调色板中的颜色绘图时,GDI绘图函数会查询调色板映射表以把像素值从逻辑调色板的索引转换成系统调色板的索引,这样当像素被输出到视频内存中时就具有了正确的颜色值。
      下图说明了这种映射关系,从图中读者可以体会到逻辑调色板的缓冲作用。在该图中,GDI绘图函数使用逻辑调色板的索引1中的颜色来绘图,通过查询调色板映射表,得知系统调色板中的第23号索引与其完全匹配,这样实际输出到视频内存中的像素值是23。注意图中还演示了颜色的不完全匹配,即逻辑调色板中的索引15和系统调色板中的索引46。



      每个要使用额外颜色的窗口都会实现自己的逻辑调色板,逻辑调色板中的每种颜色在系统调色板中都有相同或相近的匹配。调色板的实现优先权越高,匹配的精度也就越高。Windows规定,活动窗口的逻辑调色板(如果有的话)具有最高的实现优先权。这是因为活动窗口是当前与用户交互的窗口,应该保证其有最佳的颜色显示。非活动窗口的优先权是按Z顺序自上到下确定的(Z顺序就是重叠窗口的重叠顺序)。活动窗口有权将其逻辑调色板作为前景调色板实现,非活动窗口则只能实现背景调色板。
      提示:术语活动窗口(Active window)或前台窗口(Foreground window)是指当前与用户交互的窗口,活动窗口的顶端的标题条呈高亮显示,而非活动窗口的标题条则是灰色的。活动窗口肯定是一个顶层窗口(Top-level window),顶层窗口是指没有父窗口或父窗口是桌面窗口的窗口,这种窗口一般都有标题和边框,主要包括框架窗口和对话框。术语重叠窗口是指作为应用程序主窗口的窗口,我们可以把对话框看成是一种特殊的重叠式窗口。

     CreatePalette只是创建了逻辑调色板,此时调色板只是一张孤立的颜色表,还不能对系统产生影响。程序必需调用CDC::SelectPalette把逻辑调色板选入到要使用它的设备上下文中,然后调用CDC::RealizePalette把逻辑调色板实现到系统调色板中。函数的声明为:

CPalette* SelectPalette( CPalette* pPalette, BOOL bForceBackground );
该函数把指定的调色板选择到设备上下文中。参数pPalette指向一个CPalette对象。参数bForceBackground如果是TRUE,那么被选择的调色板总是作为背景调色板使用,如果bForceBackgroundFALSE并且设备上下文是附属于某个窗口的,那么当窗口是活动窗口或活动窗口的子窗口时,被选择的调色板将作为前景调色板实现,否则作为背景调色板实现。如果使用调色板的是一个内存设备上下文,则该参数被忽略。函数返回设备上下文原来使用的调色板,若出错则返回NULL

UINT RealizePalette( );
该函数把设备上下文中的逻辑调色板实现到系统调色板中。函数的返回值表明调色板映射表中有多少项被改变了。

 

如果某一个窗口要显示特殊的颜色,那么一般应该在处理WM_PAINT消息时实现自己的逻辑调色板。也就是说,在OnPaintOnDraw函数中重绘以前,要调用SelectPaletteRealizePalette。如果窗口显示的颜色比较重要,则在调用SelectPalette时应该指定bForceBackground参数为FALSE

前景调色板具有使用颜色的最高优先级,它有无条件占用系统调色板(20种保留颜色除外)的权力,也就是说,如果需要,前景调色板将覆盖系统调色板的236个表项,而不管这些表项是否正被别的窗口使用。背景调色板则无权破坏系统调色板中的已使用项。

请读者注意,前景调色板应该是唯一。如果一个活动窗口同时要实现几个逻辑调色板,那么只能有一个调色板作为前景调色板实现,也即在调用CDC::SelectPalette时只能有一个bForceBackground被指定为FALSE,其它的bForceBackground必需为TRUE。通常是把具有输入焦点的窗口的调色板作为前景调色板实现,其它窗口只能使用背景调色板。如果活动窗口的子窗口全都使用前景调色板,则会导致程序的死循环。



 
原创粉丝点击