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

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

Swift的初始化方法 TIOBE 2015年1月编程语言排行榜:JavaScript成大赢家 为什么iOS开发不需要Storyboard? 仅有纽扣大小的开发板 Intel Curie “撒娇”的豌豆荚?被百度手机助手屏蔽太糟心! 【工具推荐】Pgcli—自动完成和语法高亮的Postgres命令行工具 CES 2015:挑一款机器人带回家? 夜行、睡眠与健康:CES 2015十款酷炫的可穿戴产品 Java 9中新的货币API 唯“简”不破,Apple Watch App的设计之道 Google Glass从X labs“毕业”,更换项目负责人 不进化,则消亡——互联网时代企业管理的十项实践 RedMonk 2015年1月编程语言排行榜:进击的Swift! 微信开放JS SDK,这场web巨变意味着什么? 盘点一些iOS开发技巧:Swift和Objective-C 2014年,那些“颜值”爆表的UI动画 《近匠》爱加密:谁说iOS应用不需要保护? SwiftColorArt:开源易用的Swift图片类库 人气爆棚 干货满满 中国电信天翼开放平台开放日圆满落幕 必须Mark!43个优秀的Swift开源项目推荐 治拖延、疗懒癌!安利12款提高工作效率工具 把ES6带进Node社区 Io.js 1.0.0正式发布 Java 2014:10个最热门、最具争议性的话题 回顾:2014年最流行前端开发框架对比评测 实例讲解SQL注入攻击 调试大规模服务器集群的五大策略 .NET编译平台Rosly将迁移到Github Wasai虚拟现实头盔与体验馆发布:虚拟现实的线下经济 订票系统不再瘫痪 阿里云确认与12306合作 Apple前工程师Warren Moore:Swift中Metal使用初体验 手把手教学:详解Swift中的iOS设计模式 我想咨询一下在VB中不同的后缀代表的是什么功能? 小妹请教各位大虾,apache做应用服务器,unix下,怎样连接oracle数据库? 老天啊,这是为什么??????别了,我的世界杯,别了,巴蒂斯图塔,别了,阿根廷....... 更新数据库问题,100分回报? EXCEL里的时间问题!!谢~ 在word2000里怎样输入数学公式啊 重载[][],请各位帮忙。 我准备参加程序员考试 法国,阿根廷,我的心在滴血。:( :( 为阿根廷哭的人太多了(我的同事,同学等等)。。。是不是央视的沈冰也当场哭了? 寻dialogic代理商合作,急 分页程序中如何加书签,用rs.bookmark最好!!! 听说VB.net的编译器使用C#做的,是吗? 计算机英语在程序员考试中占多大比例? 令人失望的世界杯,放分!!!!!!!!! 怎样获得Mp3的歌曲信息 如何在ACCESS数据库中引用自身数据库? 阿根廷,别为我哭泣! 线程的同步问题(在线等待100) 请问如何在bcb中引用delphi的*.pas文件?(如果可以的话) 如何将CRichEditCtrl的内容输出到打印机? 关于jcreator编译时的问题 在xslt中如何判断一个结点在xml中出现的次数? 请邦邦忙--数据库不能启动了 请问..... 两个存储过程问题,帮我答了,重分酬谢 如何捕获键盘事件 讨论EAS,留步,您请进! 开发自己的组件库! 如何调用.chm帮助文件?? jbuilder6的经典书籍哪里有? 在seek(0,2)中,0,2表示什么意思,整个函数又是什么意思。 WebForm2中如果要引用WebForm1中的变量X(属性),怎么办?X在form1中怎样定义?在form2中怎样引用? 关于汇编语言? 用TC如何在开发OpenGL? 机工出的影印版让人失望!!! 我想问一个关于注册表的问题 如何在ASP中显式的声明一个变量,和dim xxx as xxx一样吗? 对图片处理,请问哪里有抓热点的工具Hospot4.exe下载 用jb5+wls7可以吗 急需关于网际协议分析的论文 哪里有关于学习汇编语言的网站? 请教: 我在程序中对excel的单元格作了修改,每次改后都弹出”修改了excel,是否保存“对话框,怎么去掉呀? 请问如何用VC得到局域网中所有SQLSERVER服务器的名称?请高手指教 一个小问题! 关于写帮助文件的问题 要做一个图书馆管理系统,请提些意见,加100分 请问如何判断一个对象类型? 要去面试,调查一下 上海做 J2EE 的开发的月薪是多少? 找带按钮(button)的text类型控件 kdj值是指K的,D的还是J的值好多说kdj值大于80的,说的是k的,还是d的还是j的值呢?还是他们三个全部大于80呢?简单说明就可以,是他们三个的数值都大于80吗?还是kdj还有个平均线呢?KD的取值范围都 世界上最硬的东西到底是不是金刚石 1米×2米 1毫米后紫铜板有多重? kdj指标K · D ·J 分别表示什么在期货中 KDJ中的K ` D ` J 分别表示什么 sketchup中移动面很难捕捉到绿轴怎么办?求高手指教. 摩擦起电可不可以证明原子是有更小的微粒组成 有一焦距为10cm的凸透镜,物体从离凸透镜30cm处沿主光轴移到的过程中,则 sketchup怎么只能移动蓝轴不能红轴移动? 单位电荷在电场力作用下沿闭合回路中移动一周释放的电能决定于什么? 一个焦距是10CM的凸透镜,当物体从离透镜20CM处渐移向30CM处的过程中A:像渐大,像距变小 B:像渐小,像距变大C:像渐大,像距变大 D:像渐小,像距变小 SketchUp移动问题~~急~~为什么我创建了群组,移动的时候总是在水平面上移动啊,我想在z轴方向移动~~怎么解决呀~~ 电场线与场强方向一样吗为什么负电荷可沿电场方向运动?它电势和点势能怎样变化?其实我还搞不清电势 场强 电场线 电势能的关系? 有一焦距为10CM的凸透镜,将物体从离凸透镜30CM处沿主光轴移动到距透镜5CM处在这个过程中,下面说法中正确的是A 在光屏上的像始终是倒立的,并且越来越大B 在光屏上的像始终是正立的C 开始 sketchup移动时如何准确移动到一个面上面 铜排的重量怎么计算长300mm宽60mm厚8mm的铜排重量是多少?另:铜的比重是多少? 用 字母 表示梯形的 面积公式是 什么?平行四边形为 0时 的 面积公式是什么?梯形的上底,梯形变成什么 形用 字母 表示梯形的 面积公式是 什么?平行四边形 的 面积公式是什么?梯形的上底为0 sketchup中移动工具为什么不能延绿轴移动 两颗共同绕太阳运行的行星a和b,已知它们的质量之比ma:mb=2:1,它们的球体半径之比ra:rb=2:1,则它们各...两颗共同绕太阳运行的行星a和b,已知它们的质量之比ma:mb=2:1,它们的球体半径之比ra:rb=2:1,则 一个梯形的上底延长,就变成一个平行四边形,面积增加,知道下底怎样求梯形的面积 同种原子构成的物质摩擦会发生摩擦起电现象吗?说明理由明天交作业了 Thank you A、B两物体做匀速圆周运动.质量Ma:Mb=1:2 半径Ra:Rb=1:2.当A转60圈B恰好转45圈.求向心力之比 两个平面平行,A在一个平面内,B在另一个内,C是BA的中点,AB在移动的同时,点C为什么共面,急. 由原子勾成的初步知识解释摩擦起电的原因简略点 高中化学奥赛 一个焦距是10cm的凸透镜,蜡烛在他左侧30cm处,可得一个什么像 若直线m不平行于平面a,且m不属于a,则“a内的所有直线与m异面"对不对?为什么, 铜板怎么算重量 一个凸透镜的焦距为10cm,将点燃的蜡烛放在凸透镜前30cm处在透镜的另一侧光屏上得到一个像是A倒立缩小的实像B倒立放大的实像C倒立等大的实像D正立放大的虚像 力偶移动到起其作用面平行的任意平面上()A.会引起附加力 B不改变其对刚体作用效果 C.会引起附加力矩 D.会使刚体随力偶的移动而移动 请问供应:铜板重量怎么计算 凸透镜焦距为10cm,将物体由距凸透镜40cm处匀速移动到20cm处,所用时间为2s,求此过程中物体的像移动的平均速度. 空间几何中的两线平行或垂直是指移到同一平面后,能形成这种关系的情况吗 长方体的铜板重量怎么算?宽一米,长两米,厚4公分.怎么算出来它的重量? 一个梯形,上底长 6cm,若将它的上底延长 4cm,就变成一个平行四边形,面积比原来增加 10 cm2,原来梯形的面积是( )cm2. 向量可以自由移动吗?~向量与平面共面包括向量与平面平行吗?~~ 黄铜板的重量怎么计算 草图大师中如何选择沿蓝轴移动 距地面20——35千米出的大气层里有一个“臭氧层”,它集中了地球上臭氧的( 填)有A 50% B 70% C 80% D 90% 四个选项选一个 紫铜板重量怎么算出来啊.单位是12公分宽8个厚 15米长的.和20公分宽8个厚12米长 厚0.8CM谢谢那个懂的人帮我算 我有急用一定给你高分奖赏的 物理题:一行星的半径是地球半径的2倍,密度与地球相同,在此行星上竖直上抛一物体,上升的最大高度是h,则在地球上以同样大的初速度竖直上抛同一物体,上升的最大高度应为多少?(不计空 某凸透镜焦距为10cm,物体放在离焦距5cm处,所成的像( )A、是实像 B、是虚像 C、一定是缩小的像 D、一定是放大的像 一道物理题:小华同学在教室里用教室里用一个焦距为10cm的凸透镜在一张白纸上得到了窗外一棵数清晰的像这个像是____、_____的____像 草图大师怎么限制在一个平面移动 某凸透镜焦距是10cm,将物体放在立脚点5cm的地方,所成的像( )A 一定是实像 B 一定是虚像 C 一定是放大的像 D 一定是缩小的像 电势能是电场和电荷共有的能,他为什么是共有的,就是类似重力势能的共有,我也不是很清楚。不是很能理解共有这个概念, 草图大师里移动工具为什么不能上下移我用的是草图大师8.都用这么久了,但每次画图都还是会出错,纠结! 导数与微分的计算 正场源电荷的电场中,负试探电荷逆电场线运动电势能会越来越大吗? 草图大师复制的时候怎么让在一个平面上好难复制,有时候跑到下面去了 为什么标准蛋白质必须用凯氏定氮法测定纯度 电荷在电场中的位置一定,他的电势能也一定? 草图大师如何平移到平面上我快烦死了,如何把树平移到草坪上,主要我树老是挨不到草坪,有没有什么直接输命令的.向Y轴移动多少距离,向Z轴移动多少距离的这种命令. 有什么东西比金刚石还硬吗?人造的. 已知298K时,N2(g)+3H2(g)=2NH3(g)的△G(θ)=-33kJ·mol-1,则NH3(g)=1/2N2(g)+3/2H2(g)的平衡常数Kp为( ) A.6.4×10^(-4) B.3.2×10^(-4) C.2.3×10^(-3) D.1.28×10^(-3) KDJ指标中的K值和D值是怎样计算出来的请问股市中KDJ指标中的K值、D值、J值是怎样计算出来的.再问KDJ指标中所涉及的RSV是什么意思.谢谢高师指点 金刚石是不是最硬的东西? 我是一名高三的学生,从来没有学过化学奥赛,但是这次化学奥赛预赛得了115分,所以能够去参加复赛,但是我不知道该不该去.因为毕竟没有看过高中意外的化学相关书籍,但是我想知道这样的水 臭氧层没了后地球会变成什么样子?那时还有人类吗? 比金刚石还硬的东西还有吗? 黄铜板,铍铜板,紫铜板,磷铜板性能及化学成分
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘