Как сделать тень у формы только не то что бы с одного угла ... а что б со всех сторон и плавнее как это сделано в сплэшах от многих программ и так же в миранде
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
14-08-2007 03:51 | Комментарий к предыдущим ответам
Пример с тенью очень понравился! Это то, что нужно.
Подскажите, как-нибудь вообще можно поместить поверх полученного изображения контролы?
Например, TButton.
PS: Если есть ссылки на похожие статьи или примеры, прошу помочь.
С уважением WIM
//вот начало того что нужно добавить
type
TGradientColors = array[0..255] of TRGBQuad;
TRGBQuadArray = array[0..1024] of TRGBQuad;
PRGBQuadArray = ^TRGBQuadArray;
//вот конец того что нужно добавить
Котролы не отображаются
Ну так и не должны, UpdateLayeredWindow полностью заменяет содержимое окна и никаких дочерних окон рисоваться не будет, так что всё ручками надо делать.
Если требуется только какую нибудь тень особенную добавить, то можно вот тут http://www.thedelphimagazine.com/disks/dmag57.zip посмотреть пример ShadowForm.
procedure TFormSplash.BuildCopy24to32(_B_in,_B_mask:TBitmap; var _B_out: TBitmap);
const
MaxPixelCountA = MaxInt div SizeOf(TRGBQuad);
MaxPixelCount = MaxInt div SizeOf(TRGBTriple);
type
PRGBArray = ^TRGBArray;
TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;
PRGBAArray = ^TRGBAArray;
TRGBAArray = array[0..MaxPixelCountA-1] of TRGBQuad;
var x, y: Integer; RowOut: PRGBAArray; RowIn,RowInMask:PRGBArray;
begin
_B_out.Width:=_B_in.Width;
_B_out.Height:=_B_in.Height;
for y:=0 to _B_in.Height-1 do begin
RowOut:= _B_out.ScanLine[y];
RowIn:= _B_in.ScanLine[y];
RowInMask:= _B_mask.ScanLine[y];
for x:=0 to _B_in.Width-1 do begin
RowOut[x].rgbReserved:=trunc((RowInMask[x].rgbtBlue+RowInMask[x].rgbtGreen+RowInMask[x].rgbtRed)/3);
RowOut[x].rgbBlue:=byte(trunc(RowIn[x].rgbtBlue*RowOut[x].rgbReserved/255));
RowOut[x].rgbGreen:=byte(trunc(RowIn[x].rgbtGreen*RowOut[x].rgbReserved/255));
RowOut[x].rgbRed:=byte(trunc(RowIn[x].rgbtRed*RowOut[x].rgbReserved/255));
end;
end
end;
procedure TFormSplash.RenderForm;
var zsize:TSize; zpoint:TPoint; zbf:TBlendFunction;
TopLeft: TPoint; DC:HDC;
begin
SetWindowLong(FormSplash.Handle,GWL_EXSTYLE, GetWindowLong(FormSplash.Handle,GWL_EXSTYLE) or WS_EX_LAYERED);
with zbf do begin
BlendOp := AC_SRC_OVER;
BlendFlags := 0;
AlphaFormat := AC_SRC_ALPHA;
SourceConstantAlpha := 200;
end;
DC:= GetDC(0);
TopLeft:=BoundsRect.TopLeft;
UpdateLayeredWindow(FormSplash.Handle,DC,@TopLeft,@zsize,BT.Canvas.Handle,@zpoint,0,@zbf, ULW_ALPHA);
end;
procedure TFormSplash.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const SC_DRAGMOVE : Longint = $F012;
begin
if Button <> mbRight then begin
ReleaseCapture;
SendMessage(Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
end;
end;
procedure TFormSplash.WMWINDOWPOSCHANGING(var Msg: TWMWINDOWPOSCHANGING);
begin
SetWindowPos(Handle,HWND_TOPmost,Left,Top,Width,Height, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE );
end;
Я СДЕЛАЛ ...но вариант сырой у него много косяков и проблем ... все кто может помогите доделать и оптимизировать ... DRONвся надежда в основном на тебя ...
Мне кажется, все несколько проще. Поскольку тень - вещь небольшая, стоит при перерисовке получить стандартными способами содержимое окружающей части окна, затем с использованием AlphaBlend - думаю, будет неплохо.
Вам вообще-то уже предложили несколько работающих вариантов. Если проблема в конвертации из PNG в BMP с альфа-каналом, то вот функция:
procedure PNGToAlphaBitmap(Png:TPngObject;Bmp:TBitmap);
var
X,Y:Integer;
Line:PRGBQuadArray;
AlphaLine:PByteArray;
TransColor:TColor;
begin
Bmp.Assign(Png);
Bmp.PixelFormat:=pf32bit;
case Png.TransparencyMode of
ptmNone:
for Y:=0 to PNG.Height-1 do begin
Line:=Bmp.ScanLine[Y];
for X:=0 to PNG.Width-1 do
Line[X].rgbReserved:=255;
end;
ptmPartial:
for Y:=0 to PNG.Height-1 do begin
Line:=Bmp.ScanLine[Y];
AlphaLine:=Pointer(PNG.AlphaScanLine[Y]);
for X:=0 to PNG.Width-1 do
with Line[X] do begin
rgbReserved:=AlphaLine[X];
rgbBlue:=rgbBlue*rgbReserved div 255;
rgbGreen:=rgbGreen*rgbReserved div 255;
rgbRed:=rgbRed*rgbReserved div 255;
end;
end;
ptmBit:begin
TransColor:=PNG.TransparentColor;
for Y:=0 to PNG.Height-1 do begin
Line:=Bmp.ScanLine[Y];
for X:=0 to PNG.Width-1 do
if Png.Pixels[X,Y]=TransColor then
DWORD(Line[X]):=0
else
Line[X].rgbReserved:=255;
end;
end;
end;
Bmp.Modified:=True;
end;
Эта, батенька, задача сложная!
Для достижения задачи, Вам необходимо выполнить следуюшие процедуры:
1). Ваша форма должна иметь BorderStyle - bsNone
2). Cоответственно нужно увеличить размеры формы на отсупы тени со всех сторон.
3). Содать битмап, с размерами формы.
4). Ловить сообщение для вашего окна WM_MOVE и по этому сообщению выполнить нижеследующие пункты.
5). Скопировать в битмап области экрана, где должна быть нарисована тень.
6). Сгенерировать тень - тут способов несколько (например: http://delphirus.com.ru/modules.php?name=News&file=article&sid=112 ), но
самый простой - использовать нарисованную заранее тень и сохранённую в формате PNG, при этом тень должна идти как альфа канал. Для этой цели советую использовать библиотеку PngImage https://sourceforge.net/project/showfiles.php?group_id=16012
Сохранённую тень необходимо добавить в ресурс приложения, а точнее в RCDATA. Созданный в программе PngObject должен загрузить эту тень из ресурсов и наложить её на битмап со снимком экрана.
7). Вывести битмап на канву формы.
Вот примерно так, практическая реализация данной методы черевата отладкой, так как тут ньюансов очень много(движение окна, наложение поверх других окон итд).
Удачи.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.