我原来写的一篇文章:
在使用很多RAD开发工具,象VB、Delphi。当象窗口上添加一个控件之后,只要在控件上按下鼠标左键不放就可以
拖动控件了。或者点击控件,再在控件周围的小黑块上拖动鼠标就可以动态设置控件大小了。有时我们的程序中也需要
这样的功能。那么如何实现这样的功能呢?我们可以想一下在Window中什么样的控件可以通过拖动来改变位置和大小呢?
对了,就是平常的窗口,只要点击标题栏并拖动鼠标就可以改变窗口的位置,光标移动到窗口的边缘并拖动就可以改变
窗口的大小。那么窗口是如何实现这样的功能的呢?在Windows中,当光标在控件上移动或者点击鼠标,系统就会向控件
发送WM_NCHITTEST消息。然后根据消息处理函数返回的数值“判断”光标位于控件的什么位置并根据当前鼠标状态来决定
对窗口的处理。例如如果窗口返回的数值表示光标位于窗口的标题栏上并且鼠标处于移动状态同时鼠标左键是按下的。系
统就会移动窗口。
明白了这样的道理,我们就可以在编写控件的消息处理函数中返回不同的NCHitTest数值来“欺骗”系统。由于Delphi
不单是一个RAD系统,同时也支持自定义消息处理,所以在这里我们选择使用Delphi。
下面是程序范例:首先建立一个新的Application。将Form1中的代码清空,并加入以下代码:unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TCmd = class(TButton)
protected
procedure NCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
procedure LButtonDown(var Msg: TMessage); message WM_LBUTTONDOWN;
public
iDirec:Integer;
end;type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}procedure TCmd.LButtonDown(var Msg:TMessage);
begin
inherited;
end;procedure TCmd.NCHitTest(var Msg: TWMNCHitTest);
var
tpClient,tpScreen:TPoint;
iLeft,iRight,iTop,iBottom:Integer;
begin
inherited; //将控件的左上角坐标转换为屏幕坐标,在根据此坐标得到控件的右边缘以及下
//边缘相对屏幕的坐标
tpClient.x :=0;
tpClient.y :=0;
tpScreen:=ClientToScreen(tpClient);
iLeft:=tpScreen.x;
iRight:=iLeft+Self.Width;
iTop:=tpScreen.y;
iBottom:=iTop+Self.Height; //根据光标的位置返回不同的HitTest值欺骗系统,让系统认为光标以及鼠标按键
//按下的位置的位置在窗口标题栏上或者在窗口边框上
if ((Msg.XPos > iRight - 3) and (Msg.YPos<iBottom - 2) and
(Msg.YPos > iTop + 2)) then //光标在控件的右边边缘
Msg.Result := HTRIGHT
else if((Msg.XPos < iLeft + 3) and (Msg.YPos<iBottom - 2) and
(Msg.YPos > iTop + 2)) then //光标在控件的左边边缘
Msg.Result := HTLEFT
else if ((Msg.YPos > iBottom - 3) and (Msg.XPos < iRight - 2) and
(Msg.XPos > iLeft + 2)) then //光标在控件的下边边缘
Msg.Result := HTBOTTOM
else if ((Msg.YPos < iTop + 3) and (Msg.XPos < iRight - 2) and
(Msg.XPos > iLeft + 2)) then //光标在控件的上边边缘
Msg.Result := HTTOP
else //光标位于控件中
Msg.Result := HTCAPTION;
end;end.然后在Form1的OnCreate事件中加入以下代码:
procedure TForm1.FormCreate(Sender: TObject);
var
cmdTemp:TCmd;
begin
cmdTemp:=TCmd.Create(Self); //建立一个新的TCmd对象
cmdTemp.Parent:=Self;
cmdTemp.Left := 30;cmdTemp.Width :=60;
cmdTemp.Top :=40;cmdTemp.Height :=20;
cmdTemp.Show;
end; 运行程序,将光标移动到控件边缘,可以看到光标变成了双箭头形状,这时你就可以象改变窗口大小那样来通过拖动
改变控件大小。将光标移动到控件中间,就可以通过拖-放来移动控件了。
在使用很多RAD开发工具,象VB、Delphi。当象窗口上添加一个控件之后,只要在控件上按下鼠标左键不放就可以
拖动控件了。或者点击控件,再在控件周围的小黑块上拖动鼠标就可以动态设置控件大小了。有时我们的程序中也需要
这样的功能。那么如何实现这样的功能呢?我们可以想一下在Window中什么样的控件可以通过拖动来改变位置和大小呢?
对了,就是平常的窗口,只要点击标题栏并拖动鼠标就可以改变窗口的位置,光标移动到窗口的边缘并拖动就可以改变
窗口的大小。那么窗口是如何实现这样的功能的呢?在Windows中,当光标在控件上移动或者点击鼠标,系统就会向控件
发送WM_NCHITTEST消息。然后根据消息处理函数返回的数值“判断”光标位于控件的什么位置并根据当前鼠标状态来决定
对窗口的处理。例如如果窗口返回的数值表示光标位于窗口的标题栏上并且鼠标处于移动状态同时鼠标左键是按下的。系
统就会移动窗口。
明白了这样的道理,我们就可以在编写控件的消息处理函数中返回不同的NCHitTest数值来“欺骗”系统。由于Delphi
不单是一个RAD系统,同时也支持自定义消息处理,所以在这里我们选择使用Delphi。
下面是程序范例:首先建立一个新的Application。将Form1中的代码清空,并加入以下代码:unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TCmd = class(TButton)
protected
procedure NCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
procedure LButtonDown(var Msg: TMessage); message WM_LBUTTONDOWN;
public
iDirec:Integer;
end;type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}procedure TCmd.LButtonDown(var Msg:TMessage);
begin
inherited;
end;procedure TCmd.NCHitTest(var Msg: TWMNCHitTest);
var
tpClient,tpScreen:TPoint;
iLeft,iRight,iTop,iBottom:Integer;
begin
inherited; //将控件的左上角坐标转换为屏幕坐标,在根据此坐标得到控件的右边缘以及下
//边缘相对屏幕的坐标
tpClient.x :=0;
tpClient.y :=0;
tpScreen:=ClientToScreen(tpClient);
iLeft:=tpScreen.x;
iRight:=iLeft+Self.Width;
iTop:=tpScreen.y;
iBottom:=iTop+Self.Height; //根据光标的位置返回不同的HitTest值欺骗系统,让系统认为光标以及鼠标按键
//按下的位置的位置在窗口标题栏上或者在窗口边框上
if ((Msg.XPos > iRight - 3) and (Msg.YPos<iBottom - 2) and
(Msg.YPos > iTop + 2)) then //光标在控件的右边边缘
Msg.Result := HTRIGHT
else if((Msg.XPos < iLeft + 3) and (Msg.YPos<iBottom - 2) and
(Msg.YPos > iTop + 2)) then //光标在控件的左边边缘
Msg.Result := HTLEFT
else if ((Msg.YPos > iBottom - 3) and (Msg.XPos < iRight - 2) and
(Msg.XPos > iLeft + 2)) then //光标在控件的下边边缘
Msg.Result := HTBOTTOM
else if ((Msg.YPos < iTop + 3) and (Msg.XPos < iRight - 2) and
(Msg.XPos > iLeft + 2)) then //光标在控件的上边边缘
Msg.Result := HTTOP
else //光标位于控件中
Msg.Result := HTCAPTION;
end;end.然后在Form1的OnCreate事件中加入以下代码:
procedure TForm1.FormCreate(Sender: TObject);
var
cmdTemp:TCmd;
begin
cmdTemp:=TCmd.Create(Self); //建立一个新的TCmd对象
cmdTemp.Parent:=Self;
cmdTemp.Left := 30;cmdTemp.Width :=60;
cmdTemp.Top :=40;cmdTemp.Height :=20;
cmdTemp.Show;
end; 运行程序,将光标移动到控件边缘,可以看到光标变成了双箭头形状,这时你就可以象改变窗口大小那样来通过拖动
改变控件大小。将光标移动到控件中间,就可以通过拖-放来移动控件了。
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货