RSS
热门关键字:  数据挖掘  人工智能  数据仓库  搜索引擎  数据挖掘导论

控件移动类的实现之一

来源: 作者:unkonwn 时间:2005-08-20 点击:

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

  数据挖掘研究院

其中有两个类:

数据挖掘研究院

TDragClass就是实现拉动的类 数据挖掘研究院

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

数据挖掘实验室

用法很简单: 数据挖掘研究院

创建一个TDragClass对象 数据挖掘研究院

将要实现拉动的控件传进去就行了 数据挖掘实验室

比如:

myDrag.addControl(Edit1);

数据挖掘研究院

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

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

isMoveStep:boolean 数据挖掘研究院

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

数据挖掘研究院

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

MoveStep :integer

数据挖掘研究院

当移动方式为跳跃式时,该属性指定跳跃的大小,范围在520之间 数据挖掘研究院

另外还有一个方法: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,又继续累加,如此循环 数据挖掘研究院

 

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


最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
匿名?