说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

用Delphi开发分隔线组件

HTML文档下载 WORD文档下载 PDF文档下载
用Delphi开发分隔线组件

【摘要】本文以分隔线为例,采用面向对象方法,介绍了如何用Delphi开发Windows

的可视化控件。可视化控件具有较强的实用价值,用Delphi语言开发控件简便、方

便、

效率高。

关键词:Delphi 控件 面向对象

一、引言

Delphi除了能采用可视化方法进行编程和系统开发外,还有非常重要的一个功能,

就是能用其语言本身开发Delphi的可视化控件(Component)。Delphi是完全面向对

象的语言,其各个控件都是从最基本的类TClass逐步继承而来,因此,编程者也可

通过继承Delphi标准的控件类,开发出自己的控件,以满足某些特殊需要或使界面

更为友好、美观。

在Windows 95的某些窗口中,用到了很多分隔线(如在资源管理器窗口中)。分隔

线将一个窗口分成两个或多个部分。这些部分可能是面板(Panel)、图形、列表框

或编辑区。当鼠标移到分隔线上时,光标会变成左右箭头或上下箭头,将鼠标按住

并按指示的方向左右或上下拖动,就会使其中某部分放大,而另一部分缩小,从而

提高了窗口各部分的可视范围,增加了窗口的信息量。

二、基本原理

分隔线界于窗口中两个控件之间。首先要在当前窗口中找到分隔线控件,并记录它

的状态;然后要在窗口中找到与它相邻的控件,并记录它们的当前状态,然后再通

过分隔线的鼠标事件控制各个控件的移动及尺寸变化,从而达到用分隔线分隔窗口

的动态效果。

三、分隔线控件(TSplit)对象

分隔线控件对象由现有的控件对象继承而来,在此基础上,还必须有它本身的私有

变量(方法)和公有变量(方法)。具体为:

1、 首先定义分隔线控件类:TSplit。由于Delphi的面板控件Tpanel具有可改变其

凸凹、形状大小等属性,所支持的事件方法也较多,因此采用Tpanel作为TSplit的

父类。

2、 定义TSplit的私有变量和方法:与分隔线有关的一些控件,如其所在的窗口、

分隔线本身、分隔线的坐标、分隔线在移动时使其大小改变的控件(主要指分隔线

的左侧或上侧的控件,以下称目标)等,这些定义为私有变量;对分隔线和其周围

控件的检测、画阴影线以及求其状态等过程(子程序),定义为私有方法。其中关

键的变量有FSplitControl,FSizeTarget,它们为分隔线变量和所移动的目标控件

变量,通过调用私有方法GetComponent可将它们赋值,得到分隔线和目标的实例,

从而便于对他们操作。在分隔线移动时,DrawSizegLine方法画出它的阴影线。

3、定义公共方法:公共方法定义了TSplit的构造函数、开始移动分隔线、改变分隔

线 的 位 置、分隔线停止移动时调整目标(被分隔线改变形状的控件)尺寸等过

程,以及分隔线的鼠标事件:按下、移动和弹起。另外,还定义了分隔线是否可移

动的属性(property),以判断分隔线的当前状态。

鼠标事件是分隔线移动和目标改变大小的触发点,对鼠标事件进行重载,使得移动

和变化得以实现。在MouseDown事件中,加入了公共方法BeginSizing,对分隔线对

象初始化;MouseMove事件中加入ChangeSizing方法,改变分隔线位置和画阴影;

MouseUp事件中加入EndSizing,停止分隔线的移动,改变目标大小。

4、分隔线控件实现过程 (见附录:split.pas程序及其说明。)

四、控件的安装方法

在Delphi 1.0的系统菜单Options下(2.0为Components),选择Install Component子

菜单,弹出对话框,按Add按纽,在输入栏键入程序名及其路径,再按OK键,等待编

译完毕,在Delphi的控件列表中的Sample栏中就会出现我们所开发的新控件:

Split。

五、使用方法

1、 建立一个新的项目文件(Project),在新窗口上放置一个面板(或列表框、树

型结构列表、图形框、记忆框等),将其Align属性设为Left;

2、 从控件列表中的Sample栏中选取Split控件放于窗口,将其形状改为垂直的长条

窄棒,并将Align属性设为Left,Cursor属性设为crHSplit;

3、 再在窗口中放一个面板(或其他控件),将其Align属性设为Client;

4、 运行该项目文件,当鼠标移动到分隔线上,且光标变为左右箭头时,即能将其

两边的部分放大或缩小。

若想做成上下分隔线,将以上1和2中的Align属性设为Top,2中的Cursor属性设为

crVSplit,其余不变即可。

另外用户还可在3中的面板上再按1、2、3的步骤进行操作,将整个窗口用两个分隔

线分为3个部分。以此类推,可将窗口分为任意多个部分。

本程序在Delphi 1.0和2.0下调试通过。

附录:源程序split.pas

unit Split;

interface

uses

SysUtils

WinTypes

WinProcs

Messages

Classes

Graphics

Controls

Forms

Dialogs

ExtCtrls;

type {定义分隔线控件类}

TSpliter = class(TPanel) {TSpliter类从Tpanel类继承}

private {定义私有变量和方法}

FForm: TForm; {分隔线所在的窗口变量}

FSplitControl

FSizeTarget: Tcontrol; {分隔线及要改变的目标控件变量}

FVertical: Boolean; {分隔线方向变量}

FSplit: TPoint; {分隔线坐标变量}

FAOwner: TComponent; {分隔线的拥有者变量}

procedure GetComponents; {获得分隔线和目标实例}

function GetSizing: Boolean; {判断分隔线状态}

procedure DrawSizingLine; {画分隔线阴影}

public {定义公共方法}

constructor Create(AOwner: TComponent);override; {构造函数}

procedure BeginSizing; {移动前初始化}

procedure ChangeSizing(X

Y: Integer); {改变分隔线位置}

procedure EndSizing; {终止移动}

property Sizing: Boolean read GetSizing; {分隔线是否可移动属性}

procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X

Y:Integer); Override; {按下鼠标事件}

procedure MouseMove(Shift: TShiftState; X

Y: Integer);override; {移动鼠

标事件}

procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X

Y: Integer);override; {弹起鼠标事件}

end;

procedure Register; {控件注册}

implementation

constructor TSpliter.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

FAOwner := AOwner;

FForm:= TForm(FAOwner); {定义分隔线所在的窗口类}

end;

function CToC(C1

C2: TControl; P: TPoint): TPoint; {转换分隔线坐标函数}

begin

Result := C1.ScreenToClient(C2.ClientToScreen(P)); {将分隔线坐标转化为窗

口坐标}

end;

function TSpliter.GetSizing: Boolean;

begin

Result := FSplitControl <> nil; {是否获得了分隔线变量}

end;

procedure TSpliter.DrawSizingLine;

var P: TPoint;

begin

P := CToC(FForm

FSplitControl

FSplit);

with FForm.Canvas do begin

MoveTo(P.X

P.Y);

if FVertical then {若为上下移动的分隔线,画横向阴影线}

LineTo(CToC(FForm

FSplitControl

Point(FSplitControl.Width

0)).X

P.Y)

else {否则}

LineTo(P.X

CToC(FForm

FSplitControl

Point(0

FSplitControl.Height)

).Y) {画竖直的阴影线}

end;

end;

procedure TSpliter.BeginSizing;

begin

GetComponents;

SetCaptureControl(FSplitControl); {使分隔线可接受鼠标事件}

if FVertical then {获得分隔线的坐标}

FSplit := Point(0

FSplitControl.Top) else

FSplit := Point(FSplitControl.Left

0);

FForm.Canvas.Handle := GetDCEx(FForm.Handle

0

DCX_CACHE or

DCX_CLIPSIBLINGS

or DCX_LOCKWINDOWUPDATE); {取窗口句柄}

with FForm.Canvas do begin {设置画笔状态模式}

Pen.Color := clWhite;

if FVertical then

Pen.Width := FSplitControl.Height else

Pen.Width := FSplitControl.Width;

Pen.Mode := pmXOR;

end;

DrawSizingLine;

end;

procedure TSpliter.ChangeSizing(X

Y: Integer);

begin

DrawSizingLine;

if FVertical then FSplit.Y := Y else FSplit.X := X; {移动分隔线位置}

DrawSizingLine;

end;

procedure TSpliter.EndSizing;

var

DC: HDC;

P: TPoint;

begin

DrawSizingLine;

P := CToC(FSizeTarget

FSplitControl

FSplit); {将分隔线坐标转化为目标控

件坐标}

SetCaptureControl(nil); {将可接收鼠标事件的控件置空}

FSplitControl := nil; {分隔线对象指向空}

with FForm do begin

DC := Canvas.Handle;

Canvas.Handle := 0;

ReleaseDC(Handle

DC); {释放窗口句柄}

end;

if FVertical then begin {若为上下移动的分隔线}

if P.Y >= FSizeTarget.Parent.Height then Exit {若分隔线超过窗口高度退出}

else FSizeTarget.Height := P.Y; {否则改变目标高度}

end

else begin

if P.X >= FSizeTarget.Parent.Width then Exit {若分隔线超过窗口宽度退出}

else FSizeTarget.Width:= P.X; {否则改变目标宽度}

end;

end;

procedure TSpliter.MouseDown(Button: TMouseButton; Shift: TShiftState;

X

Y: Integer);

begin

inherited MouseDown(Button

Shift

X

Y); {继承原方法}

if (Button = mbLeft) and (Shift = [ssLeft]) then BeginSizing; {判断鼠标按

键,开始移动}

end;

procedure TSpliter.MouseMove(Shift: TShiftState; X

Y: Integer);

begin

inherited MouseMove(Shift

X

Y);

if Sizing then ChangeSizing(X

Y);

end;

procedure TSpliter.MouseUp(Button: TMouseButton; Shift: TShiftState;X

Y: Integer);

begin

inherited MouseUp(Button

Shift

X

Y);

if Sizing then EndSizing; {若获得分隔线对象,结束移动}

end;

procedure TSpliter.GetComponents;

var I: Integer;

begin

FSplitControl:= GetCaptureControl; {获得窗口中的分隔线对象}

FVertical := FSplitControl.Width > FSplitControl.Height;

if not FVertical then begin {若为横向分隔线}

for I:= 0 to FSplitControl.Parent.ControlCount-1 do {在分隔线所在的控件上

搜寻与它相邻的控件}

begin

if (FSplitControl <> FSplitControl.Parent.Controls[I]) and

(FSplitControl.Left - FSplitControl.Parent.Controls[I].Width >= 0) and

(FSplitControl.Left - FSplitControl.Parent.Controls[I].Width < 8) then

begin

FSizeTarget:= TControl(FSplitControl.Parent.Controls[I]); {获得目标控件}

Break; {跳出循环}

end

end;

end

else begin {若为纵向分隔线}

for I:= 0 to FSplitControl.Parent.ControlCount-1 do begin

if (FSplitControl <> FSplitControl.Parent.Controls[I]) and

(FSplitControl.Top - FSplitControl.Parent.Controls[I].Height >= 0) and

(FSplitControl.Top - FSplitControl.Parent.Controls[I].Height < 8) then

begin

FSizeTarget:= TControl(FSplitControl.Parent.Controls[I]);

Break;

end;

end;

end;

end;

procedure Register;

begin

RegisterComponents('Samples'

[TSpliter]); {将分隔线控件注册到Sample控件

列表中}

end;

end.

submit()-JQuery API toggle(even,odd)-JQuery API trigger(type)-JQuery API unbind(type,fn)-JQuery API unload(fn)-JQuery API Effects特效-JQuery API animate-JQuery API fadeIn(speed, callback)-JQuery API fadeOut(speed,callback)-JQuery API fadeTo(speed,opacity,callback)-JQuery API hide(speed,callback)-JQuery API hide()-JQuery API show(speed,callback)-JQuery API show()-JQuery API slideDown(speed,callback)-JQuery API slideToggle(speed,callback)-JQuery API slideUp(speed, callback)-JQuery API toggle()-JQuery API Javascript-JQuery API $.browser-JQuery API $.each(obj, fn)-JQuery API $.extend(target,prop1,propN)-JQuery API $.grep(array,fn,inv)-JQuery API $.map(array, fn)-JQuery API $.merge(first,second)-JQuery API $.trim(str)-JQuery API Ajax-JQuery API $.ajax(properties)-JQuery API $.ajaxSetup(settings)-JQuery API $.ajaxTimeout(time)-JQuery API $.get(url, params, callback)-JQuery API 请大家说一下哪个代理注册的网站收费比较底,而且服务又比较好的,谢谢! 在asp中如何实现记录集与编辑框、table表等的数据绑定,给个思路也行。着急呀 [-------大虾帮忙啊--------] bcb中缺少的帮助文件能否再添加? 在哪里可以找到关于sybase的资料 哪位仁兄知道如何打包delphi开发的sybase客户程序,最高78分奉送 一个关于OnDraw()的重绘问题,急急急急急急急! 新手的问题! dll调问题???VB调用VC++的DLL需要返回值时,DLL如何定义?VB调用函数如何定义??? 各位大虾 谁能提供视频采集卡的原代码,必须要CB的,300分 在堆(heap)上与在栈(stack)上建立的对象有什么区别? 一个问题,在做元件时怎样建立TdateTimePicker 给大家看看我弟弟给我的信 求助,标题栏为“The police are investigating the robbery-"的是什么程序? 谁能将.CPP文件的代码翻译成DELPHI语言?? 有关于FLASH5.0的问题!!!请各位大吓指点! 一个问题,怎样在PC:PageControl上增加TabSheet1,TabSheet1,TabSheet1…. 标题栏为“The police are investigating the robbery-"的是什么程序? 一个弱弱的问题 一个问题,建立的 FB: TBevel没显示,好象根本没建立一样。 如何在 MDI CLIENT 中添加快捷方式??谢谢!! 55分,如何映射控件中子控件的消息? 如何选择书 关于文献数据库的一个问题-如何把一个字段和一个文件关联起来? 所有喜欢到水园来逛逛,但是从不回帖子或很少回帖子的人进来签到~~~~ 谁来救救我呀,我好惨呀。。。。 如何通过VC编程,随时关闭网络端口 诚寻对嵌入式linux感兴趣的网友 今天临走前,再灌一桶酒! 急!!!哪里可以下载到制作工具栏时用到的位图呀? 太原的在哪能买到程序员杂志 我的qq:10120129 谁找我??? xml 高手帮帮我,为什么我下面的文件,在IE5.0中什么也没有?? 请问高手:在uml类图中如何用关系表示一个实体类和一个接口间的关系。 Cathy进来~~ 请问高手们一个Delphi的一个应该是比较底层的东西。 mimi大酒店正式開業﹗先進來的有分啊﹗ 哪个高手完整地讲讲OpenWith菜单项的调用方法和函数等 关于非模态对话框中使用UpdateData(FALSE)函数的问题,朋友,帮个忙好吗? “记事本”小问题,大逻辑.大虾们,照顾照顾小弟呗. Linux下配置ISDN--期待所有的Linux高手到来?? 我是女生,哈哈 急,怎么样在打印表格时使较长的字段分两行显示,并字体变小。 在VB里做的用户控件为什么在VC不能调用啊! 不服不行(真没辙了)[不够可在加200分] 我的代理怎么了? 寻找能显示CAD图纸的delphi控件 偶要给lastlove(☆☆☆☆☆robin★★★★★)放高利贷了! 哪位做过读取网卡地址的动态链接库? c++builder与sql server 2000的sql语言兼容性问题 所有自然数相乘等于几? 如何测智力? 物理和智商有关系么,为什么有些女生物理好但是数学不好呢 所有自然数相乘等于几?3Q所有自然数相乘等于几?(注:这是一个准确的数!不是什么X/N/Y 之类的!) 测智力如何测? 高中物理学不好是不是和智商有关系?是或者不是.不要听什么假安慰的话那有没有改进的方法? 一个自然数它本身的各个数位上的数字之和与17相乘等于这个数,这个自然数是多少?我希望你们能给我一个解答的过程,应该怎样去说,才是有理有条的.因为那个结果是不难知道 钱学森的数学智力测试题?8————————》99 11———————》126 26———————》26115———————》? 帮忙找一些物理方面的智力问答题,RT要的,至少20道吧…… 哪两个自然数相乘等于13? (初二英语智力测试题) 具体地说说为什么!At a school outing 81℅ of the boys lost a shoe,82℅ of the boys lost a sock,77℅ of the boys a cap and 68℅ of the boys lost a bag.What's the least percentage who lost all 4 things? 为什么1+1+2 不等于三谢谢了, 求数学大神来算下这个的面积.. 求左边的面积(包括三角) 和右边的面积 -.- 狂风暴雨神倒颠打一生肖 2/(√3-1)等于多少谢谢了, 这个时间还有数学大神吗 求神级智商解答! (2)(3)求大神 1.已知x为整数,且2/(x+3)+2/(3-x)+2x+18/x²-9为整数,求所有符合条件的x的值2.解方程2(x²+1/x²)-3(x+1/x)-1=03.试证:对任意的正整数n,有1/1*2*3 + 1/2*3*4 + ...+1/n(n+1)(n+2) 神起的红色风暴和神话的白色风暴是怎么一回事.?什么叫不要成为第2个ANDY.?SM公司打过艺人么,? 数学大神请入3+6+9+……+3n=? 第9题选什么求数学大神 小明和小华一起做功课,小明对小华说:“我出一道题给你做做:一个多边形各内角都等于72°,求这个多角形的边数.”小华想了想,答不上,后来他对小明说:“我也考考你:一个凸四边形的四 1加1在什么时后会等于3大神们帮帮忙 第9题,数学大神来,快 有1、2、3、4四个数 2 的出现几率是1的一半、3的出现几率是2的一半、4的出现几率是3的一半.1、2、3、4 的出现几率加一起等于1(100%)那么1、2、3、4的出现几率各是多少 公式是什么?同理5个 一加一可以不等于二,一加一可以等于三吗? 第二题,求数学大神解答 我的神 我的神把两个式子相加得到:a3+a7-a10+a11-a4=12=a3+a11-(a10+a4)+a7=12 因为a3+a11=a10+a4所以 要是-(a10+a4)+ a3+a11那就=0了 所以就是0+a7=12 然后…… 然后就求出来了.问;为什么不能用3+7-10=0 11-4-7 求大神解这两道题,原谅我数学不好…详细请看图 求数学大神,第9题,只要正确,定当采纳. 龟与神赛跑的数学问题叫什么之论?龟与神赛跑,神先让龟跑一段距离,然后神再追.问神能否追上.答案是实际神能追上,理论追不上龟. 寻极度无聊IQ题必须系搞笑的!例如铁甲无敌奖门人之类嘎 10个以上才要!多1个+给1分 一道关于数学三角函数的题,哪位数学好的朋友帮哈忙,谢 证明sin(x+y)-sinx=2cos((2x+y)\2)sin(y\2)有点急,喜欢数学的朋友来帮哈忙哈,对不起,我再查查 第十题. 神才能做的高一数学难题数列{10^(n/11)}前n项之积大于10^5的最小正整数n=?(最好有过程,感激不尽!) 关于三角函数的数学 如图在三角形abc中角bac等于70度,点d,e分别在ab ac上,且de平行bc,点f在de上,且bd=df ce=ef 则角baf等于 we want to know in____ case people's hidden consciousness can be developedA which B that C whose D what为什么不选A啊 2 Albert Einstein was the first man_____the great amount of energy locked in theatomA to realize B realize C realized D having 有关三角函数的题,求数学大神解答!具体如图:能详细解答吗? 高二数学有关求导的解答,数学大神进!谢谢 CAD请问这个几何图形怎么做啊,想了几天了,求大神们回答,外形差不多这样,已知道尺寸. 数学三角函数.算的好难过啊. 24题怎么求导?求大神帮忙解答下!谢谢! 英语翻译 关于爱因斯坦的数学游戏,随便做运算可以知道起始数字的那个,请问一下怎么解的大科学家爱因斯坦小时候就特别聪明,有一次同学们在一起玩,他说:“我们做一个数学游戏怎么样?”同学们 求大神解用变限积分求导解此题 12个9加减乘除等于1212,急…… 求爱因斯坦数学题.有一条长阶,若每步跨2阶,则最后剩1阶;若每步跨阶,则最后剩2阶;若每步跨5阶,则最后剩4阶;若每步跨7阶,则最后正好一阶不剩.答;#include int main(void){int steps = 29,i = 1;while ( steps 数学的二次求导到底干嘛用的,求什么的?高中多用二次求导来证数列不等式,到底二次求导怎么用,用在哪的? 1-3-7-5加减乘除怎么得24? "爱因斯坦的数学游戏"大科学家爱因斯坦小时候就特别聪明,有一次同学们在一起玩,他说:“我们做一个数学游戏怎么样?”同学们说:爱因斯坦说:“你们随便想一个数,然后做一些运算,我就 哪能测智力,我测过一个33道问题的那个,但分太低,我不可能就有比弱智聪明一点!谁有再给我一个 分数加减乘除法的意义和整数加减乘除法的意义有什么不同问答题 解上来你就号称第二爱因斯坦5乘5的方格从1开始依次排列到24.1旁边的X不用写~就还剩下24个格子!两数之间不能不能跳跃!必须是两数紧靠着!也不能倾斜着写. 我测过一个33道问题的那个,但分太低,我不可能就有比弱智聪明一点!谁有再给我一个 将八个8用加减乘除等运算符连起来,怎么得到1000? 爱因斯坦 数学只有1分.据说德国的大学1分是满分.那到底爱因斯坦的1分是最高分还是最低分?从前,看故事,说爱因斯坦小时候数学不好,考试只有1分,但是努力学习后成为了最伟大的物理学家,当 怎样测智力?智力 我智商130左右,但为什么还是学不好数学和物理啊.做了许多测试,智商在130左右.其中一种测试中显示我右脑智商70+,左脑智商50+.数学和物理是用的哪个脑?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn