-
Может кому-то нужно, заодно и покритикуете.
procedure PrintParentFullZOrder(Control: TControl; DC: HDC);
var
LastOrigin: TPoint;
i: Integer;
ControlInd: Integer;
lControl: TControl;
lIntersectRect, FirstRect, SecondRect: TRect;
begin
if not Assigned(Control.Parent) then Exit;
if not (Control is TWinControl) then Exit;
GetWindowOrgEx(DC, LastOrigin);
SetWindowOrgEx(DC, LastOrigin.X + Control.Left, LastOrigin.Y + Control.Top, nil);
Control.Parent.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC));
Control.Parent.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND);
ControlInd := Control.Parent.ControlCount - 1;
for i := 0 to ControlInd do
begin
lControl := Control.Parent.Controls[i];
if lControl = Control Then Break;
if not (lControl is TWinControl) then Continue;
if not lControl.Visible then Continue;
FirstRect.Left := lControl.Left;
FirstRect.Top := lControl.Top;
FirstRect.Right := lControl.Left + lControl.Width;
FirstRect.Bottom := lControl.Top + lControl.Height;
SecondRect.Left := Control.Left;
SecondRect.Top := Control.Top;
SecondRect.Right := Control.Left + Control.Width;
SecondRect.Bottom := Control.Top + Control.Height;
if not IntersectRect(lIntersectRect, FirstRect, SecondRect) then Continue;
SetWindowOrgEx(DC, LastOrigin.X - lControl.Left + Control.Left, LastOrigin.Y - lControl.Top + Control.Top, nil);
lControl.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC));
lControl.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND or PRF_CHILDREN);
end;
SetWindowOrgEx(DC, LastOrigin.X, LastOrigin.Y, nil);
end; Для отсутствия мигания элемент на котором рисуется должен быть DoubleBuffered = True; Вызывать в Paint оконных элементов Основной баг(неустранимый) - если прозрачные элементы накладываются друг на друга, то отрисовка тормозит. (Количество перекрывающихся прозрачных элементов)!
-
А как её использовать?
-
> Kolan © (25.12.07 21:52) [1] > > А как её использовать?
В Paint наследника TCustomControl рисовать на свой Canvas.Handle procedure Paint;
begin
PrintParentFullZOrder(Self, Canvas.Handle);
end;
-
> В Paint наследника TCustomControl рисовать на свой Canvas.Handle
И что будет? Не понял что значит «функцию прозрачности»
может полупрозрачность
А как тогда задать величину(AlphaBlend)?
-
> Kolan © (25.12.07 22:01) [3] > > > В Paint наследника TCustomControl рисовать на свой Canvas. > Handle > > И что будет? Не понял что значит «функцию прозрачности»… > может полупрозрачность… А как тогда задать величину(AlphaBlend)?
Именно прозрачности.
Можно рисовать на Canvas TBitmap, получаешь полную копию экрана под твоим оконным компонентом. А дальше уже смешать два TBitmap(подложка и отрисовка) - стандартный способ.
-
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
PrintParentFullZOrder(Panel1, PaintBox1.Canvas.Handle);
end; И где чудо?
-
Мдааа... FirstRect.Left := lControl.Left;
FirstRect.Top := lControl.Top;
FirstRect.Right := lControl.Left + lControl.Width;
FirstRect.Bottom := lControl.Top + lControl.Height;
FirstRect := lControl.BoundsRect;
SecondRect.Left := Control.Left;
SecondRect.Top := Control.Top;
SecondRect.Right := Control.Left + Control.Width;
SecondRect.Bottom := Control.Top + Control.Height;
if not IntersectRect(lIntersectRect, FirstRect, SecondRect) then Continue; if not IntersectRect(lIntersectRect, FirstRect.BoundsRect, Control.BoundsRect) then Continue;
-
> homm © (25.12.07 22:07) [5] > > procedure TForm1.PaintBox1Paint(Sender: TObject); > begin > PrintParentFullZOrder(Panel1, PaintBox1.Canvas.Handle); > > end; > И где чудо?
Подходит только для Win-контролов
-
> [7] Черный Шаман (25.12.07 22:51) > Подходит только для Win-контролов
Panel1 — Win-контрол.
-
> [0] Черный Шаман (25.12.07 21:40) > lControl.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND > or PRF_CHILDREN);
А еще уконтроллов бывает Неклинтская часть, слыхал?
-
-
> homm © (25.12.07 23:00) [9] > > > [0] Черный Шаман (25.12.07 21:40) > > lControl.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND > > or PRF_CHILDREN); > > А еще уконтроллов бывает Неклинтская часть, слыхал?
Бывает, но она в данном случае не нужна.
-
> [11] Черный Шаман (25.12.07 23:10) > Бывает, но она в данном случае не нужна.
Как не нужна? Она такая же часть окна.
-
> [10] Черный Шаман (25.12.07 23:09)
А теперь сам приглядись к примеру, и скажи, почему его так колбасит во все стороны, когда над контролами надписи пролетают. Подсказка: см [12]
-
> homm © (25.12.07 23:19) [13] > > > [10] Черный Шаман (25.12.07 23:09) > > А теперь сам приглядись к примеру, и скажи, почему его так > колбасит во все стороны, когда над контролами надписи пролетают. > Подсказка: см [12]
Сорри вы правы.
procedure PrintParentFullZOrder(Control: TControl; DC: HDC);
var
LastOrigin: TPoint;
i: Integer;
ControlInd: Integer;
lControl: TControl;
lIntersectRect: TRect;
begin
if not Assigned(Control.Parent) then Exit;
if not (Control is TWinControl) then Exit;
GetWindowOrgEx(DC, LastOrigin);
SetWindowOrgEx(DC, LastOrigin.X + Control.Left, LastOrigin.Y + Control.Top, nil);
Control.Parent.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC));
Control.Parent.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND);
ControlInd := Control.Parent.ControlCount - 1;
for i := 0 to ControlInd do
begin
lControl := Control.Parent.Controls[i];
if lControl = Control Then Break;
if not (lControl is TWinControl) then Continue;
if not lControl.Visible then Continue;
if not IntersectRect(lIntersectRect, lControl.BoundsRect, Control.BoundsRect) then Continue;
SetWindowOrgEx(DC, LastOrigin.X - lControl.Left + Control.Left, LastOrigin.Y - lControl.Top + Control.Top, nil);
lControl.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC));
lControl.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND or PRF_CHILDREN or PRF_NONCLIENT);
end;
SetWindowOrgEx(DC, LastOrigin.X, LastOrigin.Y, nil);
end;
-
Вот еще так попробуй: procedure SetLeft(Control:TWinControl; NewLeft: Integer);
begin
SetWindowPos(Control.Handle, 0, NewLeft, Control.Top, 0, 0, SWP_NOSIZE or SWP_NOZORDER or SWP_NOCOPYBITS );
end;
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
SetLeft(SkinVisualControl1, SkinVisualControl1.Left+2);
SetLeft(SkinVisualControl2, SkinVisualControl2.Left+3);
if SkinVisualControl1.Left > 400 then SetLeft(SkinVisualControl1, 2);
if SkinVisualControl2.Left > 400 then SetLeft(SkinVisualControl2, 2);
SkinVisualControl1.Refresh;
SkinVisualControl2.Refresh;
end; Зы. Бесит VCL-ная особенность инвалидейтить все налюбой чих. От этого стока фликов.
-
> homm © (25.12.07 23:36) [15]
С [14] вроде багов не заметил. Что не так?
-
> [16] Черный Шаман (25.12.07 23:42) > Что не так?
Колбасит-с
-
> homm © (25.12.07 23:48) [17] > > > [16] Черный Шаман (25.12.07 23:42) > > Что не так? > > Колбасит-с
Но пока это лучший способ из тех что я видел без полной переделки VCL. Подойдет при нечастом изменении подложки.
Кстати, DoubleBuffered у контролов стоит?
SkinVisualControl1.DoubleBuffered := True; SkinVisualControl2.DoubleBuffered := True;
-
Если комбинировать ее с этой(аналог отрисовки бекраунда в темах XP, но работает начиная с Win95)
procedure PrintParentBackground(Control: TControl; DC: HDC);
var
LastOrigin: TPoint;
begin
if not Assigned(Control.Parent) then Exit;
if not (Control is TWinControl) then Exit;
GetWindowOrgEx(DC, LastOrigin);
SetWindowOrgEx(DC, LastOrigin.X + Control.Left, LastOrigin.Y + Control.Top, nil);
Control.Parent.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC));
Control.Parent.Perform(WM_PRINT, DC, PRF_CLIENT or PRF_ERASEBKGND);
SetWindowOrgEx(DC, LastOrigin.X, LastOrigin.Y, nil);
end;
То совсем жить можно.
-
> [18] Черный Шаман (25.12.07 23:54) > Кстати, DoubleBuffered у контролов стоит?
Демка та же, стоит. Если все равно не понятно, о чем я, вот так еще сделай: procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
SkinVisualControl1.Left := X - (SkinVisualControl1.Width div 2);
SkinVisualControl2.Left := X - (SkinVisualControl2.Width div 2);
SkinVisualControl1.Refresh;
SkinVisualControl2.Refresh;
end; Только таймер отключи. А потом разремарь мой вариант и заремарь SkinVisualControl1.Left. Почувствуй, как говориться, разницу :)
-
Есть, кстати, еще одна досада. Положи на форму ричедит, попробуй по нему «проехаться». Эту гадость вообще ни одна прозрачность не берет :)
-
homm © (26.12.07 00:00) [20] SetLeft чуть быстрее, но это и понятно.
Вполне прилично по скорости для прозрачных/полупрозрачных панелек если их сделать только парочку для крутоты.
-
> [22] Черный Шаман (26.12.07 00:09) > SetLeft чуть быстрее, но это и понятно.
Скорость не причем. То, что тебе не вино разницы может быть обусловленно другой версией дельфи, плохим монитором, плохим зрением, или не желанием видеть.
У меня Д7. Новее нет ничего сейчас на машине.
-
> homm © (26.12.07 00:06) [21] > > Есть, кстати, еще одна досада. Положи на форму ричедит, > попробуй по нему «проехаться». Эту гадость вообще ни одна > прозрачность не берет :)
Для большинства случаев хватит. Даже в Vista нормальной прозрачности дочерних элементов нет. Хотите полных наворотов - берите QT.
Или же я обдумываю о создании библиотеки визуальных контролов через Direct3D. Нужно же загрузить процессорные мощности? :)
-
> [24] Черный Шаман (26.12.07 00:14) > Или же я обдумываю о создании библиотеки визуальных контролов > через Direct3D. Нужно же загрузить процессорные мощности? > :)
Скорее ноборот, разгрузить ;)
-
Ребята, бросайте курить эту гадость ! :)
Помоему, начиная с Delphi7 (или раньше ?) давно уже есть TCustomForm.AlphaBlendValue := [0..255]; TCustomForm.AlphaBlend := [true || false];
И все там прозрачно: и форма, и дочерние элементы управления ...
-
> [26] PEAKTOP © (26.12.07 06:24) > Ребята, бросайте курить эту гадость ! :)
Хорошо так, со стороны ляпнуть первое, что в голову пришло, и вроде умным показался и напрягатся особо не пришлось. Давай уже сам бросай, включай соображалку.
-
> PEAKTOP © (26.12.07 06:24) [26] молодец. писать научился. осталось научиться думать перед тем как писать.
зыж у меня, например, тоже была такая же реакция. но я не поддался, и потрудился хотя бы глянуть код перед постом. после чего понял, что не стоит глупости постить.
-
а для чего в этой функции SetWindowOrgEx ?
-
> MetalFan © (27.12.07 10:21) [29] > > а для чего в этой функции SetWindowOrgEx ?
Не нравится SetWindowOrgEx, можешь использовать SetViewportOrgEx :), только знаки в вычислениях поменяй на противоположные.
Для того чтобы сместить точку отрисовки на Canvas(HDC).
|