各位大虾快救救我!如何完成控件拖动的编程?(250分)

  • 主题发起人 主题发起人 yanliangjr
  • 开始时间 开始时间
Y

yanliangjr

Unregistered / Unconfirmed
GUEST, unregistred user!
我最近遇到一个麻烦问题:现在要做一个软件的封面,(具体和NBase的网管系统软件的
封面差不多,不知道谁用过这个软件?)要完成以下功能:
界面内要放好多个“控件”,每一个“控件”代表有具体的含义。由于我作的也
是网管系统,这个软件是用来管理交换机,路由器,收发器等器件的。所以,控件上的
不同的图标就代表不同的器件。我现在要开发这么一个控件:当程序运行后,它会象
button那样凸起在界面内,当点击控件后,控件会凹下。而且控件可以在界面内随意的
放置(即控件会移动)。
我曾经试过richedit和label,但效果不好。当我在界面内拖动他们时,这两个
控件都“变形”了,我估计DELPHI在实现时重新画了一个FORM。这样不是太好。
不知道有那位大虾能够帮我呢?
谢谢了!
 
怎么老是没有人回答,是不是题目太难了?
 
你可以看看Delphi高级技术这本书,有介绍的。我这儿也有这样一个类
 
如果下周一还没人回答我来提供答案。
 
//TSizer

unit Sizer;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TSizer = class(TCustomControl)
private
{ Private declarations }
FControl:TControl;
FRectList:array[1..8] of Trect;
FPosList:Array[1..8] of integer;
protected
{ Protected declarations }
public
{ Public declarations }
Constructor Create(Aowner:TComponent;AControl:TControl);
procedure CreateParams(Var Params:TCreateParams);override;
Procedure CreateHandle;override;
Procedure WNNCHITTEST(var msg:Twmnchittest);message wm_nchittest;
procedure wmsize(var msg:Twmsize);message wm_size;
procedure WmLbuttonDown(var msg:twmlbuttondown);message wm_lbuttondown;
procedure wmmove(var msg:twmmove);message wm_move;
procedure paint;override;
procedure sizercontrolexit(sender:tobject);
published
{ Published declarations }
end;

procedure Register;

implementation

procedure Register;
begin
RegisterNoicon([Tsizer]);
end;

{ TSizer }

constructor TSizer.Create(Aowner: TComponent; AControl: TControl);
var
r:trect;
begin
inherited create(Aowner);
FControl:=Acontrol;
onexit:=sizercontrolexit;
r:=fcontrol.BoundsRect;
inflaterect(r,2,2);
boundsrect:=r;
parent:=fcontrol.Parent;
fposlist[1]:=httopleft;
fposlist[2]:=httop;
fposlist[3]:=httopRight;
fposlist[4]:=htRight;
fposlist[5]:=htBottomRight;
fposlist[6]:=htBottom;
fposlist[7]:=htBottomleft;
fposlist[8]:=htleft;
end;

procedure TSizer.CreateHandle;
begin
inherited createhandle;
setfocus;
end;

procedure TSizer.CreateParams(var Params: TCreateParams);
begin
inherited createparams(params);
params.ExStyle:=params.ExStyle+ws_ex_transparent
end;

procedure TSizer.paint;
var
i:integer;
begin
Canvas.Brush.Color:=clblack;
for i:=1 to 8 do
canvas.Rectangle(Frectlist.left,frectlist.top,frectlist.right,frectlist.bottom);
end;

procedure TSizer.sizercontrolexit(sender: tobject);
begin
free;
end;

procedure TSizer.WmLbuttonDown(var msg: twmlbuttondown);
begin
perform(wm_syscommand,$f012,0);
end;

procedure TSizer.wmmove(var msg: twmmove);
var
r:trect;
begin
r:=boundsrect;
inflaterect(r,-2,-2);
fcontrol.BoundsRect:=r;
fcontrol.Invalidate;
end;

procedure TSizer.wmsize(var msg: Twmsize);
var
r:trect;
begin
r:=boundsrect;
inflaterect(r,-2,-2);
fcontrol.BoundsRect:=r;
frectlist[1]:=rect(0,0,5,5);
frectlist[2]:=rect(width div 2-3,0,width div 2+2,5);
frectlist[3]:=rect(width-5,0,width,5);
frectlist[4]:=rect(width-5,height div 2-3,width,height div 2+2);
frectlist[5]:=rect(width -5,height-5,width,height);
frectlist[6]:=rect(width div 2-3,height-5,width div 2+2,height);
frectlist[7]:=rect(0,height-5,5,height);
frectlist[8]:=rect(0,height div 2-3,5,height div 2+2);
end;

procedure TSizer.WNNCHITTEST(var msg: Twmnchittest);
var
pt:tpoint;
i:integer;
begin
pt:=point(msg.XPos,msg.YPos);
pt:=screentoclient(pt);
msg.Result:=0;
for i:=1 to 8 do
if ptinrect(frectlist,pt) then
msg.Result:=fposlist;
if msg.Result=0 then
inherited;
end;

end.

//调用

tsizer.create(self,tcontrol(sender));


你可以将改变大小部分去掉的
 
告诉你一个简单方法:
当按下鼠标时向控件发送WM_SysCommand消息。如下
const
sc_drag=$F012;

//这是按纽的鼠标按下事件;
procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if ssCtrl in Shift then
begin
ReleaseCapture;
TWinControl(Sender).Perform(wm_syscommand,sc_dragmove,0);
end;
end;

 
djdsz这段程序不错,只是人家要求很简单,
balaschen给出的足够用了。
 
谢谢诸位给我的帮助.
To:balaschen
1. " if ssCtrl in Shift then "应为"if ssLeft in Shift then"才对.
这个程序是可以完成移动按钮的功能,但是,这个程序为什么能完成这样的功能?
balaschen老兄能不能给我讲解一下?
2.如何显示凹下好凸起功能?即,当我鼠标点击时按钮凹下,当焦点离开时按钮再凸起?
3.如何在按钮上添加图片?
To:djdsz
你所说的DELPHI高级编程的书是什么样的书?有没有电子版?如果有的化,能不能
给我发一个过来?
再一次谢谢诸位!
 
>>1. " if ssCtrl in Shift then "应为"if ssLeft in Shift then"才对.
这样没错,这样做的目的是保留按钮正常的单击事件。
>>如何显示凹下好凸起功能?
在拖动过程中是无法完成的,除非你自己写一个控件,在开始拖动前绘制按钮的按下状态
在拖动结束时绘制正常状态。当然还有一种方法,即不用系统的WM_SysCommand消息而用
MouseDown,MouseMove,MouseUP事件自己控制,可能也是你原先用的方法,但是有大量的事情
要自己控制。
>>这个程序为什么能完成这样的功能?
不是说的很清楚吗,是通过发送WM_SysCommand消息来实现的。
>> 3.如何在按钮上添加图片?
用TBitBtn即可。
 
To balaschen:
我仔细想了一下,用button是不行的.因为我要要是两个器件之间有联系,我要
在两个button之间画线.要画线的话就要知道这两个button的中心坐标,当鼠标移动nutton
时,但是我没有法子确定button移到的点的中心坐标,所以我觉得仅仅用button 是不行的.
或者,如果用button的话,不知道你有没有好一点的解决办法?

To djdsz:
你的代码我看了一下,有点看不懂,你能不能就怎样建立按钮、移动按钮、并在两个
按钮之间画线给我举一个例子?
谢谢诸位!
 
你要画线你说呀,你不说我怎么会知道:)
我有一个支持运行时拖动的控件,可以设置上下级关系,自动画线,不过不能显示图片,带
Source,你自己爱怎么改就怎么改。
如过你要的话给发mail,好用的话得给我另外加分,因为问题已经超出你原来的问题。
 
TO balaschen:
OK! 谢谢了!分的问题不是问题.如果你要你就说,你不说我怎么知道你要?说了我才会
知道嘛!
 
大家好!
balaschen给的控件我也看过了,可就是不知道怎么改!
不知大家有没有更好的办法?
djdsz:
你的代码我看了一下,有点看不懂,你能不能就怎样建立按钮、移动按钮、并在两个
按钮之间画线给我举一个例子?
 
研究了一下balaschen的代码,其实代码可以改成如下形式:
if ssCtrl in Shift then
begin
ReleaseCapture;//取消这次鼠标作用,使鼠标的点击事件无效
TWinControl(Sender).Perform(wm_syscommand,SC_MOVE+1,0);
end;
我windows处理wm_syscommand的消息应该是这样的:
1、首先SetCapture
2、根据鼠标的运动状况,重新绘制control
3、鼠标抬起,releaseCapture
可以用如下的程序证实:
if ssCtrl in Shift then
begin
ReleaseCapture;//取消这次鼠标作用,使鼠标的点击事件无效
TWinControl(Sender).Perform(wm_syscommand,SC_MOVE+1,0);
TWinControl(Sender).Perform(wm_syscommand,SC_SIZE+8,0);
end;
上面的程序向button发送了两个wm_syscommand消息。试验证明,
先是移动button,然后再调整button的大小。windows先处理
SC_MOVE消息,返回0以后再处理SC_SIZE消息。
另外SC_SIZE+i,i:=0,1,2..有不同的含义,大家自己试试看吧,
呵呵,很有意思的说!


 
多人接受答案了。
 
后退
顶部