控件移动类的实现

来源:互联网 发布:手机北斗导航软件 编辑:程序博客网 时间:2024/06/03 18:57

Delphi的IDE是本身就是一个非常精彩的软件,其中涵含了许多非常宝贵的软件知识。IDE中有一个窗体设计器,控件放在里面,就可以随意移动,以及调整大小,如果能够自己实现一个类似于这样的窗体设计器,那真是一件非常美妙事情。本文实现的就是窗体设计器中最重要的部分,一个移动控件的类,控件要求从TControl继承下来,在介绍如何实现之前,先说说这个类的用法:



其中有两个类:

TDragClass就是实现拉动的类

TDragPoint是控件周围出现的拉动点的类

用法很简单:

创建一个TDragClass对象

将要实现拉动的控件传进去就行了

比如:

myDrag.addControl(Edit1);

这样Edit1就能实现拉动和移动了。

另外有两个属性来控制移动的方式

isMoveStep:boolean

指定移动的方式,True为跳跃式,False为连续式,默认情况下是False,即连续式。

所谓跳跃式,即移动或拉动控件时,控件是以离散的方式在改变自己的位置和大小的,这个对窗体设计器中的控件对齐有帮助。而连续式,当然就是以连续的方式使控件的位置和大小得到改变。

MoveStep :integer

当移动方式为跳跃式时,该属性指定跳跃的大小,范围在5-20之间

另外还有一个方法:SetPointVisible(value:Boolean);用于指定移动点的可见性。在Delphi中,当你点击窗口时,控件周围的八个小点就消失了,即用此原理。



现在开始进入到具体实现的部分了,当你点击Delphi的窗体设计器中的控件时,控件周围出现了八个小点,这八个小点其实也是窗口类: TGrabHandle。预想中要实现控件移动,得有一个标识你正在移动或拉动的东西,这八个小点正是,Delphi的这种做法可以借鉴。于是我实现了一个移动点类:TDragPoint,该的对象将作为TDragClass的成员之一,具体等一下再讲。现在来看它的实现,其实非常简单,因为VCL给了我们一个有自绘能力的类TCustomControl,只要从这里继承下来,再重载其中的Paint方法,自己来画这个移动点就行了。

代码非常简单,这里就不多说了:

//---------TDragPoint--------------------------

unit UDragPoint;



interface

uses Windows, Messages,Controls,Classes,Graphics;

type

TDragPoint=class(TCustomControl)

protected

procedure Paint;override;

public

//处理移动时用变量

isDown:Boolean;

PrevP,NextP:TPoint;

constructor Create(AOwner: TComponent); override;

procedure CreateWnd; override;

published

property OnMouseMove;

property OnMouseDown;

property OnMouseUp;

end;



implementation



{ TDragPoint }



constructor TDragPoint.create;

begin

inherited Create(AOwner);

isDown:=False;

Width:=6;

Height:=6;

end;



procedure TDragPoint.CreateWnd;

begin

inherited;

//使该类位窗口最前

BringWindowToTop(self.Handle);

end;



procedure TDragPoint.Paint;

begin

Canvas.Brush.Color:=clBlack;

Canvas.Brush.Style:=bsSolid;

Canvas.Rectangle(0,0,width,Height);

end;



end.



这里有必须谈到的一点是该类重载了WndCreate,并在其中写入BringWindowToTop(self.Handle);这样做目的是让这些移动点控件能够位于窗口的最前位置。另外在其中显化了三个鼠标事件:

property OnMouseMove;

property OnMouseDown;

property OnMouseUp;

目的是为了在TDragClass中实现移动这些点。



现在可以进入主题,来说明TDragClass的实现了。

其中有一个保存传进来的控件的列表类:FConList:TList;还有一个标识当前正在被移动或拉动的控件在FConList中的索引FCurActiveCon:Integer;

还有控件事件相关的成员

FConMouseDown:TMouseEvent;

FConMouseMove:TMouseMoveEvent;

FConMouseup:TMouseEvent;

这三个事件方法指针指向所有传进来的控件的鼠标事件的处理函数,在Create中将得到赋值。而所有控件的鼠标处理函数将在类中实现。

接下来就到了最重要的成员了:FPointRec:TPointRec;这是一个记录类型,其定义为:

TPointRec=record

LeftTop:TDragPoint;

LeftBottom:TDragPoint;

RightTop:TDragPoint;

RightButton:TDragPoint;

LeftMid:TDragPoint;

TopMid:TDragPoint;

RightMid:TDragPoint;

ButtonMid:TDragPoint;

end;

这正是当前被移动控件边缘的八个点。这八个点会粘在被移动控件的边缘。

上面说过该类可以实现跳跃式移动或拉动则必定有相关的成员: FisMoveStep:Boolean;

FMoveStep:integer;

MoveX,MoveY:integer;

FisMoveStep指定是否为跳跃式,FMoveStep为跳跃的幅度,MoveX,MoveY标识控件移动或拉动的距离是否达到了FMoveStep,是就改变控件位置和大小,如此重复

除了上面那些成员,类中还定义了一些相类的方法,大概如下:

//-------对移动点类的操作—

//创建移动点类

procedure CreateDragPoint(PointParent:TWinControl);

//设定移动点类的位置

procedure SetPointPos(posRect:TRect);

//指定移动点类的父窗口

procedure SetPointParent(PointParent:TWinControl);

//设置移动点类的鼠标事件

procedure SetPointEvent;

//设置移动点类的可见性

procedure SetPointVisible(Visibled:Boolean);

//三个控件事件处理函数,所有控件的鼠标处理函数都将是这个,主要是解决控件的移动

//以及移动点类的位置,当你点击某一个控件的时候,移动点类会附着到这个控件的边缘

procedure ConMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure ConMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure ConMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

//移动点类的鼠标处理事件,解决移动点类的移动,以及当前控件的大小改变

procedure PointMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure PointMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure PointMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

最后一个重要方法是function addControl(AddCon:Pointer):Boolean;

控件从这里加入,就可以实现移动和拉动了。



下面就将类实现比较重要的几点略说一下吧(主要还是看代码吧)

在类的构造函数中,将上面的三个控件处理函数指定给三个指针成员:

FConMouseDown:=ConMouseDown;

FConMouseMove:=ConMouseMove;

FConMouseup:=ConMouseUp;

现在这三个成员就指定了三个处理函数的地址了,等一下就可以看到那些控件的鼠标消息是怎么和这三个处理函数联系在一起的,实现就在AddControl函数中。



AddControl是一个非常重要的方法,在控件加入之前,它要先判断控件是否有Parent值,没有则不能加入,更重要的一点是,在FConList是否已经有这个控件了,即该控件已经加入过了,如果已经加入了,则不能再加一次,代码如下:

//如果该控件已经在列表中了,则加入失败

for i:=0 to FConList.Count-1 do

if Integer(AddCon)=Integer(FConList.Items[i]) then

begin

result:=false;

exit;

end;

如果可以加入则先加入列表类中,再指定当前活动控件:

FConList.Add(AddCon);

FCurActiveCon:=FConList.Count-1;

而AddControl中还有一个比较重要的TempCon.Parent.DoubleBuffered:=True;

即加入的控件的父窗口设为双缓冲模式,这样在移动控件或拉动控件大小的时候,不会出现闪烁现象。

接着就是为加入的控件指定鼠标处理函数了,但加入的是TControl,而他的鼠标事件指针被设为保护类型,因此无法获得,但他的子类把他们显化出来了。这里用了一种折衷的方案:

TButton(TempCon).OnMouseDown:=FconMouseDown;

TButton(TempCon).OnMouseMove:=FconMouseMove;

TButton(TempCon).OnMouseUp:=FconMouseUp;

这样做并不会出错,但显得怪怪的,但不理他了,能实现功能就行了。现在加入控件的鼠标事件都将会在这里的三个处理函数中处理了。

最后,将移动点类移动该控件的边缘去。

说得够杂的,各位可以和第二部分的原代码对照着看,这样会更好一些。



再稍微讲一下跳跃式移动或拉动控件的实现,FMoveStep指定跳跃的幅度,MoveX,MoveY:integer;用在移动点类和控件的鼠标事件中,累加鼠标移动的距离,当达到FMoveStep时,就移动控件,或改变控件的大小,然后将MoveX,MoveY变为0,又继续累加,如此循环



至于其他的就没有什么好说的了,各位还是看看源代码吧,也并不是很难理解。代码在第二部分给出。


控件移动类的实现之二 选择自 linzhengqun 的 Blog
关键字 控件移动类的实现之二
出处

下面是TDragClass的源代码,比如多,可以拷去机上试试,再慢慢看:



//------TDragClass------------------------

unit uDrag;



interface

uses Windows, Messages,Classes,SysUtils,Controls,Graphics,

uDragPoint,StdCtrls;

type

//控件的八个点,用于拉动大小

TPointRec=record

LeftTop:TDragPoint;

LeftBottom:TDragPoint;

RightTop:TDragPoint;

RightButton:TDragPoint;

LeftMid:TDragPoint;

TopMid:TDragPoint;

RightMid:TDragPoint;

ButtonMid:TDragPoint;

end;



TDragClass=class

private

FConList:TList; //保存控件的列表

FCurActiveCon:Integer; //当前活动控件

FPointRec:TPointRec; //当前控件的边缘的八个小点

//跳跃式移动的成员

FisMoveStep:Boolean;

FMoveStep:integer;

MoveX,MoveY:integer;

//控件事件相关的成员

FConMouseDown:TMouseEvent;

FConMouseMove:TMouseMoveEvent;

FConMouseup:TMouseEvent;

isDown:Boolean;

prevP,nextP:TPoint;

protected

//-------对移动点的操作--

procedure CreateDragPoint(PointParent:TWinControl);

procedure SetPointPos(posRect:TRect);

procedure SetPointParent(PointParent:TWinControl);

procedure SetPointEvent;

procedure SetCurActiveCon(curCon:Pointer);

//----------------------

procedure MoveLeftTopPoint;

procedure AlignLeftTop;

procedure MoveLeftBottomPoint;

procedure AlignLeftBottom;

procedure MoveRightTopPoint;

procedure AlignRightTop;

procedure MoveRightBottomPoint;

procedure AlignRightBottom;

procedure MoveLeftMidPoint;

procedure AlignLeftMid;

procedure MoveTopMidPoint;

procedure AlignTopMid;

procedure MoveRightMidPoint;

procedure AlignRightMid;

procedure MoveBottomMidPoint;

procedure AlignBottomMid;

procedure reSizeCon;

//当前控件事件和移动点事件处理------------

procedure ConMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure ConMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure ConMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure PointMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure PointMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure PointMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);



procedure SetisMoveStep(value:Boolean);

procedure SetMoveStep(value:integer);

public

constructor create(PointParent:TWinControl);

destructor destroy; override;

function addControl(AddCon:Pointer):Boolean; //important

procedure SetPointVisible(Visibled:Boolean);

property isMoveStep:Boolean read FisMoveStep write SetisMoveStep;

property MoveStep:Integer read FMoveStep write SetMoveStep;

end;



implementation



{ TDragClass }



constructor TDragClass.create(PointParent:TWinControl);

begin

inherited Create;

FConList:=TList.Create;

FCurActiveCon:=-1;

isDown:=False;

FisMoveStep:=False;

FMoveStep:=5;



FConMouseDown:=ConMouseDown;

FConMouseMove:=ConMouseMove;

FConMouseup:=ConMouseUp;



CreateDragPoint(PointParent);

SetPointVisible(false);

SetPointEvent;

end;



destructor TDragClass.destroy;

begin

FreeAndNil(FConList);

FPointRec.LeftTop.Free;

FPointRec.LeftBottom.Free;

FPointRec.RightTop.Free;

FPointRec.RightButton.Free;

FPointRec.LeftMid.Free;

FPointRec.TopMid.Free;

FPointRec.RightMid.Free;

FPointRec.ButtonMid.Free;

inherited;

end;

//加一个控件进入拖拉类

function TDragClass.addControl(AddCon: Pointer): Boolean;

var TempCon:TControl; R:TRect;

i:integer;

begin

result:=True;

if TControl(AddCon).Parent=nil then

begin

result:=false;

exit;

end;

//如果该控件已经在列表中了,则加入失败

for i:=0 to FConList.Count-1 do

if Integer(AddCon)=Integer(FConList.Items[i]) then

begin

result:=false;

exit;

end;

//将控件加入列表中,并指定当前的控件的索引

FConList.Add(AddCon);

FCurActiveCon:=FConList.Count-1;

TempCon:=TControl(AddCon);

TempCon.Cursor:=crSizeAll;

TempCon.Parent.DoubleBuffered:=True; //使用双缓冲技术

//折中方案,指定控件鼠标事件

TButton(TempCon).OnMouseDown:=FconMouseDown;

TButton(TempCon).OnMouseMove:=FconMouseMove;

TButton(TempCon).OnMouseUp:=FconMouseUp;

//画控件周围的八个小点

R.Left:=TempCon.Left;

R.Top:=TempCon.Top;

R.Right:=TempCon.Left+TempCon.Width;

R.Bottom:=TempCon.Top+TempCon.Height;

SetPointParent(TempCon.Parent);

SetPointPos(R);

SetPointVisible(true);

end;

//设置八小点的可见性

procedure TDragClass.SetPointVisible(Visibled: Boolean);

begin

FPointRec.LeftTop.Visible:=Visibled;

FPointRec.LeftBottom.Visible:=Visibled;

FPointRec.RightTop.Visible:=Visibled;

FPointRec.RightButton.Visible:=Visibled;

FPointRec.LeftMid.Visible:=Visibled;

FPointRec.TopMid.Visible:=Visibled;

FPointRec.RightMid.Visible:=Visibled;

FPointRec.ButtonMid.Visible:=Visibled;

end;

//设置小点事件

procedure TDragClass.SetPointEvent;

begin

FPointRec.LeftTop.OnMouseDown:=PointMouseDown;

FPointRec.LeftTop.OnMouseMove:=PointMouseMove;

FPointRec.LeftTop.onMouseUp:=PointMouseUp;

FPointRec.LeftBottom.OnMouseDown:=PointMouseDown;

FPointRec.LeftBottom.OnMouseMove:=PointMouseMove;

FPointRec.LeftBottom.onMouseUp:=PointMouseUp;

FPointRec.RightTop.OnMouseDown:=PointMouseDown;

FPointRec.RightTop.OnMouseMove:=PointMouseMove;

FPointRec.RightTop.onMouseUp:=PointMouseUp;

FPointRec.RightButton.OnMouseDown:=PointMouseDown;

FPointRec.RightButton.OnMouseMove:=PointMouseMove;

FPointRec.RightButton.onMouseUp:=PointMouseUp;

FPointRec.LeftMid.OnMouseDown:=PointMouseDown;

FPointRec.LeftMid.OnMouseMove:=PointMouseMove;

FPointRec.LeftMid.onMouseUp:=PointMouseUp;

FPointRec.TopMid.OnMouseDown:=PointMouseDown;

FPointRec.TopMid.OnMouseMove:=PointMouseMove;

FPointRec.TopMid.onMouseUp:=PointMouseUp;

FPointRec.RightMid.OnMouseDown:=PointMouseDown;

FPointRec.RightMid.OnMouseMove:=PointMouseMove;

FPointRec.RightMid.onMouseUp:=PointMouseUp;

FPointRec.ButtonMid.OnMouseDown:=PointMouseDown;

FPointRec.ButtonMid.OnMouseMove:=PointMouseMove;

FPointRec.ButtonMid.onMouseUp:=PointMouseUp;

end;

//确定控件边缘八个小点的位置

procedure TDragClass.SetPointPos(posRect: TRect);

begin

FPointRec.LeftTop.Left:=posRect.Left-6;

FPointRec.LeftTop.Top:=posRect.Top-6;



FPointRec.LeftBottom.Left:=PosRect.Left-6;

FPointRec.LeftBottom.Top:=PosRect.Bottom;



FPointRec.RightTop.Left:=posRect.Right;

FPointRec.RightTop.Top:=posRect.Top-6;



FPointRec.RightButton.Left:=PosRect.Right;

FPointRec.RightButton.Top:=PosRect.Bottom;



FPointRec.LeftMid.Left:=posRect.Left-6;

FPointRec.LeftMid.Top:=(posRect.Top+posRect.Bottom) div 2 - 3;



FPointRec.TopMid.Left:=(posRect.Left+posRect.Right) div 2 -3;

FPointRec.TopMid.Top:=PosRect.Top-6;



FPointRec.RightMid.Left:=posRect.Right;

FPointRec.RightMid.Top:=(posRect.Top+posRect.Bottom) div 2 - 3;



FPointRec.ButtonMid.Left:=(posRect.Left+posRect.Right) div 2 -3;

FPointRec.ButtonMid.Top:=PosRect.Bottom;

end;

//创建八个小点

procedure TDragClass.CreateDragPoint(PointParent:TWinControl);

begin

FPointRec.LeftTop:=TDragPoint.Create(nil);

FPointRec.LeftTop.Cursor:=crSizeNWSE;

FPointRec.LeftBottom:=TDragPoint.Create(nil);

FPointRec.LeftBottom.Cursor:=crSizeNESW;

FPointRec.RightTop:=TDragPoint.Create(nil);

FPointRec.RightTop.Cursor:=crSizeNESW;

FPointRec.RightButton:=TDragPoint.Create(nil);

FPointRec.RightButton.Cursor:=crSizeNWSE;

FPointRec.LeftMid:=TDragPoint.Create(nil);

FPointRec.LeftMid.Cursor:=crSizeWE;

FPointRec.TopMid:=TDragPoint.Create(nil);

FPointRec.TopMid.Cursor:=crSizeNS;

FPointRec.RightMid:=TDragPoint.Create(nil);

FPointRec.RightMid.Cursor:=crSizeWE;

FPointRec.ButtonMid:=TDragPoint.Create(nil);

FPointRec.ButtonMid.Cursor:=crSizeNS;

SetPointParent(PointParent);

end;

//------当前控件事件处理-------------------------

//处理点下的事件

procedure TDragClass.ConMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

var TempCon:TControl; R:TRect;

begin

if Button=mbLeft then

begin

isDown:=True;

GetCursorPos(PrevP);

end;

TempCon:=TControl(Sender);

SetPointParent(TempCon.Parent);

R.Left:=TempCon.Left;

R.Top:=TempCon.Top;

R.Right:=TempCon.Left+TempCon.Width;

R.Bottom:=TempCon.Top+TempCon.Height;

MoveX:=0; MoveY:=0;

SetPointPos(R);

SetPointvisible(true);

SetCurActiveCon(TempCon);

end;

//处理当前控件移动的消息

procedure TDragClass.ConMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

var offsetX,offsetY:integer; con:TControl;

r:TRect;

begin

if isDown and (Shift=[ssLeft])then

begin

GetCursorPos(nextP);

offsetX:=NextP.X-PrevP.X;

offSetY:=NextP.Y-PrevP.Y;

Con:=TControl(Sender);

if not FisMoveStep then

begin

Con.Left:=Con.Left+offSetX;

Con.Top:=Con.Top+offSetY;

end

else begin

MoveX:=MoveX+offsetX;

MoveY:=MoveY+offsetY;

if Abs(MoveX)>=FMoveStep then

begin

Con.Left:=Con.Left+MoveX;

MoveX:=0;

end;

if Abs(MoveY)>FMoveStep then

begin

Con.Top:=Con.Top+MoveY;

MoveY:=0;

end;

end;

R.Left:=Con.Left;

R.Top:=Con.Top;

R.Right:=Con.Left+Con.Width;

R.Bottom:=Con.Top+Con.Height;

SetPointPos(R);

prevP:=nextP;

end;

end;

//处理当前控件鼠标弹起的消息

procedure TDragClass.ConMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

isDown:=False;

end;

//------------------------

//设置八个点的父子关系

procedure TDragClass.SetPointParent(PointParent: TWinControl);

begin

FPointRec.LeftTop.Parent:=PointParent;

FPointRec.LeftBottom.Parent:=PointParent;

FPointRec.RightTop.Parent:=PointParent;

FPointRec.RightButton.Parent:=PointParent;

FPointRec.LeftMid.Parent:=PointParent;

FPointRec.TopMid.Parent:=PointParent;

FPointRec.RightMid.Parent:=PointParent;

FPointRec.ButtonMid.Parent:=PointParent;

end;

//得到当前活动窗口

procedure TDragClass.SetCurActiveCon(curCon: Pointer);

var i:integer;

begin

for i:=0 to FConList.Count-1 do

if Integer(curCon)=Integer(FConList.Items[i]) then

begin

FCurActiveCon:=i;

break;

end;

end;

//----------------------------------

//八个小点的处理消息

procedure TDragClass.PointMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

if Button= mbLeft then

begin

moveX:=0; moveY:=0;

if Sender=FPointRec.LeftTop then

begin

FpointRec.LeftTop.isDown:=True;

GetCursorPos(FPointRec.LeftTop.PrevP);

end

else if Sender=FPointRec.RightTop then

begin

FpointRec.RightTop.isDown:=True;

GetCursorPos(FPointRec.RightTop.PrevP);

end

else if Sender=FPointRec.LeftBottom then

begin

FpointRec.LeftBottom.isDown:=True;

GetCursorPos(FPointRec.LeftBottom.PrevP);

end

else if Sender=FPointRec.RightButton then

begin

FpointRec.RightButton.isDown:=True;

GetCursorPos(FPointRec.RightButton.PrevP);

end

else if Sender=FPointRec.LeftMid then

begin

FpointRec.LeftMid.isDown:=True;

GetCursorPos(FPointRec.LeftMid.PrevP);

end

else if Sender=FPointRec.TopMid then

begin

FpointRec.TopMid.isDown:=True;

GetCursorPos(FPointRec.TopMid.PrevP);

end

else if Sender=FPointRec.RightMid then

begin

FpointRec.RightMid.isDown:=True;

GetCursorPos(FPointRec.RightMid.PrevP);

end

else if Sender=FPointRec.ButtonMid then

begin

FpointRec.ButtonMid.isDown:=True;

GetCursorPos(FPointRec.ButtonMid.PrevP);

end;

end;

end;



procedure TDragClass.PointMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

begin

if Shift=[ssLeft] then

begin

if FPointRec.LeftTop.isDown then

begin

MoveLeftTopPoint;

reSizeCon

end

else if FPointRec.LeftBottom.isDown then

begin

MoveLeftBottomPoint;

reSizeCon

end

else if FPointRec.RightTop.isDown then

begin

MoveRightTopPoint;

reSizeCon

end

else if FPointRec.RightButton.isDown then

begin

MoveRightBottomPoint;

reSizeCon

end

else if FPointRec.LeftMid.isDown then

begin

MoveLeftMidPoint;

reSizeCon

end

else if FPointRec.TopMid.isDown then

begin

MoveTopMidPoint;

reSizeCon

end

else if FPointRec.RightMid.isDown then

begin

MoveRightMidPoint;

reSizeCon

end

else if FPointRec.ButtonMid.isDown then

begin

MoveBottomMidPoint;

reSizeCon

end

end;

end;



procedure TDragClass.PointMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

if Button= mbLeft then

begin

if (FpointRec.LeftTop.isDown) and

(Sender=FpointRec.LeftTop) then

FpointRec.LeftTop.isDown:=False

else if (FpointRec.LeftBottom.isDown) and

(Sender=FpointRec.LeftBottom) then

FpointRec.LeftBottom.isDown:=False

else if (FpointRec.RightTop.isDown) and

(Sender=FpointRec.RightTop) then

FpointRec.RightTop.isDown:=False

else if (FpointRec.RightButton.isDown) and

(Sender=FpointRec.RightButton) then

FpointRec.RightButton.isDown:=False

else if (FpointRec.LeftMid.isDown) and

(Sender=FpointRec.LeftMid) then

FpointRec.LeftMid.isDown:=False

else if (FpointRec.TopMid.isDown) and

(Sender=FpointRec.TopMid) then

FpointRec.TopMid.isDown:=False

else if (FpointRec.RightMid.isDown) and

(Sender=FpointRec.RightMid) then

FpointRec.RightMid.isDown:=False

else if (FpointRec.ButtonMid.isDown) and

(Sender=FpointRec.ButtonMid) then

FpointRec.ButtonMid.isDown:=False;

end;

end;

//左顶点的移动

procedure TDragClass.MoveLeftTopPoint;

var offsetX,offsetY:Integer;

begin

GetCursorPos(FPointRec.LeftTop.NextP);

offsetX:=FPointRec.LeftTop.NextP.X-FPointRec.LeftTop.PrevP.X;

offSetY:=FPointRec.LeftTop.NextP.Y-FPointRec.LeftTop.PrevP.Y;

if not FisMoveStep then

begin

FPointRec.LeftTop.Left:=FPointRec.LeftTop.Left+offsetX;

FPointRec.LeftTop.Top:=FPointRec.LeftTop.Top+offsetY;

end

else begin

MoveX:=MoveX+offsetX;

MoveY:=MoveY+offsetY;

if Abs(moveX)>=FMoveStep then

begin

FPointRec.LeftTop.Left:=FPointRec.LeftTop.Left+moveX;

moveX:=0;

end;

if Abs(moveY)>=FMoveStep then

begin

FPointRec.LeftTop.Top:=FPointRec.LeftTop.Top+moveY;

moveY:=0;

end;

end;

FPointRec.LeftTop.PrevP:=FPointRec.LeftTop.NextP;

AlignLeftTop;

end;

//其他点对齐左右点

procedure TDragClass.AlignLeftTop;

begin

FPointRec.LeftBottom.Left:=FPointRec.LeftTop.Left;

FPointRec.RightTop.Top:=FPointRec.LeftTop.Top;

FPointRec.LeftMid.Left:=FPointRec.LeftTop.Left;

FPointRec.LeftMid.Top:=

(FPointRec.LeftBottom.Top+FPointRec.LeftTop.Top) div 2;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.TopMid.Left:=

(FPointRec.RightTop.Left+FPointRec.LeftTop.Left) div 2;

FPointRec.RightMid.Top:=

(FPointRec.RightTop.Top+FPointRec.RightButton.Top) div 2;

FPointRec.ButtonMid.Left:=

(FPointRec.LeftBottom.Left+FPointRec.RightButton.Left) div 2;

end;

//对齐点

procedure TDragClass.AlignLeftBottom;

begin

FPointRec.LeftTop.Left:=FPointRec.LeftBottom.Left;

FPointRec.RightButton.Top:=FPointRec.LeftBottom.Top;

FPointRec.LeftMid.Left:=FPointRec.LeftTop.Left;

FPointRec.LeftMid.Top:=

(FPointRec.LeftBottom.Top+FPointRec.LeftTop.Top) div 2;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.TopMid.Left:=

(FPointRec.RightTop.Left+FPointRec.LeftTop.Left) div 2;

FPointRec.RightMid.Top:=

(FPointRec.RightTop.Top+FPointRec.RightButton.Top) div 2;

FPointRec.ButtonMid.Top:=FPointrec.LeftBottom.Top;

FPointRec.ButtonMid.Left:=

(FPointRec.LeftBottom.Left+FPointRec.RightButton.Left) div 2;

end;

//移动左底点

procedure TDragClass.MoveLeftBottomPoint;

var offsetX,offsetY:Integer;

begin

GetCursorPos(FPointRec.LeftBottom.NextP);

offsetX:=FPointRec.LeftBottom.NextP.X-FPointRec.LeftBottom.PrevP.X;

offSetY:=FPointRec.LeftBottom.NextP.Y-FPointRec.LeftBottom.PrevP.Y;

if not FisMoveStep then

begin

FPointRec.LeftBottom.Left:=FPointRec.LeftBottom.Left+offsetX;

FPointRec.LeftBottom.Top:=FPointRec.LeftBottom.Top+offsetY;

end

else begin

MoveX:=MoveX+offsetX;

MoveY:=MoveY+offsetY;

if Abs(moveX)>=FMoveStep then

begin

FPointRec.LeftBottom.Left:=FPointRec.LeftBottom.Left+moveX;

moveX:=0;

end;

if Abs(moveY)>=FMoveStep then

begin

FPointRec.LeftBottom.Top:=FPointRec.LeftBottom.Top+moveY;

movey:=0;

end;

end;

FPointRec.LeftBottom.PrevP:=FPointRec.LeftBottom.NextP;

AlignLeftBottom;

end;

//对齐点

procedure TDragClass.AlignRightTop;

begin

FPointRec.LeftTop.Top:=FPointRec.RightTop.top;

FPointRec.RightButton.Left:=FPointRec.RightTop.Left;

FPointRec.LeftMid.Left:=FPointRec.LeftTop.Left;

FPointRec.LeftMid.Top:=

(FPointRec.LeftBottom.Top+FPointRec.LeftTop.Top) div 2;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.TopMid.Left:=

(FPointRec.RightTop.Left+FPointRec.LeftTop.Left) div 2;

FPointRec.RightMid.Left:=FPointRec.RightTop.Left;

FPointRec.RightMid.Top:=

(FPointRec.RightTop.Top+FPointRec.RightButton.Top) div 2;

FPointRec.ButtonMid.Top:=FPointrec.LeftBottom.Top;

FPointRec.ButtonMid.Left:=

(FPointRec.LeftBottom.Left+FPointRec.RightButton.Left) div 2;

end;

//移动右上点

procedure TDragClass.MoveRightTopPoint;

var offsetX,offsetY:Integer;

begin

GetCursorPos(FPointRec.RightTop.NextP);

offsetX:=FPointRec.RightTop.NextP.X-FPointRec.RightTop.PrevP.X;

offSetY:=FPointRec.RightTop.NextP.Y-FPointRec.RightTop.PrevP.Y;

if not FisMoveStep then

begin

FPointRec.RightTop.Left:=FPointRec.RightTop.Left+offsetX;

FPointRec.RightTop.Top:=FPointRec.RightTop.Top+offsetY;

end

else begin

MoveX:=MoveX+offsetX;

MoveY:=MoveY+offsetY;

if Abs(moveX)>=FMoveStep then

begin

FPointRec.RightTop.Left:=FPointRec.RightTop.Left+moveX;

moveX:=0;

end;

if Abs(moveY)>=FMoveStep then

begin

FPointRec.RightTop.Top:=FPointRec.RightTop.Top+moveY;

moveY:=0;

end;

end;

FPointRec.RightTop.PrevP:=FPointRec.RightTop.NextP;

AlignRightTop;

end;

//对齐点

procedure TDragClass.AlignRightBottom;

begin

FPointRec.LeftBottom.Top:=FPointRec.RightButton.top;

FPointRec.RightTop.Left:=FPointRec.RightButton.Left;

FPointRec.LeftMid.Left:=FPointRec.LeftTop.Left;

FPointRec.LeftMid.Top:=

(FPointRec.LeftBottom.Top+FPointRec.LeftTop.Top) div 2;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.TopMid.Left:=

(FPointRec.RightTop.Left+FPointRec.LeftTop.Left) div 2;

FPointRec.RightMid.Left:=FPointRec.RightTop.Left;

FPointRec.RightMid.Top:=

(FPointRec.RightTop.Top+FPointRec.RightButton.Top) div 2;

FPointRec.ButtonMid.Top:=FPointrec.LeftBottom.Top;

FPointRec.ButtonMid.Left:=

(FPointRec.LeftBottom.Left+FPointRec.RightButton.Left) div 2;

end;

//移动右底点

procedure TDragClass.MoveRightBottomPoint;

var offsetX,offsetY:Integer;

begin

GetCursorPos(FPointRec.RightButton.NextP);

offsetX:=FPointRec.RightButton.NextP.X-FPointRec.RightButton.PrevP.X;

offSetY:=FPointRec.RightButton.NextP.Y-FPointRec.RightButton.PrevP.Y;

if not FisMoveStep then

begin

FPointRec.RightButton.Left:=FPointRec.RightButton.Left+offsetX;

FPointRec.RightButton.Top:=FPointRec.RightButton.Top+offsetY;

end

else begin

MoveX:=MoveX+offsetX;

MoveY:=MoveY+offsetY;

if Abs(moveX)>=FMoveStep then

begin

FPointRec.RightButton.Left:=FPointRec.RightButton.Left+moveX;

moveX:=0;

end;

if Abs(moveY)>=FMoveStep then

begin

FPointRec.RightButton.Top:=FPointRec.RightButton.Top+moveY;

moveY:=0;

end;

end;

FPointRec.RightButton.PrevP:=FPointRec.RightButton.NextP;

AlignRightBottom;

end;

//对齐点

procedure TDragClass.AlignLeftMid;

begin

FPointRec.LeftTop.Left:=FPointRec.LeftMid.Left;

FPointRec.LeftBottom.Left:=FPointRec.LeftMid.Left;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.TopMid.Left:=

(FPointRec.RightTop.Left+FPointRec.LeftTop.Left) div 2;

FPointRec.ButtonMid.Top:=FPointrec.LeftBottom.Top;

FPointRec.ButtonMid.Left:=

(FPointRec.LeftBottom.Left+FPointRec.RightButton.Left) div 2;

end;

//左中点

procedure TDragClass.MoveLeftMidPoint;

var offsetX:Integer;

begin

GetCursorPos(FPointRec.LeftMid.NextP);

offsetX:=FPointRec.LeftMid.NextP.X-FPointRec.LeftMid.PrevP.X;

if not FisMoveStep then

begin

FPointRec.LeftMid.Left:=FPointRec.LeftMid.Left+offsetX;

end

else begin

MoveX:=MoveX+offsetX;

if Abs(moveX)>=FMoveStep then

begin

FPointRec.LeftMid.Left:=FPointRec.LeftMid.Left+moveX;

moveX:=0;

end;

end;

FPointRec.LeftMid.PrevP:=FPointRec.LeftMid.NextP;

AlignLeftMid;

end;

//对齐点

procedure TDragClass.AlignTopMid;

begin

FPointRec.LeftTop.Top:=FPointRec.TopMid.Top;

FPointRec.RightTop.Top:=FPointRec.TopMid.Top;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.LeftMid.Left:=FPointRec.LeftTop.Left;

FPointRec.LeftMid.Top:=

(FPointRec.LeftBottom.Top+FPointRec.LeftTop.Top) div 2;

FPointRec.RightMid.Left:=FPointRec.RightTop.Left;

FPointRec.RightMid.Top:=

(FPointRec.RightTop.Top+FPointRec.RightButton.Top) div 2;

end;

//顶中点

procedure TDragClass.MoveTopMidPoint;

var offsetY:Integer;

begin

GetCursorPos(FPointRec.TopMid.NextP);

offSetY:=FPointRec.TopMid.NextP.Y-FPointRec.TopMid.PrevP.Y;

if not FisMoveStep then

begin

FPointRec.TopMid.Top:=FPointRec.TopMid.Top+offsetY;

end

else begin

MoveY:=MoveY+offsetY;

if Abs(moveY)>=FMoveStep then

begin

FPointRec.TopMid.Top:=FPointRec.TopMid.Top+moveY;

moveY:=0;

end;

end;

FPointRec.TopMid.PrevP:=FPointRec.TopMid.NextP;

AlignTopMid;

end;

//对齐点

procedure TDragClass.AlignRightMid;

begin

FPointRec.RightTop.Left:=FPointRec.RightMid.Left;

FPointRec.RightButton.Left:=FPointRec.RightMid.Left;

FPointRec.TopMid.Top:=FPointRec.LeftTop.Top;

FPointRec.TopMid.Left:=

(FPointRec.RightTop.Left+FPointRec.LeftTop.Left) div 2;

FPointRec.ButtonMid.Top:=FPointrec.LeftBottom.Top;

FPointRec.ButtonMid.Left:=

(FPointRec.LeftBottom.Left+FPointRec.RightButton.Left) div 2;

end;

//右中点

procedure TDragClass.MoveRightMidPoint;

var offsetX:Integer;

begin

GetCursorPos(FPointRec.RightMid.NextP);

offsetX:=FPointRec.RightMid.NextP.X-FPointRec.RightMid.PrevP.X;

if not FisMoveStep then

begin

FPointRec.RightMid.Left:=FPointRec.RightMid.Left+offsetX;

end

else begin

MoveX:=MoveX+offsetX;

if Abs(moveX)>=FMoveStep then

begin

FPointRec.RightMid.Left:=FPointRec.RightMid.Left+moveX;

moveX:=0;

end;

end;

FPointRec.RightMid.PrevP:=FPointRec.RightMid.NextP;

AlignRightMid;

end;

//对齐点

procedure TDragClass.AlignBottomMid;

begin

FPointRec.LeftBottom.Top:=FPointRec.ButtonMid.Top;

FPointRec.RightButton.Top:=FPointrec.ButtonMid.Top;

FPointRec.LeftMid.Left:=FPointRec.LeftTop.Left;

FPointRec.LeftMid.Top:=

(FPointRec.LeftBottom.Top+FPointRec.LeftTop.Top) div 2;

FPointRec.RightMid.Left:=FPointRec.RightTop.Left;

FPointRec.RightMid.Top:=

(FPointRec.RightTop.Top+FPointRec.RightButton.Top) div 2;

end;

//底中点

procedure TDragClass.MoveBottomMidPoint;

var offsetY:Integer;

begin

GetCursorPos(FPointRec.ButtonMid.NextP);

offSetY:=FPointRec.ButtonMid.NextP.Y-FPointRec.ButtonMid.PrevP.Y;

if not FisMoveStep then

begin

FPointRec.ButtonMid.Top:=FPointRec.ButtonMid.Top+offsetY;

end

else begin

MoveY:=MoveY+offsetY;

if Abs(moveY)>=FMoveStep then

begin

FPointRec.ButtonMid.Top:=FPointRec.ButtonMid.Top+moveY;

moveY:=0;

end;

end;

FPointRec.ButtonMid.PrevP:=FPointRec.ButtonMid.NextP;

AlignBottomMid;

end;

//重定位控件的尽寸

procedure TDragClass.reSizeCon;

var Con:TControl;

begin

Con:=TControl(FConList.Items[FCurActiveCon]);

Con.Left:=FPointRec.LeftTop.Left+FPointRec.LeftTop.Width;

Con.Top:=FPointRec.LeftTop.Top+FPointRec.LeftTop.Height;

Con.Width:=FPointRec.RightTop.Left-Con.Left;

Con.Height:=FPointRec.LeftBottom.Top-Con.Top;

end;

//-----------------------------------------------

//设置控件移动时是否用跳跃式的移动

procedure TDragClass.SetisMoveStep(value: Boolean);

begin

if FisMoveStep<>value then

FisMoveStep:=Value;

end;

//设置控件移动跳跃的距离

procedure TDragClass.SetMoveStep(value: integer);

begin

if Value<5 then

FMoveStep:=5

else if Value>20 then

FMoveStep:=20

else

FMoveStep:=Value;

end;



end.



到第三部分,用一个例子来说明这个类的用法


我们用一个例子来演示这个类的用法,建一个工程,将TDragClass的单元加入主窗体单元中,代码如下:



unit Main;



interface



uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ExtCtrls, Buttons,uDrag,uDragPoint, jpeg;



type

TForm1 = class(TForm)

Bevel1: TBevel;

Button3: TButton; //指定用何种方式移动和拉动

Edit2: TEdit;//用于设定跳跃式移动的幅度

Button4: TButton;//确定Edit2中的内容

Button1: TButton;//点击该按钮,加入下面的控件,实现控件移动

Panel1: TPanel;

Shape1: TShape;

Image1: TImage;

Button2: TButton;

Edit1: TEdit;

StaticText1: TStaticText;

Shape2: TShape;

BitBtn1: TBitBtn;

BitBtn2: TBitBtn;

procedure Button1Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

procedure Button3Click(Sender: TObject);

procedure Button4Click(Sender: TObject);

procedure FormClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

MyDrag:TDragClass;

end;



var

Form1: TForm1;



implementation



{$R *.dfm}



procedure TForm1.Button1Click(Sender: TObject);

begin

myDrag.addControl(Edit1);

myDrag.addControl(Button2);

myDrag.addControl(Shape1);

myDrag.addControl(Image1);

myDrag.addControl(Panel1);

myDrag.addControl(BitBtn1);

myDrag.addControl(shape2);

myDrag.addControl(BitBtn2);

end;



procedure TForm1.FormCreate(Sender: TObject);

begin

myDrag:=TDragClass.create(self);

end;



procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

if Assigned(myDrag) then

MyDrag.Free;

end;



procedure TForm1.Button3Click(Sender: TObject);

begin

myDrag.isMoveStep:=not myDrag.isMoveStep;

if myDrag.isMoveStep then

Button3.Caption:='连接式移动'

else

Button3.Caption:='跳跃式移动';

end;



procedure TForm1.Button4Click(Sender: TObject);

var value:integer;

begin

if TryStrtoInt(Edit2.Text,value) then

myDrag.MoveStep:=value;

end;



procedure TForm1.FormClick(Sender: TObject);

begin

myDrag.SetPointVisible(false);

end;



end.



运行程序,点击Button1按钮,看看如何,下面的控件是不是都可以移动了呢,再点击Button3,控件的移动是不是变得不连续了呢,再输入Edit2的值,然后点确定,控件移动的不连续性是不是变化了呢。



至此这个控件移动类讲解完毕,但还有很多改善的地方,有兴趣自己改吧。还是那句话,希望对你有用。


(出处:www.delphibbs.com)

 
原创粉丝点击