21st
Авг

Полупрозрачность в Delphi

Posted by Chas under Статьи, Топик-обзор

И так, как сделать окошко в дельфи прозрачным с красивыми тенями и другой мутью.

Перво наперво, качаем gdiplus.dll (если есть желание) с MS Official Site

Потом смотрим мои (DIB) и не мои (GdiPlus) модули в аттаче.

И так… Подготовим плацдарм для нашего окошка

код:

implementation

const
   WndClassName = ‘Trulyalya’;

var
   WndClass: TWndClass = (
     style: CS_DBLCLKS;
     cbClsExtra: 0;
     cbWndExtra: 0;
     hbrBackground: 0;
     lpszMenuName: NIL;
     lpszClassName: WndClassName;
   );

initialization
   WndClass.lpfnWndProc := @DefWindowProc; // I hope…
   WndClass.hInstance := HInstance;
   WndClass.hIcon := LoadIcon(HInstance, ‘MAINICON’);
   WndClass.hCursor := LoadCursor(0, IDC_ARROW);
   Windows.RegisterClass(WndClass);

finalization
   Windows.UnregisterClass(WndClassName, HInstance);

И так у нас есть зарегиный класс, вот ведь счастье ну мы не собираемся на этом останавливаться и пойдем до конца! Теперь давайте создадим окошко

Код:
hWnd := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_LAYERED,
   WndClass.lpszClassName, NIL, WS_POPUP or WS_VISIBLE, 0, 0, 0, 0, 0, 0, HInstance, NIL);

Думаю то что здесь, понять не составит труда. Теперь стоит понять, что у нас есть окошко со стилем WS_EX_LAYERED и это дает нам по сути установить и отобразить любое 32х битное изображение разумеется в формате ARGB никакие PNG и т.п. на прямую не ставятся. Как же это сделать?

Код:

var
   Context: GpGraphics;
   Tmp: TDIB;
   Image: TDIB;
   Rect: TRect;
begin
   // Rect := GetWindowRect(); / GetClientRect(); не помню как точно, сами разберетесь

   Tmp := TDIB.Create(Rect.right – Rect.left, Rect.bottom – Rect.top); // создаем битмап по размеру окна
   Image := TDIB.Create(’my_image.png’); // загрузим какое то изображение

   GdipCreateFromHDC(Tmp.DC, Context); // создадим контекст GDI+ c Tmp
   GdipSetSmoothingMode(Context, SmoothingModeAntiAlias); // antialias включим
   GdipSetCompositingMode(Context, CompositingModeSourceCopy); // рисование с перекрытием
   GdipSetInterpolationMode(Context, InterpolationModeHighQualityBicubic); // качественно масштабировать изображения

   GdipDrawImageRectRect(Context, Image.Bitmap,
      0, 0, Tmp.Width, Tmp.Height, // покрываем все окно
      0, 0, Image.Width, Image.Height, // берем все изображение
      UnitPixel, NIL, NIL, NIL);

   GdipDeleteGraphics(Context);
   Image.Free();

И так, мы узнали размер окна, создали битпам для окна, загрузили картинку, связали GDI+ с Tmp и нарисовали с помощью GDI+ нашу картинку, потом все освободили. Теперь у нас есть Tmp на с отрисованной картинкой. Осталось дело за малым, отобразить на окне.

Код:

var
   BlendFunc: TBlendFunction;
   ZPoint: TPoint;
   LeftTop: TPoint;
   Size: TSize;
   Rect: TRect;
begin
   with BlendFunc do
   begin
      BlendOp := AC_SRC_OVER;
      BlendFlags := 0;
      AlphaFormat := AC_SRC_ALPHA;
      SourceConstantAlpha := 255; // не желательно менять это, да станет прозрачней, но тормаза начнутся, лучше перерисовать сам битмап в более прозрачный.
   end;

   // Rect := GetWindowRect(); / GetClientRect(); не помню как точно, сами разберетесь

   ZPoint := Point(0, 0);
   LeftTop := Point(Rect.left, Rect.top);
   Size.cx := Rect.right – Rect.left;
   Size.cy := Rect.bottom – Rect.top;

   UpdateLayeredWindow(hWnd, 0, @LeftTop, @Size, Tmp.DC, @ZPoint, 0, @BlendFunc, ULW_ALPHA);

Разумеется, не забудьте сделать это Tmp.Free();

Опять такие, это мануалчик, проверять не могу сейчас, да и думаю тут суть ясна, садитесь и пробуйте.
DIB.rar

Тема на форуме

Обсудить на форуме – Полупрозрачность в Delphi

Похожие статьи