Советы по Delphi

Прозрачная растровая кисть


Следующий модуль выводит на форме два изображения. Одно используется в качестве фона, второе выводится на передний план. Изображение переднего плана отображается как изображение, обладающее "прозрачностью".

Более подробную информацию можно почерпнуть из комментариев.

    { Цель:     Вывод прозрачного изображения, загруженного из файла
Автор:    Michael Vincze (vincze@ti.com) Дата:     04/20/95 Использование: Создайте пустую форму с именем Form1, скомпилируйте и запустите проект. Ограничения: Данный модуль протестирован как с 16-, так и с 256-цветными изображениями. Подразумевается, что левый нижний пиксель изображения

содержит цвет, определяющий прозрачность. Примечание: Если этот модуль предполагается использовать для любой цели, пожалуйста, оставьте данный заголовок нетронутым в качестве подтверждения авторских прав. Если вы имеете к.-либо замечания или предложения по улучшению кода, пожалуйста, обратитесь к автору. Никаких ограничений по использованию данного кода не существует. Версия:  1.00  04/20/95  Первый выпуск }
unit Tbmpu;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;
type
TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } ImageForeGround: TImage; ImageBackGround: TImage; public { Public declarations } end;
procedure DrawTransparentBitmap (ahdc: HDC;
Image: TImage; xStart, yStart: Word);
var
Form1: TForm1;
implementation

{$R *.DFM}

procedure DrawTransparentBitmap (ahdc: HDC;
Image: TImage; xStart, yStart: Word); var
TransparentColor: TColor; cColor          : TColorRef; bmAndBack, bmAndObject, bmAndMem, bmSave, bmBackOld, bmObjectOld, bmMemOld, bmSaveOld       : HBitmap; hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave         : HDC; ptSize          : TPoint; begin
{ устанавливаем цвет прозрачности для левого нижнего пиксела изображения
}
TransparentColor := Image.Picture.Bitmap.Canvas.Pixels[0,
Image.Height - 1]; TransparentColor := TransparentColor or $02000000;

hdcTemp := CreateCompatibleDC (ahdc);
SelectObject (hdcTemp, Image.Picture.Bitmap.Handle); { выбираем изображение }

{ преобразуем размеры изображения к логическим точкам
}
ptSize.x := Image.Width;
ptSize.y := Image.Height;
DPtoLP (hdcTemp, ptSize, 1);  { преобразуем логические точки устройства }

{ создаем некие DCы для хранения временных данных
}
hdcBack   := CreateCompatibleDC(ahdc);
hdcObject := CreateCompatibleDC(ahdc);
hdcMem    := CreateCompatibleDC(ahdc);
hdcSave   := CreateCompatibleDC(ahdc);

{ создаем изображение для каждого DC
}

{ черно-белый DC
}
bmAndBack   := CreateBitmap (ptSize.x, ptSize.y, 1, 1, nil);
bmAndObject := CreateBitmap (ptSize.x, ptSize.y, 1, 1, nil);

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

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

{ устанавливаем соответствующих режим управления (Map) памятью
}
SetMapMode (hdcTemp, GetMapMode (ahdc));

{ сохраняем переданное сюда изображение, поскольку оно будет переписано
}
BitBlt (hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);

{ устанавливаем цвет фона исходного DC
в цвет прозрачности (чтобы фон был прозрачным) }
cColor := SetBkColor (hdcTemp, TransparentColor);

{ создаем объект-маску для изображения, выполняя 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, ahdc, 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 (ahdc, 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);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
{ создаем для двух изображений элементы управления Image и назначаем им родителей
}
ImageForeGround := TImage.Create (Form1);
ImageForeGround.Parent := Form1;
ImageBackGround := TImage.Create (Form1);
ImageBackGround.Parent := Form1;

{ загружаем изображения
}
ImageBackGround.Picture.LoadFromFile ('c:\delphi\images\splash\16color\earth.bmp');
ImageForeGround.Picture.LoadFromFile ('c:\delphi\images\splash\16color\athena.bmp');

{ устанавливаем размер изображения заднего плана равным размеру исходного изображения
}
with ImageBackGround do
begin
Left := 0; Top := 0; Width := Picture.Width; Height := Picture.Height; end;
{ устанавливаем размер изображения переднего плана, отцентрированного по отношению к изображению заднего плана
}
with ImageForeGround do
begin
Left := (ImageBackGround.Picture.Width - Picture.Width) div 2; Top := (ImageBackGround.Picture.Height - Picture.Height) div 2; Width := Picture.Width; Height := Picture.Height; end;
{ не выводим прозрачное изображение так, как это делает BitBlt()
функция, пользуемся функцией DrawTransparentBitmap() }
ImageForeGround.Visible := False;

{ рисуем прозрачное изображение
обратите внимание на то, как DC переднего плана используется в расположенной ниже функции }
DrawTransparentBitmap (ImageBackGround.Picture.Bitmap.Canvas.Handle, {HDC}
ImageForeGround, {TImage} ImageForeGround.Left, {X} ImageForeGround.Top {Y} ); end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{ освобождаем изображения
}
ImageForeGround.Free;
ImageBackGround.Free;
end;

end.

[001946]



Содержание раздела