Выше уже было сказано, что одиннадцатый аргумент функции StretchBlt() - это код растровой операции. Другими словами, это код, который определяет, как при операции будут взаимодействовать биты, определяющие заливку и изображение совместимого контекста с изображением на действительном контексте. Комбинируются биты на основе логических операций над ними. По укоренившейся в книге по программированию для Windows традиции, эти операции записываются в обратной польской нотации (не путать с венгерской, автор польской нотации не имеет к Microsoft ни малейшего отношения).

По той же традиции, биты, определяющие bitmap совместимого контекста, обозначают буквой S (source - источник, исходный), биты заливки - буквой P (pattern - образец), а биты, на которых будет прорисовываться изображение - буквой D (destination - назначение, место назначения). Операции обозначаются следующим образом: a - побитовое И (AND), n - побитовое НЕТ (NO), o - побитовое ИЛИ (OR), x - побитовое исключающее ИЛИ (XOR).

Несколько слов о польской нотации. В ней операции записываются слева направо. Знак операции следует за операндами. Появление знака операции означает, что нужно произвести следующие действия:
 - взять два последних операнда  - произвести с ними требующуюся операцию  - записать результат на место последних двух операндов.

Фактически польская нотация описывает действия таким образом, словно операнды и операции находятся в стеке, для чего, собственно, эта польская нотация и была изобретена.

Обозначив знак операции как Op, в польской нотации действия с битами можно записать таким образом:

  PSOp

Это говорит о необходимости взять пиксель патерны и прорисоваемого bitmap'а и произвести над ним операцию. Если в операции участвуют три операнда, то получим:

  DPSOp1Op2

Что мы должны сделать в этом случае? Правильно, сначала произвести действие, определяемое Op1, с битами патерны и прорисовываемым bitmap'ом, после этого произвести Op2 с полученным результатом и битами действительного контекста. Ничего сложного здесь нет.

Каждый код растровой операции представляется 32-битным целым. Старшее слово кода представляет собой индекс битовой операции, младшее - код операции. Как определяется индекс операции?

Давайте представим, что нам необходимо определить индекс растровой операции, определяемой в польской нотации записью DPSxx. Попутно можно определить и индекс операции PSx. Запишем друг под другом ОПРЕДЕЛЕННЫЕ значения P,S и D, а под ними - результаты побитовых операций PSx и DPSxx:

 

P 1 1 1 1 0 0 0 0
S 1 1 0 0 1 1 0 0
D 1 0 1 0 1 0 1 0

PSx 0 0 1 1 1 1 0 0
DPSxx 0 0 0 1 0 1 1 0

Итак, индекс операции PSx - 0x3C, а индекс операции DPSxx - 0x96.
Уважаемый читатель, я прошу обратить внимание на то, что друг под другом записываются не произвольные, а строго определенные значения. Эти значения позволяют перебрать все возможные комбинации патерны, исходного и целевого bitmap'ов. Теперь, когда все стало ясно, вы можете попробовать попрактиковаться в определении индексов дюбых операций. Несмотря на то, что существуют 256 индексов растровых операций, на практике используются только некоторые из них. В файле wingdi.h для наиболее часто используемых растровых операций определены идентификаторы, которые приведены в таблице:

Краткое описание кодов растровых операций

Наименование Индекс
операции
Польская
запись
Эффект
BLACKNESS 0x00 0 Заполнение действительного контекста черным цветом
NOTSRCERASE 0x11 DSon  
NOTSRCCOPY 0x33 Sn Прорисовываемый bitmap отображается в негативном виде
DSTINVERT 0x55 Dn Изображение действительного контекста проявляется негативным
PATINVERT 0x5A DPx  
SRCINVERT 0x66 DSx  
SRCAND 0x88 DSa  
MERGEPAINT 0xBB DSno  
MERGECOPY 0xC0 PSa  
SRCCOPY 0xCC S Копирование прорисовываемого bitmap'а на действительный контекст
SCRPAINT 0xEE DSo  
PATCOPY 0xF0 P Копирование патерны на действительный контекст
PATPAINT 0xFB DPSnoo  
WHITENESS 0xFF 1 Заполнение действительного контекста белым цветом

На основании данных таблицы я затрудняюсь объяснить, как изменяется изображение при использовании разных растровых операций. Рекомендую читателю запустить приведенную выше программу несколько раз, и каждый раз в функции StretchBlt() указывать новую растровую операцию.

Теперь и одиннадцатый аргумент PatBlt() стал ясным и понятным - я просто копирую bitmap в окно. Только и всего. Кстати, понимание логики работы с растровыми операциями может позволить избежать трудоемких преобразований bitmap'ов перед копированием.