`
javasogo
  • 浏览: 1816973 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

组件制作之三(图形控件)

阅读更多

VCL中的Shape是个很不错的控件,可以选择几种图形,以满足我们的需求,但有时候就是觉得它的可选图形少了一点,比如我们想要一个三角形,它却没有。于是就想到来扩展一下这个控件,名为ShapeEx。其实扩展的功能不多,只是增加了一些图形。而类也并不是继承自TShape,而是继承自TGraphicControl,这样可以让我们彻底看看图形控件的做法。Tshape也是继承自TGraphicControl。而我们的扩展控件功能是基于Shape的扩展,所以当然里面的代码几乎取之TShape,只是加了一些扩展图形的代码,但又有什么关系呢,VCL源码是最好的学习资源,我们何不取之用之。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

很多东西我们已经在上面说过了,这里不多说了,我要直入图形控件的重点。图形控件不是封装Windows的控件,而是Delphi自己画出来的,那么它肯定有一个画控件的函数。这个函数就是:

Paint;

看一下VCL源码,可以知道它定义在TGraphicControl。中:

procedure Paint; virtual;

这是一个虚函数,那么它的实现是怎么样的呢,点击看它的实现如下:

procedure TGraphicControl.Paint;

begin

end;

里面什么码也没有,这个很容易理解,因为它不可能知道他的子类的图形是什么样子的。所以设为虚函数,由它的子类来覆盖它。

那么是谁调用了这个函数来引起画控件呢。Windows有一个WM_PAINT;消息,当一切引起重画的条件发生,则会发送这条消息,再看看TGraphicControl,果然有截获这个消息:

procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

在处理函数里面,调用了Paint方法,从而实现了画图形控件可能:

procedure TGraphicControl.WMPaint(var Message: TWMPaint);

begin

if Message.DC <> 0 then

begin

Canvas.Lock;

try

Canvas.Handle := Message.DC;

try

Paint; //调用了这个函数来画图形控件

finally

Canvas.Handle := 0;

end;

finally

Canvas.Unlock;

end;

end;

end;

而它的子类覆盖了Paint函数,所以消息处理函数调用的实际上是某个子类的Paint方法,这个就是多态的应用了,这里不多说。

既然Paint函数可以画图形控件,那么它是以什么来画的呢,VCL有一个Canvas类,它就是用这个来画的,在TGraphicControl果然也定义了这个成员:

FCanvas: TCanvas;

property Canvas: TCanvas read FCanvas;

可以看出这是一个只读的成员,因为它不想外界来影响他。

好了,一切已经具备了,现在就可以画上去了。源代码有详细解释,这里不多说。

ShapeEx中有两个对象属性,为PenBrush。对应于他的两个对象成员。设置了这两个属性之后,在对象察看器中就可以展开他们来设置他们的属性了。这个也是对象属性的一般用法。

似乎没有什么可说的了,下面看源代码吧,其中也有很详细的说明:

unit shapeExUnit;

interface

uses

SysUtils,Classes,Graphics,Controls,ExtCtrls;

type

//定义了几种形状:矩形,正方形,圆角矩形,圆角正方形,椭圆形,圆形,

//增加的图形:横线,坚线,上三角形,菱形

TShapeType = (stRectangle, stSquare, stRoundRect, stRoundSquare,

stEllipse, stCircle,stHLine,stVLine,stTriangle,stDiamond);

TShapeEx = class(TGraphicControl)

private

FPen: TPen;

FBrush: TBrush;

FShape: TShapeType;

procedure SetBrush(Value: TBrush);

procedure SetPen(Value: TPen);

procedure SetShape(Value: TShapeType);

protected

//最重要的函数,在父类TGraphicControl中定义的一个

//虚函数,当得到WM_PAINT消息时,调用该函数引起重画

//父类是一个空函数,以便TGraphicControl的子类复盖它。

procedure Paint; override;

public

constructor Create(AOwner: TComponent); override;

destructor Destroy; override;

published

//这个函数当图形中的画笔和画刷改变时引起重画,在设计器中最为明显

procedure StyleChanged(Sender: TObject);

property Align;

property Anchors;

property Brush: TBrush read FBrush write SetBrush;

property DragCursor;

property DragKind;

property DragMode;

property Enabled;

property Constraints;

property ParentShowHint;

property Pen: TPen read FPen write SetPen;

property Shape: TShapeType read FShape write SetShape default stRectangle;

property ShowHint;

property Visible;

property OnContextPopup;

property OnDragDrop;

property OnDragOver;

property OnEndDock;

property OnEndDrag;

property OnMouseDown;

property OnMouseMove;

property OnMouseUp;

property OnStartDock;

property OnStartDrag;

end;

implementation

//构造函数,ControlStyle确定控件的特征,这里是加上csReplicatable

//使该控件可以用PaintTo方法把它画到一个任意的画布中

//另外还指定PenBrush对象的OnChange事件的方法指针给StyleChanged;

constructor TShapeEx.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

ControlStyle := ControlStyle + [csReplicatable];

Width := 65;

Height := 65;

FPen := TPen.Create;

FPen.OnChange := StyleChanged;

FBrush := TBrush.Create;

FBrush.OnChange := StyleChanged;

end;

destructor TShapeEx.Destroy;

begin

FPen.Free;

FBrush.Free;

inherited Destroy;

end;

//最重要函数,控件就是以这个函数画出来的。

procedure TShapeEx.Paint;

var

//X:左上角X Y:左上角Y W:宽, Y:高 S:宽高中大的值

X, Y, W, H, S: Integer;

begin

//Canvas是父类TGraphicControl的属性,用于画控件

//在画图之前,要进行一些坐标点的确定,

with Canvas do

begin

//如果以控件的四个角来画图形,当Pen太大时,图形的边线

//将比Pen的宽要小一些,所以要进行点的重定位。

Pen := FPen;

Brush := FBrush;

X := Pen.Width div 2;

Y := X;

W := Width - Pen.Width + 1;

H := Height - Pen.Width + 1;

//Pen.width的值为0和为1时是一样的等于一个象素

//如果上面Pen.width等于1,则图形的宽高刚好等于控件的宽高

//如果为0,则图形宽高要大于控件宽高一个象素了,所以有了下面的语句

if Pen.Width = 0 then

begin

Dec(W);

Dec(H);

end;

if W < H then S := W else S := H;

//当图形为正方类型的图形时,需要对图形的位置进行一些调整

if FShape in [stSquare, stRoundSquare, stCircle] then

begin

Inc(X, (W - S) div 2);

Inc(Y, (H - S) div 2);

W := S;

H := S;

end;

case FShape of

stRectangle, stSquare:

Rectangle(X, Y, X + W, Y + H);

stRoundRect, stRoundSquare:

RoundRect(X, Y, X + W, Y + H, S div 4, S div 4);

stCircle, stEllipse:

Ellipse(X, Y, X + W, Y + H);

//以下是增加的部分。

stHLine:

begin

MoveTo(X, Height div 2);

LineTo(X+W,Height div 2);

end;

stVLine:

begin

MoveTo(Width div 2,Y);

LineTo(Width div 2,Y+H);

end;

stTriangle:

Polygon([Point(X,Y+H-1),Point(X+W-1,Y+H-1),Point(Width div 2,Y)]);

stDiamond:

Polygon([Point(Width div 2,Y),Point(X,Height div 2),

Point(Width div 2,Y+H-1),Point(X+W-1, Height div 2)]);

end;

end;

end;

//Invalidate这个函数将使系统发送WM_PAINTTGraphicControl

//TGraphicControl的处理函数将调用Paint,而它的子类覆盖了它

//所以实际就调用了ShapeExPaint函数,从而达到了重画的效果

procedure TShapeEx.StyleChanged(Sender: TObject);

begin

Invalidate;

end;

procedure TShapeEx.SetBrush(Value: TBrush);

begin

FBrush.Assign(Value);

end;

procedure TShapeEx.SetPen(Value: TPen);

begin

FPen.Assign(Value);

end;

//设置图形,同时引起重画,以达到图形变化,

//最明显的效果是在设计器时改变Shape属性时看到的变化

procedure TShapeEx.SetShape(Value: TShapeType);

begin

if FShape <> Value then

begin

FShape := Value;

Invalidate;

end;

end;

end.

安装等方法在上一章已经说过了,这里不多说。这一次知道了图形控件的大概做法,其实无非就是覆盖Paint来画自己的图形控件,而其他,则和我们上一章的说过的一样。其实也很简单。

以上两个控件算是比较简单,但已经讲清了很多组件制作的概念和技巧,看不看得懂就由你了,我也没有办法。有一个有用的技巧就是多看看VCL的源码,你会学到更多的东西。

接下来,应该要做一个难一点了吧。想知道是什么,且听下回分解。

分享到:
评论

相关推荐

    visual graph 专业图形控件

    Visual Graph(Http://www.visual-graph.com)是一套强大的交互图形开发平台,她能非常方便地建造基于图形的界面、轻松容易自已定制公司专属与国家标准的各种图形元件,实现图形管理,图形建模,制作监控系统,表单系统,...

    三维表面图形VB编程控件 MATVIEW 4.5

    标题 "三维表面图形VB编程控件 MATVIEW 4.5" 涉及到的是一个用于Visual Basic(VB)编程的三维图形控件,MATVIEW 4.5。这个控件使得开发者能够在VB应用程序中创建和展示三维表面图,极大地扩展了VB在科学计算和数据...

    Qt之自绘制日历控件(三)

    总的来说,“Qt之自绘制日历控件(三)”是一个功能丰富的日历组件,它展示了如何在Qt中利用图形系统实现复杂用户界面的自定义控件。通过这样的实践,开发者不仅可以掌握自绘技巧,还能更好地理解Qt的事件处理和图形...

    C#自定义控件的制作.doc

    在C#编程中,自定义控件的制作是一项基础但重要的技能,它允许开发者根据特定需求创建具有独特功能和外观的UI元素。本教程旨在引导初学者了解如何在C#环境中构建自己的控件,虽然例子可能较为简单,但其目的是激发...

    三维表面图形VB编程控件

    【三维表面图形VB编程控件】是一个关于使用Visual Basic(VB)进行三维图形编程的资源集合,主要涉及VB与图形库的集成,用于创建复杂的3D表面模型。在这个压缩包中,包含了一些关键的动态链接库(DLL)文件和VB项目...

    使用C++制作ocx控件

    三、在 VS2010 中使用 OCX 控件步骤 1. 注册控件使用命令 regsvr32 控件所在目录/*.ocx若注册不成功,可能是系统缺少一些动态库,检测缺少的动态库方法: 2. 注册成功后,打开工程项目,直接将 OCX 控件拖入控件...

    c++builder自制控件

    制作这样的控件通常涉及到以下几个关键知识点: 1. **自定义组件**:C++Builder允许开发者创建自己的组件,这可以通过继承现有的VCL组件或从TComponent基类开始。自定义组件可以扩展标准组件的功能,或者提供全新的...

    开关及输入面板制作 delphi控件

    "开关及输入面板制作 Delphi 控件"的主题聚焦于如何在Delphi集成开发环境中创建自定义的图形用户界面(GUI)组件,特别是开关(Switch)和输入面板(Input Panel)。下面将详细阐述这个主题所涵盖的知识点。 首先,...

    WPF、C# 电池控件的制作

    在制作电池控件时,我们首先会定义一个`UserControl`,这是WPF中自定义控件的基础。在XAML文件中,我们可以使用各种WPF元素来构建电池的外观,例如`Rectangle`表示电池主体,`Path`来绘制电池的边角和充电指示线,...

    android制作仿iphone开关控件

    这篇博客 "android制作仿iphone开关控件" 提供了实现这一功能的详细步骤和源码,下面将对其中的关键知识点进行深入阐述。 首先,我们要了解Android中的开关控件基本结构。在Android原生系统中,开关控件通常是`...

    flash制作的上传文件控件

    标题中的“Flash制作的上传文件控件”是指利用Adobe Flash技术创建的一种交互式组件,用于在网页上实现文件上传功能。这种控件通常由ActionScript编写,ActionScript是Flash平台上的编程语言,允许开发者创建动态...

    Delphi 为组件制作立体效果,实现组件的阴影、投影效果

    在 Delphi 开发环境中,为组件制作立体效果和实现阴影、投影效果是提升用户界面(UI)视觉吸引力的重要手段。Delphi 提供了强大的图形处理能力,使得开发者可以通过原生的 Delphi 方法来实现这些效果,而无需依赖第...

    C#常用函数和动态组件制作

    在这个“C#常用函数和动态组件制作”的主题中,我们将深入探讨C#的一些核心特性、常用函数以及如何制作动态组件。 一、C#常用函数 C#拥有丰富的内置函数,这些函数可以帮助开发者快速实现各种功能。以下是一些常见...

    C#制作的渐变Button控件

    总结起来,"C#制作的渐变Button控件"是一个利用C#和GDI+技术创建的用户自定义控件,它允许开发者在Button上实现美观的渐变色彩效果。这种自定义控件不仅提升了应用的视觉体验,也为程序员提供了更多的界面设计可能性...

    各种图形报表组件

    本篇文章将详细探讨标题中提到的"各种图形报表组件",包括微软图表控件MSChart、水晶报表以及Jquery图表制作功能。 首先,我们来看微软图表控件MSChart。MSChart是Microsoft .NET Framework的一个组成部分,主要...

    C#二维三维图形绘制 工程实例宝典

    DirectX是微软推出的游戏和多媒体开发接口,其Direct3D组件专注于三维图形处理。OpenGL则是一个跨语言、跨平台的编程接口,用于渲染高质量的2D和3D图形。Chapter6和Chapter9可能深入讨论了这两个库的使用,包括坐标...

    QT制作超炫控件集合

    QT制作超炫控件集合是针对QT框架进行GUI(图形用户界面)开发的一种技术实践,主要涉及QT库中的各种自定义控件设计和C++编程。QT是一个强大的跨平台应用程序开发框架,尤其在GUI设计方面表现出色,它允许开发者创建...

    使用vs2010中的自带chart控件,制作图形报表

    在Visual Studio 2010中,开发人员可以利用内置的Chart控件轻松创建各种图形报表,这大大简化了数据可视化的步骤。本教程将深入探讨如何使用MSChart控件来绘制点图,并通过实例来展示其具体操作过程。 1. **MSChart...

    C#阀门及文本框控件制作demo-源代码.rar

    通过分析"11【喜科堂】空压机项目实战:2-8 阀门及文本框控件制作"这个压缩包中的源代码,我们可以学习到以下关键知识点: 1. **自定义控件**: 在C#中,可以通过继承现有的控件类(如System.Windows.Forms....

    C# /winform编写的简易图形编辑器

    三、矢量图支持 矢量图是一种基于数学描述的图像格式,其特点是放大不失真。在WinForm中,可以使用Path类来存储矢量图数据。当用户绘制或编辑图形时,Path对象会记录下每条线段和曲线的参数,这样在保存和加载时,...

Global site tag (gtag.js) - Google Analytics