PatBlt (”pattern block transfer“) is the simplest of the three ”blt“ functions. It's really quite different from BitBlt and StretchBlt in that it uses only one device context. But PatBlt is nonetheless a reasonable place to begin.
In Chapter 12 you encountered the device context attribute called the drawing mode. This attribute can be set to 1 of 16 binary raster operation (ROP2) codes. When you draw a line, the drawing mode determines the type of logical operation that Windows performs on the pixels of the pen and the pixels of the device context destination. PatBlt is similar to the drawing mode except that it alters a rectangular area of the device context destination rather than merely a line. It performs a logical operation involving the pixels in this rectangle and a ”pattern.“ This ”pattern“ is nothing new—pattern is simply another name for a brush. For this pattern, PatBlt uses the brush currently selected in the device context.
The syntax of PatBlt is:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, dwROP) ;
The xDest, yDest, xWidth, and yHeight parameters are in logical units. The logical point (xDest, yDest) specifies the upper left corner of a rectangle. The rectangle is xWidth units wide and yHeight units high. (See the section entitled ”Blt Coordinates,“ later in this chapter, for a more precise definition of these values.) This is the rectangular area that PatBlt alters. The logical operation that PatBlt performs on the brush and the destination device context is determined by the dwROP parameter, which is a doubleword (32-bit integer) ROP code—not one of the ROP2 codes used for the drawing mode.
Windows has 256 ROP codes. These define all possible logical combinations of a source display area, a destination display area, and a pattern (or brush). The device driver for the video display supports all 256 raster operations through the use of a ”compiler“ of sorts. This compiler uses the 32-bit ROP code to create a set of machine-language instructions on the stack that can carry out this logical operation on the pixels of the display; it then executes these instructions. The high word of the 32-bit ROP code is a number between 0 and 255. The low word is a number that assists the device driver ”compiler“ in constructing the machine code for the logical operation. Fifteen of the 256 ROP codes have names. If you want to use any of the others, you'll have to look up the number in the table in the Programmer's Reference included with the Windows Software Development Kit.
Because the PatBlt function uses only a destination device context and a pattern (and not a source device context), it can accept only a subset of these 256 ROP codes—that is, the 16 ROP codes that use only the destination device context and a pattern. The 16 raster operations supported by PatBlt are shown in the table below. You'll note that this is similar to the table showing ROP2 codes on page 551 of Chapter 12.
Pattern (P): | 1 | 1 | 0 | 0 | Boolean | ROP | |
Destination (D): | 1 | 0 | 1 | 0 | Operation | Code | Name |
Result: | 0 | 0 | 0 | 0 | 0 | 000042 | BLACKNESS |
0 | 0 | 0 | 1 | ~(P|D) | 0500A9 | ||
0 | 0 | 1 | 0 | ~P & D | 0A0329 | ||
0 | 0 | 1 | 1 | ~P | 0F0001 | ||
0 | 1 | 0 | 0 | P & ~D | 500325 | ||
0 | 1 | 0 | 1 | ~D | 550009 | DSTINVERT | |
0 | 1 | 1 | 0 | P ^ D | 5A0049 | PATINVERT | |
0 | 1 | 1 | 1 | ~(P & D) | 5F00E9 | ||
1 | 0 | 0 | 0 | P & D | A000C9 | ||
1 | 0 | 0 | 1 | ~(P ^ D) | A50065 | ||
1 | 0 | 1 | 0 | D | AA0029 | ||
1 | 0 | 1 | 1 | ~P|D | AF0229 | ||
1 | 1 | 0 | 0 | P | F00021 | PATCOPY | |
1 | 1 | 0 | 1 | P|~D | F50225 | ||
1 | 1 | 1 | 0 | P|D | FA0089 | ||
1 | 1 | 1 | 1 | 1 | FF0062 | WHITENESS |
For a monochrome device context, a 1 bit corresponds to a white pixel and a 0 bit to a black pixel. Destinations and patterns that are either pure black or pure white are the easiest to consider when you start thinking about PatBlt. For instance, if you call:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, 0x5F00E9L) ;
then the rectangular area that begins at the logical point (xDest, yDest) and that is xWidth pixels wide and yHeight pixels high will be colored black only if the destination was originally white and you had WHITE_BRUSH selected in the device context. Otherwise, the destination will be colored white. Of course, even in a monochrome device context, destinations and brushes can be dithered combinations of black and white pixels. In this case, Windows performs the logical combination on a pixel-by-pixel basis, which can lead to some odd results. For instance, if your destination has already been colored with GRAY- BRUSH, and GRAY_BRUSH is also the current brush selected in the device context, then:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, PATINVERT) ;
will set the destination to either pure white or pure black, depending on how the dithered pixels of the destination coincide with the dithered pixels of the brush.
Color introduces more complexities. Windows performs the logical operation for each color plane separately or each set of color bits separately, depending on how the memory of the device is organized.
Some of the more common uses of PatBlt are shown below. If you want to draw a black rectangle, you call:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, BLACKNESS) ;
To draw a white rectangle, use:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, WHITENESS) ;
The function:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, DSTINVERT) ;
always inverts the colors of the rectangle. If WHITE_BRUSH is currently selected in the device context, then the function:
PatBlt (hdc, xDest, yDest, xWidth, yHeight, PATINVERT) ;
also inverts the rectangle.
You'll recall that the FillRect function fills in a rectangular area with a brush:
FillRect (hdc, &rect, hBrush) ;
The FillRect function is equivalent to the following code:
hBrush = SelectObject (hdc, hBrush) ;
PatBlt (hdc, rect.left, rect.top,
rect.right - rect.left,
rect.bottom - rect.top, PATCOPY) ;
SelectObject (hdc, hBrush) ;
In fact, this code (in more optimized assembly language) is what Windows uses to execute the FillRect function. When you call:
InvertRect (hdc, &rect) ;
Windows translates it into the function:
PatBlt (hdc, rect.left, rect.top,
rect.right - rect.left,
rect.bottom - rect.top, DSTINVERT) ;