Code:
unit unitTComponentAfstammeling;
interface
uses System.Classes, Vcl.ExtCtrls, System.SysUtils, Vcl.Forms, Winapi.Windows, Vcl.Controls;
type
TMyComponent = class(TComponent)
public
FSubComponent: TComponent;
FSubComponent2: TComponent;
public
procedure SetNonVisualPos(Form: TCustomForm; Component: TComponent; X, Y: Integer);
constructor Create(AOwner:TComponent); override;
end;
procedure Register;
implementation
constructor TMyComponent.Create(AOwner: TComponent);
var NewDesignInfo:LongRec;
begin
FSubComponent:=TComponent.Create(AOwner);
FSubComponent.Name:='Component'+IntToStr(FSubcomponent.ComponentIndex);
SetNonVisualPos(TCustomForm(AOwner),FSubComponent,100,100);
FSubComponent2:=TComponent.Create(AOwner);
FSubComponent2.Name:='Component2'+IntToStr(FSubcomponent.ComponentIndex);
SetNonVisualPos(TCustomForm(AOwner),FSubComponent2,200,200);
end;
procedure TMyComponent.SetNonVisualPos(Form: TCustomForm; Component: TComponent; X, Y: Integer);
const
NonvisualClassNamePattern = 'TContainer';
csNonVisualSize = 28;
csNonVisualCaptionSize = 14;
csNonVisualCaptionV = 30;
var
P: TSmallPoint;
H1, H2: HWND;
Offset: TPoint;
function HWndIsNonvisualComponent(hWnd: hWnd): Boolean;
var
AClassName: array[0..256] of Char;
begin
AClassName[GetClassName(hWnd, @AClassName, SizeOf(AClassName) - 1)] := #0;
Result := string(AClassName) = NonvisualClassNamePattern;
end;
procedure GetComponentContainerHandle(AForm: TCustomForm; L, T: Integer; var H1, H2: hWnd; var Offset: TPoint);
var
R1, R2: TRect;
P: TPoint;
ParentHandle: hWnd;
AControl: TWinControl;
I: Integer;
begin
ParentHandle := AForm.Handle;
AControl := AForm;
if AForm.ClassNameIs('TDataModuleForm') then // ÊÇ DataModule
begin
for I := 0 to AForm.ControlCount - 1 do
if AForm.Controls[I].ClassNameIs('TComponentContainer')
and (AForm.Controls[I] is TWinControl) then
begin
AControl := AForm.Controls[I] as TWinControl;
ParentHandle := AControl.Handle;
Break;
end;
end;
H2 := 0;
H1 := GetWindow(ParentHandle, GW_CHILD);
H1 := GetWindow(H1, GW_HWNDLAST);
while H1 <> 0 do
begin
if HWndIsNonvisualComponent(H1) and GetWindowRect(H1, R1) then
begin
P.x := R1.Left;
P.y := R1.Top;
P := AControl.ScreenToClient(P);
if (P.x = L) and (P.y = T) and (R1.Right - R1.Left = csNonVisualSize)
and (R1.Bottom - R1.Top = csNonVisualSize) then
begin
H2 := GetWindow(ParentHandle, GW_CHILD);
H2 := GetWindow(H2, GW_HWNDLAST);
while H2 <> 0 do
begin
if HWndIsNonvisualComponent(H2) and GetWindowRect(H2, R2) then
begin
if (R2.Top - R1.Top = csNonVisualCaptionV) and (Abs(R2.Left + R2.Right - R1.Left - R1.Right) <= 1)
and (R2.Bottom - R2.Top = csNonVisualCaptionSize) then
begin
Offset.x := R2.Left - R1.Left;
Offset.y := R2.Top - R1.Top;
Break;
end;
end;
H2 := GetWindow(H2, GW_HWNDPREV);
end;
Exit;
end;
end;
H1 := GetWindow(H1, GW_HWNDPREV);
end;
end;
begin
P := TSmallPoint(Component.DesignInfo);
GetComponentContainerHandle(Form, P.x, P.y, H1, H2, Offset);
Component.DesignInfo := Integer(PointToSmallPoint(Point(X, Y)));
if H1 <> 0 then
SetWindowPos(H1, 0, X, Y, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
if H2 <> 0 then
SetWindowPos(H2, 0, X + Offset.x, Y + Offset.y, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
end;
procedure Register;
begin
RegisterComponents('ComponentAfstammeling', [TMyComponent]);
end;
end.
Bookmarks