Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как быстро нарисовать тень в заданном регионе

Delphi , Графика и Игры , Canvas

Как быстро нарисовать тень в заданном регионе



procedure TForm2.DrawShadows(WDepth, HDepth : Integer);
var
  Dst, RgnBox: TRect;
  hOldDC: HDC;
  OffScreen: TBitmap;
  Pattern: TBitmap;
  Bits: array [0..7] of WORD;
begin
  Bits[0]:=$0055;
  Bits[1]:=$00aa;
  Bits[2]:=$0055;
  Bits[3]:=$00aa;
  Bits[4]:=$0055;
  Bits[5]:=$00aa;
  Bits[6]:=$0055;
  Bits[7]:=$00aa;

  hOldDC:=Canvas.Handle;
  Canvas.Handle:=GetWindowDC(Form1.Handle);

  OffsetRgn(ShadeRgn, WDepth, HDepth);
  GetRgnBox(ShadeRgn, RgnBox);

  Pattern:=TBitmap.Create;
  Pattern.ReleaseHandle;
  Pattern.Handle:=CreateBitmap(8, 8, 1, 1, @(Bits[0]));
  Canvas.Brush.Bitmap:=Pattern;

  OffScreen:=TBitmap.Create;
  OffScreen.Width:=RgnBox.Right-RgnBox.Left;
  OffScreen.Height:=RgnBox.Bottom-RgnBox.Top;
  Dst:=Rect(0, 0, OffScreen.Width, OffScreen.Height);

  OffsetRgn(ShadeRgn, 0, -RgnBox.Top);
  FillRgn(OffScreen.Canvas.Handle, ShadeRgn, Canvas.Brush.Handle);
  OffsetRgn(ShadeRgn, 0, RgnBox.Top);

  // BitBlt работает быстрее CopyRect
  BitBlt(OffScreen.Canvas.Handle, 0, 0, OffScreen.Width, OffScreen.Height,
  Canvas.Handle, RgnBox.Left, RgnBox.Top, SRCAND);

  Canvas.Brush.Color:=clBlack;
  FillRgn(Canvas.Handle, ShadeRgn, Canvas.Brush.Handle);

  BitBlt(Canvas.Handle, RgnBox.Left, RgnBox.Top, OffScreen.Width,
  OffScreen.Height, OffScreen.Canvas.Handle, 0, 0, SRCPAINT);

  OffScreen.Free;
  Pattern.Free;
  OffsetRgn(ShadeRgn, -WDepth, -HDepth);

  ReleaseDC(Form1.Handle, Canvas.Handle);
  Canvas.Handle:=hOldDC;
end;

Комментарии:

Функция рисует тень сложной формы на форме Form2 (извиняюсь за стиль). Для определения формы тени используется регион ShadeRgn, который был создан где-то раньше (например в OnCreate). Относительно регионов см. Win32 API.

Классический "DrawShadows" процедура!

Этот код довольно эффективен и использует различные функции Windows GDI для достижения желаемого результата. Вот разбивка, что он делает:

  1. Массив Bits определяет 8x8 пиксельный шаблон, который будет использоваться как кисть для рисования тени.
  2. Процедура сохраняет текущий DC (Canvas.Handle) и заменяет его на DC окна (GetWindowDC(Form1.Handle)). Это позволяет коду доступ к всей области окна.
  3. Код.offsets регион ShadeRgn на (WDepth, HDepth) пикселей с помощью OffsetRgn. Это перемещает область тени вниз и вправо на указанное количество пикселей.
  4. Затем код получает прямоугольник ограничения региона ShadeRgn с помощью GetRgnBox.
  5. Код создает новый объект TBitmap (Pattern) размером 8x8 пикселей, инициализирует его шаблоном, определенным в массиве Bits, и назначает его как кисть для канваса.
  6. Код создает еще один объект TBitmap (OffScreen) с темиже размерами, что регион тени, и устанавливает его начало в (0, 0). Это будет использоваться как буфер с экрана.
  7. Код.offsets регион ShadeRgn на (0, -RgnBox.Top) пикселей с помощью OffsetRgn, заполняет буфер с экрана шаблоном тени с помощью FillRgn, и затем восстанавливает offset в (0, RgnBox.Top).
  8. Код выполняет бит-блочный перенос (BitBlt) из буфера с экрана на канвас, используя операцию SRCAND (and). Это эффективно рисует тень на канвасе.
  9. Код устанавливает цвет кисти в черный и заполняет регион тени на канвасе с помощью FillRgn.
  10. Затем код выполняет еще один бит-блочный перенос (BitBlt) из буфера с экрана на канвас, используя операцию SRCPAINT (srcpaint). Это рисует тень на канвасе.
  11. Код освобождает все ресурсы: освобождает объекты OffScreen, Pattern и ShadeRgn, и возвращает к оригинальному DC.

В целом, этот код довольно эффективен и использует различные оптимизационные техники для достижения быстрого отображения теней. Однако есть несколько предложений, которые я могу сделать:

  • Вместо создания двух отдельных объектов TBitmap (Pattern и OffScreen),consider using a single TBitmap object with a larger size (e.g., 16x16 pixels) and offsetting the brush pattern accordingly.
  • You can further optimize the BitBlt operations by using the RLE32 or RLE8 compression formats, which can reduce the amount of data transferred between the off-screen buffer and the canvas.

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

В статье описана функция на Delphi, которая позволяет быстро нарисовать тень в заданном регионе на форме с использованием REGION и BitBlt алгоритмов.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Canvas ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 12:00:39/0.005681037902832/1