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

转载 2004年08月07日 14:03:00
CSDN_Logo.gif
ddd.GIF
01_bg_02.gif
  首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才 menu_1.gif 01_bg_03.gif
移 动专 题SUNIBM微 软微 创精 华Donews人 邮
我的技术中心 
我的分类 我的文档
最新文章 发表文章
专栏管理 使用说明

RSSIcon.gif RSS 订阅 
Windows/.NET
.NET  (rss)    
Visual C++  (rss)    
Delphi  (rss)    
Visual Basic  (rss)    
ASP  (rss)    
JavaScript  (rss)    
Java/Linux
Java  (rss)    
Perl  (rss)    
综合
其他开发语言  (rss)    
文件格式  (rss)    
企业开发
游戏开发  (rss)    
网站制作技术  (rss)    
数据库
数据库开发  (rss)    
软件工程
其他  (rss)    

积极原创作者 
windoze (12)
ngnr (3)
unique001 (2)
duckur (2)
CanvasHat (5)
chensheng913 (132)
yolle (1)
sbf2000 (1)
ycg01 (1)
ezdevelop (29)
CSDN - 文档中心 - Delphi 阅读:163   评论: 0    参与评论
标题   组件制作之三(图形控件)     linzhengqun [原作]
关键字   组件制作之三(图形控件)
出处  

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的源码,你会学到更多的东西。

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


相关文章
对该文的评论


网站简介 - 广告服务 - 网站地图 - 帮助信息 - 联系方式 - English biaoshi.gif
北京百联美达美数码科技有限公司 版权所有 京ICP证020026号
Copyright © CSDN.NET, Inc. All Rights Reserved
pageview1.asp?columnid=4&itemid=11

awt--常用组件的使用

/*Java.awt.List是一个滚动列表组件,它与Choice最大的不同是:该组件可以同时选择多个选项 1.构造方法 List():创建的滚动列表有默认的可见行 List...
  • zouyang2014
  • zouyang2014
  • 2017年02月24日 20:04
  • 413

巧用TWaver 3D 矢量图形功能

的确,提起TWaver,大家想到的首先是“电信拓扑图组件”。其实,由于其灵活的MVC架构、矢量化设计、方便定制等特点,TWaver可以做的还有很多。例如房地产行业常见到的“户型图”。...
  • twaver
  • twaver
  • 2014年10月29日 11:14
  • 1346

NGUI基本控件制作

NGUI 基本控件的制作。 NGUI基本控件的制作。在NGUI的Prefab ToolBar中有预先制作好的按钮、复选框、列表框、滚动条、进度条和滑块控制条。下面是我接触NGUI并制作这些控...
  • sinat_26368235
  • sinat_26368235
  • 2015年09月22日 10:10
  • 587

JAVA图形界面(GUI)之常用组件

前面提到容器是用来组织组件的,那么这一篇博客就为大家介绍一些Java的常用组件。最后通过一个例子展示这些组件的实际效果。按钮(JButton)JButton是我们常用的一个组件,其表现形式为一个按钮。...
  • jianggujin
  • jianggujin
  • 2015年12月31日 16:58
  • 14207

unity3d图形用户界面组件

 在这篇文章中我将给读者介绍Unity中的图形用户界面(GUI)编程.Unity有一个非常强大的GUI脚本API.它允许你使用脚本快速创建简单的菜单和GUI. 简介 Unity提供了使用脚本...
  • yangjian6292176
  • yangjian6292176
  • 2015年12月10日 11:43
  • 1214

Java 拖动Swing组件和图片

SwingUtilities类是Swing组件内部使用的实用工具,它提供了许多的涉及计算、转换、访问控制、布局等方面的方法。这里我们只讨论它的一个方法public static Point conve...
  • ytlcainiao
  • ytlcainiao
  • 2015年04月17日 16:52
  • 717

Java图形化组件

一、component组件 是其他组件类的父类,Javax.swing包中Jcomponent(轻组件)类是Java.awt包中Container类的一个直接子类、Component类的一个间接子类。...
  • dongxingpeng
  • dongxingpeng
  • 2015年09月10日 15:31
  • 473

Unity自定义UI组件(一)函数图篇(上)

Untiy自定义UI组件 自定义折线图,曲线图,条形图,饼图,函数公式图等 可自定义多种别的工具比如颜色拾取器,日期拾取器,简单Excel的绘制...
  • qq_29579137
  • qq_29579137
  • 2017年04月25日 14:32
  • 2095

基于WMP控件编程(属性)

http://blog.csdn.net/kingmax54212008/article/details/7178495 windows media player 控件在我们编程时经常要用到...
  • u014605728
  • u014605728
  • 2016年03月24日 17:14
  • 1674

Android的图形图表控件Android-Charts正式发布

今天正是将之前所做的Android图表控件打包分享给广大Android开发者,目前画面截图和演示效果图都已经添加代码和其他的内容可以直接到googleCode和本地下载。CG本次仍然使用APL2.0作...
  • yctccg
  • yctccg
  • 2016年08月16日 10:41
  • 3575
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:组件制作之三(图形控件)
举报原因:
原因补充:

(最多只允许输入30个字)