-
> Поменяйте монитор, дрожать перестанет. А если нет, ты оплатишь расходы? Тогда я уже в магазин пошел за плазменной панелью побольше :)
А если серьезно, то неужели непонятно, что когда 2. Даём паренту перерисоваться (Parent.Update), то он и перерисовывается, соответсвенно изображение быстро меняется с пернта, на наш контрол в одном и то-же месте. Может хватит глупости говорить?
-
> 1. Сдвигаем Наш контрол в сторону (Left := -Left);
Ну был у меня Left = 0. Ну сделал я Left := -Left и чего? :)
-
Поставьте Left := - Width
-
Зачем? Я же сказал что предложенный способ получить прозрачность кривой.
-
Хочеш продолжать флуд, постучи в аську.
-
Разберёмся, почему "ДРОЖИТ". "Дрожит" потому что перерисовывается фон. Дабы фон не перерисовывался можно: 1. Запретить перерисовку DoubleBuffered := true;
ControlState := ControlState + [csOpaque];
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
begin
Message.Result := 1;
end;
-
-
Вы можете чётко объяснить с какой целью вы наследуетесь от TGraphicsControl.
-
Могу.
Все вопросы от Вас теперь только в аську, если не трудно.
-
У меня нет аськи, если вы не хотите чтобы я пытался вам помочь, так и скажите.
-
Хорошо, мне нужно сделать контрол, имеющий прозрачные А возможно полу-прозрачные) области, при этом при его тображении не должно быть видно никаких серцаний других компонентов находящимся за ним и прочих артефактов.
-
Половина контролов библиотеки Raize унаследована от TRzCustomButton = class( TCustomControl ) в котором реализовано свойство Transparent и не ДРОЖАТ. Может прислушаемся к профессионалам ?
procedure TRzCustomButton.WMEraseBkgnd( var Msg: TWMEraseBkgnd );
begin
if FTransparent then
begin
DrawParentImage( Self, Msg.DC, True );
Msg.Result := 1;
end
else
inherited;
end;
procedure DrawParentImage( Control: TControl; DC: HDC; InvalidateParent: Boolean = False );
var
SaveIndex: Integer;
P: TPoint;
begin
if Control.Parent = nil then
Exit;
SaveIndex := SaveDC( DC );
GetViewportOrgEx( DC, P );
SetViewportOrgEx( DC, P.X - Control.Left, P.Y - Control.Top, nil );
IntersectClipRect( DC, 0, 0, Control.Parent.ClientWidth, Control.Parent.ClientHeight );
if not ( csDesigning in Control.ComponentState ) then
begin
Control.Parent.Perform( wm_EraseBkgnd, DC, 0 );
Control.Parent.Perform( wm_Paint, DC, 0 );
end
else
begin
try
Control.Parent.Perform( wm_EraseBkgnd, DC, 0 );
Control.Parent.Perform( wm_Paint, DC, 0 );
except
end;
end;
RestoreDC( DC, SaveIndex );
if InvalidateParent then
begin
if not ( Control.Parent is TCustomControl ) and
not ( Control.Parent is TCustomForm ) and
not ( csDesigning in Control.ComponentState ) then
begin
Control.Parent.Invalidate;
end;
end;
end;
-
Те же нотки в DevExpress
procedure DrawTransparentControlBackground(AControl: TWinControl;
ADrawCanvas: TCanvas; ADrawRect: TRect);
procedure PaintControlTo(ADrawingControl: TWinControl;
ADrawCanvas: TCanvas; AX, AY, AWidth, AHeight: Integer);
function ControlInDrawingRect(AControl: TWinControl; AOrg: TPoint): Boolean;
var
ARect: TRect;
begin
ARect.TopLeft := AOrg;
ARect.Top := ARect.Top + AControl.Top;
ARect.Left := ARect.Left + AControl.Left;
ARect.Bottom := ARect.Top + AControl.Height;
ARect.Right := ARect.Left + AControl.Width;
Result := IntersectRect(ARect, ARect, Rect(0, 0, AWidth, AHeight));
end;
procedure DrawEdgesAndBorders(ADrawCanvas: TCanvas);
var
AEdgeFlags, ABorderFlags: Integer;
R: TRect;
begin
ABorderFlags := 0;
AEdgeFlags := 0;
with ADrawingControl do
begin
if GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_CLIENTEDGE <> 0 then
begin
AEdgeFlags := EDGE_SUNKEN;
ABorderFlags := BF_RECT or BF_ADJUST
end
else
if GetWindowLong(Handle, GWL_STYLE) and WS_BORDER <> 0 then
begin
AEdgeFlags := BDR_OUTER;
ABorderFlags := BF_RECT or BF_ADJUST or BF_MONO;
end;
if ABorderFlags <> 0 then
begin
R := Rect(0, 0, Width, Height);
DrawEdge(ADrawCanvas.Handle, R, AEdgeFlags, ABorderFlags);
MoveWindowOrg(ADrawCanvas.Handle, R.Left, R.Top);
IntersectClipRect(ADrawCanvas.Handle, 0, 0,
R.Right - R.Left, R.Bottom - R.Top);
end;
end;
end;
var
AOrg: TPoint;
ASavedDC, AWindowRgnType, I: Integer;
AWindowRgn: HRGN;
begin
AWindowRgn := CreateRectRgnIndirect(cxEmptyRect);
try
AWindowRgnType := GetWindowRgn(ADrawingControl.Handle, AWindowRgn);
if AWindowRgnType = NULLREGION then
Exit;
ASavedDC := SaveDC(ADrawCanvas.Handle);
ADrawingControl.ControlState := ADrawingControl.ControlState + [csPaintCopy];
try
MoveWindowOrg(ADrawCanvas.Handle, AX, AY);
GetWindowOrgEx(ADrawCanvas.Handle, AOrg);
AOrg.X := -AOrg.X;
AOrg.Y := -AOrg.Y;
with ADrawingControl do
begin
if AWindowRgnType = ERROR then
IntersectClipRect(ADrawCanvas.Handle, 0, 0, Width, Height)
else
begin
OffsetRgn(AWindowRgn, AOrg.X, AOrg.Y);
ExtSelectClipRgn(ADrawCanvas.Handle, AWindowRgn, RGN_AND);
end;
if ADrawingControl <> AControl.Parent then
DrawEdgesAndBorders(ADrawCanvas);
ADrawCanvas.Lock;
try
Perform(WM_ERASEBKGND, ADrawCanvas.Handle, 0);
Perform(WM_PAINT, ADrawCanvas.Handle, 0);
finally
ADrawCanvas.Unlock;
end;
for I := 0 to ControlCount - 1 do
begin
if Controls[I] = AControl then
Break;
if Controls[I] is TWinControl then
if TWinControl(Controls[I]).Visible and
ControlInDrawingRect(TWinControl(Controls[I]), AOrg) then
begin
ADrawCanvas.Lock;
try
with TWinControl(Controls[I]) do
PaintControlTo(TWinControl(ADrawingControl.Controls[I]),
ADrawCanvas, Left, Top, AWidth, AHeight);
finally
ADrawCanvas.Unlock;
end;
end;
end;
end;
finally
ADrawingControl.ControlState := ADrawingControl.ControlState - [csPaintCopy];
RestoreDC(ADrawCanvas.Handle, ASavedDC);
end;
finally
DeleteObject(AWindowRgn);
end;
end;
var
AX, AY: Integer;
begin
if AControl.Parent <> nil then
begin
OffsetRect(ADrawRect, AControl.Left, AControl.Top);
AX := - ADrawRect.Left;
AY := - ADrawRect.Top;
PaintControlTo(AControl.Parent, ADrawCanvas, AX, AY,
ADrawRect.Right - ADrawRect.Left, ADrawRect.Bottom - ADrawRect.Top);
end;
end;
-
RxLib
procedure CopyParentImage(Control: TControl; Dest: TCanvas);
var
I, Count, X, Y, SaveIndex: Integer;
DC: HDC;
R, SelfR, CtlR: TRect;
begin
if (Control = nil) or (Control.Parent = nil) then Exit;
Count := Control.Parent.ControlCount;
DC := Dest.Handle;
with Control.Parent do ControlState := ControlState + [csPaintCopy];
try
with Control do begin
SelfR := Bounds(Left, Top, Width, Height);
X := -Left; Y := -Top;
end;
SaveIndex := SaveDC(DC);
try
SetViewportOrgEx(DC, X, Y, nil);
IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth,
Control.Parent.ClientHeight);
with TParentControl(Control.Parent) do begin
Perform(WM_ERASEBKGND, DC, 0);
PaintWindow(DC);
end;
finally
RestoreDC(DC, SaveIndex);
end;
for I := 0 to Count - 1 do begin
if Control.Parent.Controls[I] = Control then Break
else if (Control.Parent.Controls[I] <> nil) and
(Control.Parent.Controls[I] is TGraphicControl) then
begin
with TGraphicControl(Control.Parent.Controls[I]) do begin
CtlR := Bounds(Left, Top, Width, Height);
if Bool(IntersectRect(R, SelfR, CtlR)) and Visible then begin
ControlState := ControlState + [csPaintCopy];
SaveIndex := SaveDC(DC);
try
SaveIndex := SaveDC(DC);
SetViewportOrgEx(DC, Left + X, Top + Y, nil);
IntersectClipRect(DC, 0, 0, Width, Height);
Perform(WM_PAINT, DC, 0);
finally
RestoreDC(DC, SaveIndex);
ControlState := ControlState - [csPaintCopy];
end;
end;
end;
end;
end;
finally
with Control.Parent do ControlState := ControlState - [csPaintCopy];
end;
end;
-
Продолжить ?
-
> if not ( csDesigning in Control.ComponentState ) then > begin > Control.Parent.Perform( wm_EraseBkgnd, DC, 0 ); > Control.Parent.Perform( wm_Paint, DC, 0 ); > end > else > begin > try > Control.Parent.Perform( wm_EraseBkgnd, DC, 0 ); > Control.Parent.Perform( wm_Paint, DC, 0 ); > except > end; > end;
Отлично. Родителя я увижу (за счет его, дополнительной перерисовки, потеря производительности). А как насчет других компонентов, которые находятся под моим?
-
> Продолжить ?
Лучше ссылку дай, где можно скачать исходник хоть однго прозрачного компонента без дрожания, а то я для кфшяу нашел только 30-и метровую ссылищу :)
-
IMHO дрожание бывает двух видов: - при перерисовке, связанной с изменением внешнего вида компонента, - при перерисовке, связанной с перемещениями / ресайзами окна.
Первую я у себя лече двойной буферизацией, методом Макс Черных © (05.03.07 02:24) [2] , а вторую, устанавливая DoubleBuffered Parent-а, но на Parent-е, а не из компонента.
-
-
Извращенец. По-моему, подобные штуки надо в самом Parent делать. А зачем тебе UpdateRect? И че говорит Canvas.ClipRect? В VCL аналог SetWindowLong - TControl.WindowProc.
|