本人作了一个界面,上有 label和edit,我想用鼠标可以托动他的位置,选中控件之后,让他变色(以示被选中),用CTRL+ARROW(方向键),也可以移动他(微调)
另外一个我不明白
drag 和 DOCK 的区别?
还有以下不太明白:
onstartdrag
onstartdock
ondockdrop
ondockover
ondragover
ondragdrop
onenddock
onenddrag
ongetsiteinfo
onmousedown
onmousemove
onmouseup
onstartdock
onstartdrag
onundock
另外一个我不明白
drag 和 DOCK 的区别?
还有以下不太明白:
onstartdrag
onstartdock
ondockdrop
ondockover
ondragover
ondragdrop
onenddock
onenddrag
ongetsiteinfo
onmousedown
onmousemove
onmouseup
onstartdock
onstartdrag
onundock
在Label的MouseMove和EndDrag事件,在Panel1的DragOver事件中键入下面的代码:
procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
xlabel:=x;
ylabel:=y;
end;procedure TForm1.Label1EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
Label1.Left:=xpanel-xlabel;
Label1.Top:=ypanel-ylabel;
end;procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
xpanel:=x;
ypanel:=y;
end;
作者: 评价: 上站日期: 2002-05-22
内容说明:
来源: --------------------------------------------------------------------------------随着软件技术的不断进步,软件界面也越来越美观,操作也越来越方便。综观市面上比较专业的各种软件,我们会发现大部分都提供窗体停靠的功能,特别象工具软件,基本上都或多或少有停靠功能。自然,Delphi也支持停靠,而且她和VCL紧密结合,对于广大的Delphi程序员来说更是一大福音。让我们省去枯燥的编码时间。把注意力集中在核心程序的构思上。 先让我们来复习一下VCL的结构,在TWinControl类中有一个DockSite属性(boolean),它的作用是是否允许别的控件停靠在它的上面,在TControl类中有一个DragKind属性,如果要这个控件能停靠在别的控件上,就把DragKind属性设成dkDock。就这么简单,只要设置一下属性,一个支持停靠的程序就完成了。当然,上面说的只是最最基本的步骤,有了以上两步,我们就可以继续编写代码实现更复杂的功能。一般的支持停靠的程序都可以在主窗口的上下左右停靠,也就是说在主窗口的边上放上能被停靠的控件比较好(只要是从TWinControl继承的都行),一般我们都选择TPanel,为了便于读者理解,我们可以假定主窗口的左边可以停靠,所以在主窗口上放一个Align属性为alLeft的Panel,取名为LeftDockPanel,宽度为0,DockSite属性为True,当然我们的LeftDockPanel应该是可以改变大小的,所以在它右边再放一个TSplitter,取名为LeftSplitter,Align属性为alLeft。接下来就是停靠控件了,一般的程序停靠控件都是窗体,所以我们也建一个窗体,取名叫DockableForm,DragKind属性设成dkDock,DragMode属性设为dmAutomatic(自动停靠)。现在我们可以运行这个程序了,什么?效果不好?停靠的窗体停靠停靠进去后就不见了! 哦,我差点忘了,当停靠窗体停靠时Delphi会产生一些事件,他们分别是1.OnDockOver(Sender: TObject; Source: TDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean);2.OnDockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);3.OnGetSiteInfo(Sender: TObject; DockClient: TControl; var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);4.OnStartDock(Sender: TObject; var DragObject: TDragDockObject);5.OnEndDock(Sender, Target: TObject; X, Y: Integer);6.OnUnDock(Sender: TObject; Client: TControl; NewTarget: TWinControl; var Allow: Boolean);哇,这么多,别急,让我细细道来:先让我们来看看第一个事件OnDockOver是在停靠控件(DockableForm)掠过被停靠控件(LeftDockPanel)时触发的。Source包含了停靠—拖动操作的信息,其中有一个重要的属性是Control,就是DockableForm,另一个重要的属性是DockRect,就是停靠的位置;X,Y是鼠标的位置,State的状态有dsDragEnter, dsDragLeave, dsDragMove,分别表示拖动进入,拖动离开,拖动移动;Accept是是否同意停靠的意思。OnDockOver事件主要作用是控制停靠窗体的预览位置,下面我们来加入以下代码:procedure TMainForm.LeftDockPanelDockOver(Sender: TObject; Source: TDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean);var ARect: TRect;begin Accept := Source.Control is TDockableForm; if Accept then begin//修改预览停靠位置 ARect.TopLeft := LeftDockPanel.ClientToScreen(Point(0, 0)); ARect.BottomRight := LeftDockPanel.ClientToScreen( Point(Self.ClientWidth div 3, LeftDockPanel.Height)); Source.DockRect := ARect; end;end; 现在再运行程序,当你把DockableForm拖动到主窗口左边时,已经出现了预览停靠位置,也就是虚线包含的范围。怎么?窗体又不见了?那当然了,我们只是讲了OnDockOver,还没详细讲解OnDockDrop呢,它才是决定停靠窗体在哪里出现的罪魁祸首:OnDockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);参数和OnDockOver差不多,只是少了State: TDragState和var Accept: Boolean它是在停靠窗体进入被停靠控件时发生的,作用是控制停靠窗体的最终位置。下面添加如下代码:procedure TMainForm.LeftDockPanelDockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);Begin LeftDockPanel.Width := ClientWidth div 3; LeftSplitter.Left := LeftDockPanel.Width + LeftSplitter.Width;End;现在再运行程序,哇塞,成功了。出现了一个和Delphi的IDE完全一样的停靠窗体,上面是两条横线,用来把它拖出来,右上角有一个小X是用来关闭的。不过好景不长,当我们把它关闭时,装载DockableForm的LeftDockPanel不能还原,还是霸占着主窗口的客户区,怎么办?嘻嘻,忘了告诉你们了,其实Delphi早就为我们作好了一切。请打开DockableForm的关闭事件,你会发现原来当你点击右上角那个小X关闭DockableForm时,它会触发DockableForm的OnClose事件,在OnClose事件中把LeftDockPanel的宽度设为0就行了。procedure TDockableForm.FormClose(Sender: TObject; var Action: TCloseAction);begin MainForm.LeftDockPanel.Width := 0; Action := caHide;end;
意位置。以下是具体实现过程:
1. 首先做一下准备工作,运行Delphi,进入集成开发环境,在 File 菜单中选择New
Application 。
2. 在Form1中创建对象 Panel1,并在 Panel1 中创建另一对象 Label1。
3. 选中Label1,修改其下列属性的值:
属性值:
Caption :标签移动测试!
Cursor :crHandPoint
DragCursor:crDrag
DragMode :dmAutomatic
4.在程序的开头部分声明全局变量 x_panel,y_panel,x_label,y_label,其中,x_panel,y_panel :
鼠标在Panel1上的坐标;x_label,y_label :鼠标在label1上的坐标。
注:这里分别获取在Panel1和Label1上的坐标是为了更精确地计算出Label1实际的移动距离。
5.在Panel1的OnDragOver 和OnMouseMove 事件中添加如下代码:
x_panel:=X;
y_panel:=Y;
注:该操作是获得 mouse 在Panel1上的坐标。
6.在Label1的OnMouseMove 事件中添加如下代码:
x_Labell:=X;
y_Label1:=Y;
注:该操作是获得 mouse 在Label1上的坐标。
7.在Label1的OnEndDrag 事件中添加如下代码:
label1.left :=x_panel-x_label;
label1.top :=y_panel-y_label;
说明:两者相减是为了求得 label1 实际的移动距离。
8.创建一个对象 Button1 ,并在其 OnClick 事件中添加如下代码:
close; //用以关闭应用程序。
好了,现在运行程序,测试一下结果。
以下是程序源代码,在Delphi3.0、Windows9598中测试通过。
unit test_move;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure Label1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
procedure Label1EndDrag(Sender, Target: TObject; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
x_panel,y_panel,x_label,y_label:integer;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
close;
end;
procedure FTorm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState;X,Y: Integer);
begin
x_panel:=X;
y_panel:=Y;
end;
procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
x_panel:=X;
y_panel:=Y;
end;
procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState;X,Y: Integer);
begin
x_label:=X;
y_label:=Y;
end;
procedure TForm1.Label1EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
label1.left :=x_panel-x_label;
label1.top:=y_panel-y_label;
end;
end.
举例如下:创建一个 Panel,再创建一个Label,通过编程使控件 Lable 可以在 Panel 中被拖放到任意位置。以下是具体实现过程:
1.首先做一下准备工作,运行Delphi3.0,进入集成开发环境,在 File 菜单中选择New Application 。
2.在Form1中创建对象 Panel1,并在 Panel1 中创建另一对象 Label1。
3.选中Label1,修改其下列属性的值:
属性 值
Caption : 标签移动测试!
Cursor : crHandPoint
DragCursor : crDrag
DragMode : dmAutomatic
4.在程序的开头部分声明全局变量 x_panel,y_panel,x_label,y_label
其中,x_panel,y_panel :鼠标在Panel1上的坐标。
x_label,y_label :鼠标在label1上的坐标。
注:这里分别获取在Panel1和Label1上的坐标是为了更精确地计算出Label1实际的移动距离。
5.在Panel1的OnDragOver 和OnMouseMove 事件中添加如下代码:
x_panel:=X;
y_panel:=Y;
注:该操作是获得 mouse 在Panel1上的坐标。
6.在Label1的OnMouseMove 事件中添加如下代码:
x_Labell:=X;
y_Label1:=Y;
注:该操作是获得 mouse 在Label1上的坐标。
7.在Label1的OnEndDrag 事件中添加如下代码:
label1.left :=x_panel-x_label;
label1.top :=y_panel-y_label;
说明:两者相减是为了求得 label1 实际的移动距离。
8.创建一个对象 Button1 ,并在其 OnClick 事件中添加如下代码:
close; 用以关闭应用程序。
好了,现在运行程序,测试一下结果。
以下是程序源代码,在Delphi3.0、Windows95/98中测试通过。
unit test_move;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure Label1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
procedure Label1EndDrag(Sender, Target: TObject; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
x_panel,y_panel,x_label,y_label:integer;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
close;
end;
procedure FTorm1.Panel1MouseMove
(Sender: TObject; Shift: TShiftState;
X,Y: Integer);
begin
x_panel:=X;
y_panel:=Y;
end;
procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
x_panel:=X;
y_panel:=Y;
end;
procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState;
X,Y: Integer);
begin
x_label:=X;
y_label:=Y;
end;
procedure TForm1.Label1EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
label1.left :=x_panel-x_label;
label1.top:=y_panel-y_label;
end;
end.
抄袭就是这样疯狂,原来他是继承了父类的特性,有过之而不及。
在学校时,你们怎莫考试的!
等一下结贴
然我也研究研究!
procedure TFMForm.FileListBox1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then { drag only if left button pressed }
with Sender as TFileListBox do { treat Sender as TFileListBox }
begin
if ItemAtPos(Point(X, Y), True) >= 0 then { is there an item here? }
BeginDrag(False); { if so, drag it }
end;
end;
hEaDRoOm Development
29.10.2002 Unit Name: HREdit
Author: Benjamin Benjamin Wittfoth
Purpose:
History:
-----------------------------------------------------------------------------}
unit HREdit; interface uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls; type
THREdit = class(TEdit)
private
fDragable:Boolean;
protected
procedure MouseDown(Button: TMouseButton;Shift: TShiftState; X, Y: Integer);override;
public
Constructor Create(AOwner:TComponent);override;
Destructor Destroy;override;
published
property Dragable:Boolean read fDragable write fDragable;
end; procedure Register; implementation procedure Register;
begin
RegisterComponents('HEADROOM DEVELOPMENT', [THREdit]);
end; { THREdit }
constructor THREdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end; destructor THREdit.Destroy;
begin
inherited;
end; procedure THREdit.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
const
SC_DragMove = $F012; // important key !!
begin
inherited;
if assigned(onMouseDown)then
OnMouseDown(self,Button,Shift,x,y);
if fDragable then
begin
ReleaseCapture;
(self as TControl).perform(WM_SysCommand, SC_DragMove, 0); // this is the key !
end;
end; end.
1、
releasecapture;
perform(wm_syscommand, $f012, 0);
最简单,但是很难实现一些特殊的效果
2、自己写控制类,通过记录鼠标位置的变化实现移动
效果折中,要求容器支持canvas。
3、完全靠自己画图实现
可以实现各种复杂的效果,但需要自己写很多代码(我的程序中是以着种方法实现移动的)
var
FMouseIsDown: Boolean;然后给你要移动的控件写三个事件处理函数(OnMouseDown, OnMouseUp, OnMouseMove):OnMouseDown中写:
FMouseIsDown := True;OnMouseUp中写:
FMouseIsDown := False;OnMouseMove中写:
if FMouseIsDown and (Sender is TWinControl) then
begin
ReleaseCapture;
SendMessage((Sender as TWinControl).Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
end;行了,玩去吧!
----------------------------------------------------------------------------------
SC_DRAGMOVE是自己定义的一个常量,系统中当然没有。
const
SC_DragMove = $F012; // important key !!
SC_MOVE 是系统定义的常量
SC_MOVE = $F010;
WM_SYSCOMMAND可以接受的参数大概有9个(与窗体移动相关),[$F001..$F008, $F012]
procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
const SC_DragMove=$f012;
begin
ReleaseCapture;
Panel1.perform(WM_SysCommand, SC_DragMove, 0); // this is the key !end;我解决了 其实对于所有有perform方法的都可以行得通的 包括窗体
而且,一个个都是Copy Code的高手。
我学delphi的第14天,碰到这样的事!
procedure TForm1.Button3MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var SC_MANIPULATE: Word;
Control: TControl;
begin
if (X<Control.Width-5) and (Y<Control.Height) then
begin
SC_MANIPULATE := $F009;
Control.Cursor := crSizeAll;
end
else begin
SC_MANIPULATE := $F000;
Control.Cursor := crDefault;
end;
if Shift=[ssLeft] then
begin
ReleaseCapture;
Control.Perform(WM_SYSCOMMAND, SC_MANIPULATE, 0);
end;
end;