这时就需要使用Windows调色盘管理器(在Windows 3.0中提出)了。Windows保留了256种颜色中的20种,而允许应用程序修改其余的236种。(在某些情况下,应用程序最多可以改变256种颜色中的254种-只有黑色和白色除外-但这有一点麻烦)。Windows为系统保留的20种颜色(有时称为20种「静态」颜色)如表16-1所示。
表16-1 256种颜色显示模式中的20种保留的颜色 |
图素位 |
RGB值 |
颜色名称 |
图素位 |
RGB值 |
颜色名称 |
00000000 |
00 00 00 |
黑 |
11111111 |
FF FF FF |
白 |
00000001 |
80 00 00 |
暗红 |
11111110 |
00 FF FF |
青 |
00000010 |
00 80 00 |
暗绿 |
11111101 |
FF 00 FF |
洋红 |
00000011 |
80 80 00 |
暗黄 |
11111100 |
00 00 FF |
蓝 |
00000100 |
00 00 80 |
暗蓝 |
11111011 |
FF FF 00 |
黄 |
00000101 |
80 00 80 |
暗洋红 |
11111010 |
00 FF 00 |
绿 |
00000110 |
00 80 80 |
暗青 |
11111001 |
FF 00 00 |
红 |
00000111 |
C0 C0 C0 |
亮灰 |
11111000 |
80 80 80 |
暗灰 |
00001000 |
C0 DC C0 |
美元绿 |
11110111 |
A0 A0 A4 |
中性灰 |
00001001 |
A6 CA F0 |
天蓝 |
11110110 |
FF FB F0 |
乳白色 |
for (i = 0 ; i < 65 ; i++) { rect.left = i * cxClient / 65 ; rect.top = 0 ; rect.right = (i + 1) * cxClient / 65 ; rect.bottom = cyClient ; hBrush = CreateSolidBrush (RGB(min (255, 4 * i), min (255, 4 * i), min (255, 4 * i))) ; FillRect (hdc, &rect, hBrush) ; DeleteObject (hBrush) ; }
如果程序在逻辑调色盘中指定一种颜色,该颜色又是20种保留颜色之一,那么Windows将把逻辑调色盘项目映像给该颜色。另外,如果两个或多个应用程序都在它们的逻辑调色盘中指定了同一种颜色,那么这些应用程序将共享系统调色盘项目。程序可以通过将PALETTEENTRY结构的peFlags字段指定为常数PC_NOCOLLAPSE来忽略该内定状态(其余两个可能的标记是PC_EXPLICIT(用于显示系统调色盘)和PC_RESERVED(用于调色盘动画),我将在本章的后面展示这两个标记)。
要帮助组织系统调色盘,Windows调色盘管理器含有两个发送给主窗口的消息。
第一个是QM_QUERYNEWPALETTE。当主窗口活动时,该消息发送给主窗口。如果程序在您的窗口上绘画时使用了调色盘管理器,则它必须处理该消息。GRAYS2展示具体的作法。程序获得设备内容句柄,并选进调色盘,呼叫RealizePalette,然后使窗口失效以产生WM_PAINT消息。如果显现了逻辑调色盘,则窗口消息处理程序从该消息传回TRUE,否则传回FALSE。
当系统调色盘改成与WM_QUERYNEWPALETTE消息的结果相同时,Windows将WM_PALETTECHANGED消息发送给由目前活动的窗口来启动并终止处理窗口链的所有主窗口。这允许前台窗口有优先权。传递给窗口消息处理程序的wParam值是活动窗口的句柄。只有当wParam不等于程序的窗口句柄时,使用调色盘管理器的程序才会处理该消息。
通常,在处理WM_PALETTECHANGED时,使用自订调色盘的任何程序都呼叫SelectPalette和RealizePalette。后续的窗口在消息处理期间呼叫RealizePalette时,Windows首先检查逻辑调色盘中的RGB颜色是否与已加载到系统调色盘中的RGB颜色相匹配。如果两个程序需要相同的颜色,那么这两个程序就共同使用一个系统调色盘项目。接下来,Windows检查未使用的系统调色盘项目。如果都已使用,则逻辑调色盘中的颜色从20种保留项目映像到最近的颜色。
如果不关心程序非活动时显示区域的外观,那么您不必处理WM_PALETTECHANGED消息。否则,您有两个选择。GRAYS2显示其中之一:在处理WM_QUERYNEWPALETTE消息时,它获得设备内容,选进调色盘,然后呼叫RealizePalette。这时就可以在处理WM_QUERYNEWPALETTE时呼叫InvalidateRect了。相反地,GRAYS2呼叫UpdateColors。这个函数通常比重新绘制窗口更有效,同时它改变窗口中图素的值来帮助保护以前的颜色。
使用调色盘管理器的许多程序都将让WM_QUERYNEWPALETTE和WM_PALETTECHANGED消息用GRAYS2所显示的方法来处理。
「调色盘」索引的颜色不同于调色盘RGB颜色,其高字节是1,而低字节的值是目前在设备内容中选择的、逻辑调色盘中的索引。在GRAYS3中,逻辑调色盘有65个项目,用于这些项目的索引从0到64。值
PALETTEINDEX (0)
指黑色,
PALETTEINDEX (32)
指灰色,而
PALETTEINDEX (64)
指白色。
因为Windows不需要执行最近颜色的搜索,所以使用调色盘索引比使用RGB值更有效。
系统调色盘
我在前面提过,Windows系统调色盘直接与显示卡上的硬件调色盘查询表相符(然而,硬件调色盘查询表可能比系统调色盘的颜色分辨率低)。程序可以通过呼叫下面的函数来获得系统调色盘中的某些或全部的RGB项目:
GetSystemPaletteEntries (hdc, uStart, uNum, &pe) ;