Delphi6 控件运行期移动类

由于工作的需要,还要帮助用户维护一套旧系统,系统中包括仓库货架的布局设置,为了用户可直观的在系统中设置货架位置,就想让运行期的控件可移动,于是写了以下类

IDE:Delphi6

控件移动类代码:

type
  TMoveClass = class(TObject)
  private
    GIsMove : Boolean;     //是否允许移动
    GPosX, GPosY : Integer;  //记录控件在屏幕上的位置
    GOldX, GoldY : Integer;  //控件在容器中的位置
    GParent : TWinControl;  //容器
    GLock : Boolean;       //是否锁定
    procedure MoveEventToControl(aControl : TControl);  //设置控件移动事件
    function CheckPos(aControl: TControl) : Boolean;     //检查移动控件位置是否重叠
  public
    constructor Create;
    procedure Lock; //锁定控件
    procedure UnLock; //解锁控件
    procedure SetMoveEventToControl(aParent : TWinControl); //将容器内所有控件设置移动
    procedure OnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); //鼠标按下事件
    procedure OnMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);                    //鼠标移动事件
    procedure OnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);   //鼠标放开事件
  end;

{ TMoveClass }
constructor TMoveClass.Create;
begin
  GLock := True; //默认为锁住
end;

//设置控件移动事件
procedure TMoveClass.MoveEventToControl(aControl: TControl);
begin
  if aControl is TButton then //这里可以修改为有相关事件的控件
  begin
    TButton(aControl).OnMouseDown := OnMouseDown;
    TButton(aControl).OnMouseMove := OnMouseMove;
    TButton(aControl).OnMouseUp := OnMouseUp;
  end;//if
end;

//检查移动控件位置是否重叠
function TMoveClass.CheckPos(aControl: TControl): Boolean;
var
  i : integer;
begin
  Result := True;

  for i := 0 to GParent.ControlCount - 1 do
  begin
    if aControl.Name <> GParent.Controls[i].Name then
      if(aControl.Left = GParent.Controls[i].Left) and (aControl.Top = GParent.Controls[i].Top) then
      begin 
         //如果控件名字不同但位置相同,就让控件回复到移动前的位置
         aControl.Left := GOldX;
         aControl.Top := GoldY;
         Break;
      end;//if
  end;//for
end;

procedure TMoveClass.Lock;
begin
  GLock := True;
  GIsMove := False;
end;

procedure TMoveClass.UnLock;
begin
  GLock := False;
end;

//将容器内所有控件设置移动
procedure TMoveClass.SetMoveEventToControl(aParent: TWinControl);
var
  i : Integer;
begin
  if not (aParent = nil) and (Assigned(aParent)) then
  begin
    GParent := aParent;

    for i := 0 to GParent.ControlCount - 1 do
      MoveEventToControl(GParent.Controls[i]);
  end;//if
end;

//鼠标按下事件
procedure TMoveClass.OnMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if GLock = False then
  begin
    GIsMove := True;
    GposX := Mouse.CursorPos.X - TWinControl(Sender).Left;  //得到按钮在屏幕上的位置
    GposY := Mouse.CursorPos.Y - TWinControl(Sender).Top;
    TWinControl(Sender).BringToFront;

    GOldX := TControl(Sender).Left;
    GoldY := TControl(Sender).Top;
  end;//if
end;

//鼠标移动事件
procedure TMoveClass.OnMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if GIsMove then
  begin
    if (Mouse.CursorPos.X > (GposX + TControl(Sender).Left + TControl(Sender).Width))then
      TControl(Sender).Left := TControl(Sender).Left + TControl(Sender).Width
    else if (Mouse.CursorPos.X < (GposX + TControl(Sender).Left -  TControl(Sender).Width)) then
      TControl(Sender).Left := TControl(Sender).Left - TControl(Sender).Width
    else if (Mouse.CursorPos.y > (GposY + TControl(Sender).Top + TControl(Sender).Height)) then
       TControl(Sender).Top := TControl(Sender).Top + TControl(Sender).Height
    else if (Mouse.CursorPos.y < (GposY + TControl(Sender).Top -  TControl(Sender).Height)) then
       TControl(Sender).Top := TControl(Sender).Top - TControl(Sender).Height;
  end;//if
end;

//鼠标放开事件
procedure TMoveClass.OnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if GLock = False then
  begin
    GIsMove := False;
    CheckPos(TControl(Sender));
  end;//if
end;

移动类完成后,可以在一个窗体中放上一个Panel,再放N个Button在Panel中并靠整齐。

再加入以下代码,运行即可

声明move : TMoveClass;

实例move := TMoveClass.Create;

将Panel放入move.SetMoveEventToControl(Panel1);

调用锁定move.Lock;

调用解锁move.UnLock;


效果图


解锁,拖拽


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值