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

用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.

数据约束控件和 RecordSet-VB资料 锁住数据库中的表 -VB资料 谈谈VB的数据库编程方式 为VB5辩解: VB处理数据库时求数据表记录总数的最佳方法 为什么安装后的数据库应用总是路径不对或找不到? 返回 -VB资料 无论如何,就是只能输入数字-VB资料 VB用 DAO 或 ADO 正确访问 Access 2000 VB用CELL组件显示Access数据库的图片对象 VB用DAO打开Excel文件 VB用DATA控件绑定报表控件打印报表 VB用EXCEL来打印报表并生成折线图 VB用EXCEL组件简化VB编程的一种方法 VB用MDB文件做密码库 VB用ODBC API访问ODBC数据库 用VB 实现类电子表格的数据录入 用VB5直接控制Excel 97 用VBA编制Access的查询程序 用VB和RDO访问SQL Server 用VB开发多通道仪表数据采集程序 用VB实现关闭所有数据库对象 用VB实现类电子表格的数据录入 VB用代码创建数据库,表,字段 VB用类来编写数据库程序 优化OLE的调用频率-VB资料 语言选择引起的查询错误 -VB资料 远程数据库的访问-VB资料 运用ADO进行数据库表数据互导 -VB资料 在 VB5.0中编辑数据库和电子表格 在Access 2000中用ADO-VB资料 在Access数据库中实现密码管理的另一种方式 -VB资料 在VB6.0中使ACCESS数据库在网络使用中保持同步 特困求助:在网页中,向ocx传送参数,ocx中该怎样写 写??? 顾客显示屏的问题,打不开端口? 为什么代码提示,有的时候有,有的时候却没有出现? 好久没有来了,今天来逛逛!!! 如何添加一个 .pas文件 共享源代码 头脑风暴:我想做个口语考试系统,请大家提提需求 怎么在Interbase中锁表? 打印求助!急啊。。。 各位高手,100分求教 请问用C#如何实现可以向任意边停靠(并非DockStyle.Fill)的窗口? 我用 clientdataset 增加一条记录后如何在相关的DBGrid中同步显示? asp.net中有自己带的treeview类吗?(在web 应用程序) 什么c语言编辑器好用,(除了turboc,vc外,)请问高手 帮忙看一下 奇怪,直接继承CDialog类竟然用不了它的默认构造函数(我是菜鸟,帮帮我) Kenel panic:No init found. Try passing init=optino to kernel. 好心人帮帮我好么?在线等。。 superdullwolf(超级大笨狼) 来接分!!!!!!!!!!!!!!! 我的机器是win2000,安装了vmware软件,在模拟win2000pro时检测到了usb硬盘。后来,重新启动计算机,usb硬盘再也不认了,出现了usb硬盘的 有什么办法可以禁止FLASH右键 我得到了Msg.LParam,并且知道它发过来的是一串字符,请问怎样将Msg.LParam转成字符串显示出来? windows socket 1.1的一个问题 这个查询怎么写? rzhou(海盗) 收分来 寻程序员,短期,欢迎加盟!!!!!---------熟悉j2me的!!!!面试合格,待遇为150/天 如何在ADO中设置SQL的字符集? fastreport合计问题????兄弟们指点指点啊!!!! 怎样提高DCOM的响应速度 如何用ASP 在函数/过程中建立全局变量 金刚般若波罗蜜经  陈天竺三藏真谛译  如是我闻。一时佛婆迦婆住舍卫国只陀树林给孤独园。与大比丘众千二百五十人俱。尔时世尊于日前 一个矩形件的排样下料问题,一批板料(长L,宽W),n种零件,每种零件宽度和数量分别为:li,wi,mi,求优化排样结果,恳请各位大侠帮忙!! 请教:关于treeview 读取SQL Server的numeric字段用什么函数? rzhou(海盗) 收分来 急救:“段落或字节不能超过64K”???在线等待 初级问题! rzhou(海盗) 收分来 大家好!!用java开发数据库!!请帮忙!! 排序问题! 1。对vcl库底层机制一些不明白的地方 可以写代码导入数据吗? 连接ORACLE数据库时候的错误提示 关于动态查询表为空时,怎样获取一个条件??最终调取一个提示框 菜鸟提问,向高手请教一个VB中SQL中的问题, 怎样显示局域网内的所有计算机 请问谁有用VMware设置好的solaris文件啊?或是那里可以下载啊??谢谢了~~ 帮帮小弟呀!!散分 在本地机遇到数据无法提交或读取的事,动网论坛的数据也无法读取,什么原因啊 寻程序员,短期,欢迎加盟!!!!!-------熟悉j2me的!!!!面试合格,待遇为150/天 关于Form的构造函数和OnLoad方法...... 氯水中的物质有哪些?它是混合物吧? 描写男人的外貌 我女生要调到鄂儿多斯市去工作:希望能了解那边天气情况;什么时候天气会暖和起来;天气最热气温多少度温...我女生要调到鄂儿多斯市去工作:希望能了解那边天气情况;什么时候天气会暖和 片段:大风之夜,当雨点在树叶上淅沥时,你在床上会听见我的微语;当电光从开着的窗口闪进你的屋里时,我的笑声也偕了它一同闪进了.仿照以上片段的意境和语言风格,以“大雪之夜”为开 尿液变橙黄色是怎么回事? 物理示波管原理中改变两方电压时图案会怎么变化,为什么会变化, 初二语文仿写水库、池塘、水田密布,像明镜再仿写2句 描述人外表的文言文 汉朝刘彻儿子有哪些, 仿写:一个“雨”字,让我仿佛看到了漫天的小雨淅淅沥沥地洒落,红了樱桃,绿了芭蕉.一个“山”字,让我仿佛看到了一个“淼”字,让我仿佛看到了 如何用古文来骂人,或者用古文来骂男的 塞纳河不结冰法语怎么说 哪里能买到花青素? 如是一个男生,对你说个文言文? 什么是生态系统 中国的34个行政区 省哪23个 自治区哪5个 直辖区哪4个 特别行政区哪2个! 济南哪里有卖花青素蓝莓花青素,以及蓝莓的产品! 蜗牛壳碎了怎么办 电源电压保持不变,R为定值电阻,在a、b两接线柱上接一个标有“6V,2W”的灯泡,闭合开关S,灯泡恰好正常不需要只是答案. 用古文古诗来形容下,待我事业有所突破之时,我会勇敢去爱你或是追求真爱最好 清朝皇太子住在哪里?东宫还是阿哥所? 语文段落仿写 初三水平就像雄鹰搏击长空前要被母亲推下悬崖,痛苦地训练飞翔,不惜以生命为代价;就像溪水汇入大海前要经过曲折蜿蜒,让石头锋利的棱角折磨,甚至被太阳烤干.但这些考验 磁铁的哪个极吸引铁块?n还是s? 清朝皇太子吃肉在上书房里四皇子吃肉说明要立他为皇太子,为什么. 氯水为何淡黄绿色 形容班主任的词语,人很高大的 介绍几部汉朝或者清朝的好看电视剧 实验室新制备的氯水具有刺激性气味,呈浅黄绿色,说明氯水中含有——分子.把少量碳酸钠投入氯水中能观察到有气泡产生,其原因是——.因此实验室的氯水要现配现用,若短期保存也要注意— 铁块会不会吸引磁铁磁铁吸引铁块,那铁块吸引磁铁么(怎么判断啊) 在30克水中通直流电,一段时间后,水的质量变为26.4克.问:参加反应的水的物质的量是多少mol?生成氧气的物质的量多少mol?(根据化学方程式列式计算) 苹果放在泡沫箱低温保鲜不透气会不会坏?或者能保鲜多久?装的是苹果,里面放冰袋, 用什么词,形容班主任的好!最好要深奥一点的词! 我想了解汉朝和清朝的历史.推荐一本书.不要文言文类的,想要白话文的.史事要全要真.不想要明朝那些事那种文学类的.再想问一下,《那时汉朝》可读么? 多元函数极值问题拉格朗日数乘法 是不是最多解决3元极值 4元的咋办? 为什么磁铁会吸引铁块? 什么是相对隔水层 为什么北半球河道右岸的侵蚀程度比左岸厉害?为什么北半球河道右岸的侵蚀程度比左岸厉害(可否提出一些事例)? 字字什么什么形容词语准确每个字都是经典我是这么理解的但是不知道这句话是怎么说的我记得是字字什么什么后面一大堆好象是古文不是四个字肯定比四个字多 天气那么暖和,那么晴朗是单句吗 左岸与右岸文字的特殊含义比如说男左女右所以左岸文字表示gay地话题?或者说是男性(同性)话题? 男长辈的你用文言文怎么代替 试举例说明如何用一种或几种生态系统的基础理论知道环境保护活动 英语翻译昨天的事你还生气吗.我知道是我的错,但这一切都是因为我爱你,我希望你常常陪我,我想每天都和你在一起,我对你的胡闹,只是想证明在你心里我是重要的.第一次见你就很喜欢你,当 用文言文表达对长辈教诲的感谢 塞纳河左岸潮流向西 有什么含义吗? 左岸文字和右岸文字是什么意思 氟化钠能否用来制取氟化氢 太阳光照射过水层,被水层吸收的比例是多少?这个比例是不是固定的?和水层的厚度有关系么?不过我是想知道一个笼统的比例,就是全部波长的太阳光,穿过一定厚度的水层之后,有多少被吸 什么是右岸文字和左岸文字? 氟化氢,氟化钠哪个化合更快 不透水层中为什么没有水的浮力 中国学术期刊网(CNKI)对其检索结果是如何进行排序的?如何改变检索结果的排序? ps明黄色值是多少? (3/7)保护环境保护生命在尊重自然的基础上切实有力地保护生态系统的自组织能力达到经济发展与环境保护...(3/7)保护环境保护生命在尊重自然的基础上切实有力地保护生态系统的自组织能力 新车刚开10天,轮胎有沙沙的声响,为什么?上月刚买的悦动手豪,在路面稍微有些不平时,会听到轮胎有沙沙的声响,是锦湖轮胎,谁有这样感受?怎么解决? 送元二使安西 唐·王维 渭城朝雨浥轻尘,客舍青青柳色新.劝君更尽一杯酒,西出阳关无故人.1.诗中的“渭城”是送别之地,“君”代指________,折枝杨柳是_________的象征.2.后两句是精心选择的临 有关井点降水的问题,想了解一下一般不透水层在地下多少米 收音机被金属盆盖住后,为什么还能听见沙沙声收音机发出的沙沙声是怎样产生的?是杂乱的电磁波还是什么?若是前者,按说电磁波被屏蔽后,就不该再发出沙沙声了(很清晰,很大) 钠放到水中是抑制电离还是促进电离? 不透水层是怎么回事,为什么水到地下一定深度后就不会下降了? 首都航空长沙飞杭州航班受爆炸物威胁备遵义市委书记廖少华涉嫌严重违纪被免职贵州遵义干部群众坚决拥护对廖少华进行中日韩共用常见汉字国际学术研讨会召开快讯:首都航空JD5662长沙飞杭州港嫩模当街拆胸罩底裤 尺度之大吓坏路美主播为“杀光中国人”言论向示威者鞠中国企业助力几内亚“造城”梦大师作品巴黎展现“美丽中国”土耳其:中国当代建筑展展现“蓬勃中国中组部:领导干部退休后三年内兼职须经从严规范领导干部在企业兼职任职朝鲜民众喜迎土豆大丰收 数量多到让人美被爆在驻华使领馆搞监听美媒:十年后大学啥样? 网络授课 学巴基斯坦愿率先加入中国空间站昔日嫩模兽兽近照 皮肤松弛显老态越来听中国学者回击菲“九段线”质疑贵阳小学现黑板报外包 评论称扼杀学生受吉林地震影响 哈尔滨铁路局紧急扣停青岛涉黑头目张韶军一审死刑 其余16西班牙人否认与巴尔德斯接触巴洛特利:我觉得我两周后就能回来学会这些帮助孩子远离性早熟蓝军官员:球队高层依然支持穆帅巴萨技术总监:不担心冬季转会意媒:尤文图斯想租借河床小将美七大机场工人罢工 要求最低时薪增至惊艳的宋代物质文明,绝对让你震惊谷歌地图未标注\"首尔\" 首尔市政承认与张翰恋情,放手选择胡彦斌,郑爽《饥饿游戏3》中文版VR视频 感受“日菲举行首脑会谈 就防卫装备协定达成非洲发现世界第二大巨钻 重达1111非洲发现世界第二大巨钻 重达1111红包大战提前开撕? 易信4.0首推任秒杀美国的Lily无人机?中国智造这心若累了,就用花花草草来疗愈股权众筹运营模式及风险韭菜鸡蛋花屋久岛——鹿儿岛奥达曼英雄难度攻略 H1H2H3详细
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘