C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 Как рисовать прозрачные битмапы / Bitmap, Region / Графика

Как рисовать прозрачные битмапы.

"Прозрачной" называется та часть картинки, которая не изменяет содержимого экрана. Например, функция DrawIcon может создавать изображения с прозрачностью. Так же можно добиться прозрачности при помощи функции BitBlt, однако прийдётся воспользоваться дополнительным кодом.

Сперва необходимо получить содержимое области, где будет нарисован битмап, чтобы сохранить это фоновое изображение в памяти контекста устройства (DC). Далее накладывается маска на область фона, которая отвечает за непрозрачную часть битмапа, а также на все прозрачные пиксели битмапа. Потом, используется растровая операция XOR, чтобы совместить битмап картинки с битмапом фоновой картнки. В заключении, при помощи BitBlt, совмещённая картинка помещается в DC.

Теперь более подробно рассмотрим процесс рисования прозрачных битмапов:

  1. Создаём DC для хранения битмапа.
  2. В DC выбираем битмап.
  3. Создаём в памяти DC для хранения конечной картинки. В него будем выводить выводить конечную картинку.
  4. Копируем часть экрана, на которое будет наложена картинка в конечный DC.
  5. Создаём "маску AND", которая содержит маску цветов для рисования (непрозрачная часть картинки). Для этого делаем следующие шаги:
    1. Устанавливаем фоновый цвет в DC в цвет, который будет прозрачным в картинке.
    2. Создаём монохромный DC.
    3. Применяем BitBlt к картинке в монохромном DC.

    Путём установки фонового цвета удовлетворяющих пикселей в белый(1), а всех остальных в чёрный(0), будет создана маска AND для битмапа.

  6. Используем BitBlt с растровой операцией SRCAND, чтобы скопировать маску AND на конечный DC.
  7. Используем BitBlt с растровой операцией SRCAND, чтобы скопировать инверсию маски AND в DC картинки.
  8. Используем BitBlt с растровой операцией SRCPAINT, чтобы скопировать DC картинки в конечный DC.
  9. Используем BitBlt, чтобы скопировать содержимое конечного DC в соответствующую часть экрана.

Следующая функция демонстрирует описанные выше шаги:

   void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart,
                           short yStart, COLORREF cTransparentColor)
   {
   BITMAP     bm;
   COLORREF   cColor;
   HBITMAP    bmAndBack, bmAndObject, bmAndMem, bmSave;
   HBITMAP    bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
   HDC        hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
   POINT      ptSize;

   hdcTemp = CreateCompatibleDC(hdc);
   SelectObject(hdcTemp, hBitmap);   // Выбираем битмап

   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
   ptSize.x = bm.bmWidth;            // Получаем ширину битмапа
   ptSize.y = bm.bmHeight;           // Получаем высоту битмапа
   DPtoLP(hdcTemp, &ptSize, 1);      // Конвертируем из координат
                                     // устройства в логические
                                     // точки

   // Создаём несколько DC для хранения временных данных.
   hdcBack   = CreateCompatibleDC(hdc);
   hdcObject = CreateCompatibleDC(hdc);
   hdcMem    = CreateCompatibleDC(hdc);
   hdcSave   = CreateCompatibleDC(hdc);

   // Создаём битмап для каждого DC.

   // Монохромный DC
   bmAndBack   = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

   // Монохромный DC
   bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

   bmAndMem    = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
   bmSave      = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);

   // В каждом DC должен быть выбран объект битмапа для хранения
   // пикселей.
   bmBackOld   = SelectObject(hdcBack, bmAndBack);
   bmObjectOld = SelectObject(hdcObject, bmAndObject);
   bmMemOld    = SelectObject(hdcMem, bmAndMem);
   bmSaveOld   = SelectObject(hdcSave, bmSave);

   // Устанавливаем режим маппинга.
   SetMapMode(hdcTemp, GetMapMode(hdc));

   // Сохраняем битмап, переданный в параметре функции, так как
   // он будет изменён.
   BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);

   // Устанавливаем фоновый цвет (в исходном DC) тех частей,
   // которые будут прозрачными.
   cColor = SetBkColor(hdcTemp, cTransparentColor);

   // Создаём маску для битмапа путём вызова BitBlt из исходного
   // битмапа на монохромный битмап.
   BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
          SRCCOPY);

   // Устанавливаем фоновый цвет исходного DC обратно в
   // оригинальный цвет.
   SetBkColor(hdcTemp, cColor);

   // Создаём инверсию маски.
   BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
          NOTSRCCOPY);

   // Копируем фон главного DC в конечный.
   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart,
          SRCCOPY);

   // Накладываем маску на те места, где будет помещён битмап.
   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);

   // Накладываем маску на прозрачные пиксели битмапа.
   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);

   // XOR-им битмап с фоном на конечном DC.
   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);

   // Копируем на экран.
   BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
          SRCCOPY);

   // Помещаем оригинальный битмап обратно в битмап, переданный в
   // параметре функции.
   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);

   // Удаляем битмапы из памяти.
   DeleteObject(SelectObject(hdcBack, bmBackOld));
   DeleteObject(SelectObject(hdcObject, bmObjectOld));
   DeleteObject(SelectObject(hdcMem, bmMemOld));
   DeleteObject(SelectObject(hdcSave, bmSaveOld));

   // Удаляем DC из памяти.
   DeleteDC(hdcMem);
   DeleteDC(hdcBack);
   DeleteDC(hdcObject);
   DeleteDC(hdcSave);
   DeleteDC(hdcTemp);
   }

Следующий пример показывает как вызывать приведённую выше функцию DrawTransparentBitmap:

   DrawTransparentBitmap(hdc,         // Конечный DC.

                         hBitmap,     // Битмап, который будет нарисован.
                         xPos,        // координата X.
                         yPos,        // координата Y.
                         0x00FFFFFF); // Цвет для прозрачных
                                      // пикселей (в данном случае
                                      // белый).