摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P136
显示器上所显示的线条外观也受定义在设备环境中绘图模式的影响。设想画一条直线,其颜色由画笔的颜色和画线显示区域的共同决定。你能够使用同一支画笔在白色表面上绘制出黑色的线条,在黑色的表面上绘制出白色的线条,同时不必知道表面的确切颜色。这样对你有用吗?通过设定绘图模式,这些功能都是可以做到的。
当 Windows 使用一个画笔绘制直线时,它实际上是在将画笔的像素颜色和目标显示表面的像素颜色按位进行布尔运算。对像素颜色执行一个按位布尔运算称为“光栅操作”(raster operation,ROP),简称“ROP”,因为绘制一条直线只涉及两种像素颜色(即画笔和目标),这里的布尔运算就被称为“二元光栅操作”,或者“ROP2”。Windows 定义了 16 种 ROP2 运算码,每一个都表示 Windows 组合画笔像素色和目标像素色的一种方式。在默认的设备环境中,绘图模式是 R2_COPYPEN,意思是 Windows 只是简单地将画笔像素的颜色复制到目标像素上,这也是我们通常所熟知的。还有 15 种其他 ROP2 代码。
16 种不同的 ROP2 运算码是怎样得来的呢?为了做一个示范,我们假设每个像素使用 1 位的单色系统。目标颜色(窗口客户区的颜色)可以是黑色(用 0 表示)或者白色(用 1 表示),画笔也可以是黑色或白色。这样,使用黑色或白色画笔在黑色或白色目标上画图就有四种组合:白色画笔与白色目标、白色画笔与黑色目标、黑色画笔与白色目标、黑色画笔与黑色目标。
画笔在目标上绘制后会得到什么颜色呢?一种可能是画出的线总是黑色,不管画笔和目标颜色怎样,这种绘图方式由 ROP2 运算码中的 R2_BALCK 表示。另外一种可能是只有当画笔颜色与目标颜色都是黑色时,绘制的线才是白色,其他情况下绘制的线都是黑色。尽管这有些奇怪,但是 Windows 还是为这种绘图方式起了一个名字,称为 R2_NOTMERGEPEN。Windows 把目标像素与画笔像素进行了一个“位或”运算,然后将结果取反得到颜色。
下表显示了所有 16 中 ROP2 绘图模式,表中指出了画笔颜色(P)和目标颜色(D)是如何组合形成最终颜色的。在“布尔操作”一栏,我们使用 C 语言的位运算符显示目标像素与画笔像素的组合方式。
画笔(P): 目标(D): | 1 1 | 1 0 | 0 1 | 0 0 | 布尔操作 | 绘图模式 |
---|---|---|---|---|---|---|
结果: | 0 | 0 | 0 | 0 | 0 | R2_BLACK |
0 | 0 | 0 | 1 | ~(P | D) | R2_NOTMERGEPEN | |
0 | 0 | 1 | 0 | ~P & D | R2_MASKNOTPEN | |
0 | 0 | 1 | 1 | ~P | R2_NOTCOPYPEN | |
0 | 1 | 0 | 0 | P & ~D | R2_MASKPENNOT | |
0 | 1 | 0 | 1 | ~D | R2_NOT | |
0 | 1 | 1 | 0 | P ^ D | R2_XORPEN | |
0 | 1 | 1 | 1 | ~(P & D) | R2_NOTMASKPEN | |
1 | 0 | 0 | 0 | P & D | R2_MASKPEN | |
1 | 0 | 0 | 1 | ~ (P ^ D) | R2_NOTXORPEN | |
1 | 0 | 1 | 0 | D | R2_NOP | |
1 | 0 | 1 | 1 | ~P | D | R2_MERGENOTPEN | |
1 | 1 | 0 | 0 | P | R2_COPYPEN(默认) | |
1 | 1 | 0 | 1 | P | ~D | R2_MERGEPENNOT | |
1 | 1 | 1 | 0 | P | D | R2_MERGEPEN | |
1 | 1 | 1 | 1 | 1 | R2_WHITE |
可以通过调用下面的函数设置一种新的绘图模式:
参数 iDrawMode 是上表中“绘图模式”栏中给出的值。可以使用下面的函数来获取当前绘图模式:
设备环境默认使用 R2_COPYPEN 模式,它简单地用画笔颜色替代目标颜色。在 R2_NOTCOPYPEN 绘图模式下,若画笔为黑色,则绘制成白色;若画笔为白色,则绘制成黑色。在 R2_BLACK 模式下,不管画笔或者背景的颜色,Windows 总是绘制黑色。相反,在 R2_WHITE 模式下则总是绘制成白色。R2_NOP 表示 “不操作”,它让目标颜色保持不变。
我们已经讨论了单色系统的绘图模式。然而,大多数系统都是彩色的。在彩色系统中,Windows 为画笔和目标像素的每个颜色位执行绘图模式的位运算,也是使用上表中描述的 16 中 ROP2 代码。R2_NOT 绘图模式总是将目标颜色取反来确定绘制的线的颜色,而不管画笔的颜色。例如,在颜色为 cyan(一种青色)的目标上用 R2_NOT 模式画出的线总是 megenta(一种紫红色)。除了在中等灰度的背景上,在 R2_NOT 模式下画出的图形和背景颜色差别通常较大,总可以被清晰地辨认出来。