国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

組件制作之三(圖形控件)

2019-11-18 18:17:36
字體:
供稿:網(wǎng)友
VCL中的Shape是個(gè)很不錯(cuò)的控件,可以選擇幾種圖形,以滿足我們的需求,但有時(shí)候就是覺得它的可選圖形少了一點(diǎn),比如我們想要一個(gè)三角形,它卻沒有。于是就想到來擴(kuò)展一下這個(gè)控件,名為ShapeEx。其實(shí)擴(kuò)展的功能不多,只是增加了一些圖形。而類也并不是繼承自TShape,而是繼承自TGraphicControl,這樣可以讓我們徹底看看圖形控件的做法。Tshape也是繼承自TGraphicControl。而我們的擴(kuò)展控件功能是基于Shape的擴(kuò)展,所以當(dāng)然里面的代碼幾乎取之TShape,只是加了一些擴(kuò)展圖形的代碼,但又有什么關(guān)系呢,VCL源碼是最好的學(xué)習(xí)資源,我們何不取之用之。

 

很多東西我們已經(jīng)在上面說過了,這里不多說了,我要直入圖形控件的重點(diǎn)。圖形控件不是封裝Windows的控件,而是Delphi自己畫出來的,那么它肯定有一個(gè)畫控件的函數(shù)。這個(gè)函數(shù)就是:

Paint;

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

 PRocedure Paint; virtual; 

這是一個(gè)虛函數(shù),那么它的實(shí)現(xiàn)是怎么樣的呢,點(diǎn)擊看它的實(shí)現(xiàn)如下:

procedure TGraphicControl.Paint;

begin

end;

里面什么碼也沒有,這個(gè)很容易理解,因?yàn)樗豢赡苤浪淖宇惖膱D形是什么樣子的。所以設(shè)為虛函數(shù),由它的子類來覆蓋它。

 

那么是誰調(diào)用了這個(gè)函數(shù)來引起畫控件呢。Windows有一個(gè)WM_PAINT;消息,當(dāng)一切引起重畫的條件發(fā)生,則會(huì)發(fā)送這條消息,再看看TGraphicControl,果然有截獲這個(gè)消息:

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

在處理函數(shù)里面,調(diào)用了Paint方法,從而實(shí)現(xiàn)了畫圖形控件可能:

procedure TGraphicControl.WMPaint(var Message: TWMPaint);

begin

  if Message.DC <> 0 then

  begin

    Canvas.Lock;

    try

      Canvas.Handle := Message.DC;

      try

        Paint;   //調(diào)用了這個(gè)函數(shù)來畫圖形控件

      finally

        Canvas.Handle := 0;

      end;

    finally

      Canvas.Unlock;

    end;

  end;

end;

而它的子類覆蓋了Paint函數(shù),所以消息處理函數(shù)調(diào)用的實(shí)際上是某個(gè)子類的Paint方法,這個(gè)就是多態(tài)的應(yīng)用了,這里不多說。

 

既然Paint函數(shù)可以畫圖形控件,那么它是以什么來畫的呢,VCL有一個(gè)Canvas類,它就是用這個(gè)來畫的,在TGraphicControl果然也定義了這個(gè)成員:

FCanvas: TCanvas;

property Canvas: TCanvas read FCanvas;

可以看出這是一個(gè)只讀的成員,因?yàn)樗幌胪饨鐏碛绊懰?BR>
 

好了,一切已經(jīng)具備了,現(xiàn)在就可以畫上去了。源代碼有詳細(xì)解釋,這里不多說。

 

在ShapeEx中有兩個(gè)對象屬性,為Pen和Brush。對應(yīng)于他的兩個(gè)對象成員。設(shè)置了這兩個(gè)屬性之后,在對象察看器中就可以展開他們來設(shè)置他們的屬性了。這個(gè)也是對象屬性的一般用法。

 

似乎沒有什么可說的了,下面看源代碼吧,其中也有很詳細(xì)的說明:

unit shapeExUnit;

 

interface

uses

  SysUtils,Classes,Graphics,Controls,ExtCtrls;

 

type

//定義了幾種形狀:矩形,正方形,圓角矩形,圓角正方形,橢圓形,圓形,

//增加的圖形:橫線,堅(jiān)線,上三角形,菱形

 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

  //最重要的函數(shù),在父類TGraphicControl中定義的一個(gè)

  //虛函數(shù),當(dāng)?shù)玫絎M_PAINT消息時(shí),調(diào)用該函數(shù)引起重畫

  //父類是一個(gè)空函數(shù),以便TGraphicControl的子類復(fù)蓋它。

    procedure Paint; override;

  public

    constructor Create(AOwner: TComponent); override;

    destructor Destroy; override;

  published

  //這個(gè)函數(shù)當(dāng)圖形中的畫筆和畫刷改變時(shí)引起重畫,在設(shè)計(jì)器中最為明顯

    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

 

//構(gòu)造函數(shù),ControlStyle確定控件的特征,這里是加上csReplicatable

//使該控件可以用PaintTo方法把它畫到一個(gè)任意的畫布中

//另外還指定Pen和Brush對象的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;

//最重要函數(shù),控件就是以這個(gè)函數(shù)畫出來的。

procedure TShapeEx.Paint;

var

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

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

begin

//Canvas是父類TGraphicControl的屬性,用于畫控件

//在畫圖之前,要進(jìn)行一些坐標(biāo)點(diǎn)的確定,

  with Canvas do

  begin

  //如果以控件的四個(gè)角來畫圖形,當(dāng)Pen太大時(shí),圖形的邊線

  //將比Pen的寬要小一些,所以要進(jìn)行點(diǎn)的重定位。

    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時(shí)是一樣的等于一個(gè)象素

    //如果上面Pen.width等于1,則圖形的寬高剛好等于控件的寬高

    //如果為0,則圖形寬高要大于控件寬高一個(gè)象素了,所以有了下面的語句

    if Pen.Width = 0 then

    begin

      Dec(W);

      Dec(H);

    end;

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

    //當(dāng)圖形為正方類型的圖形時(shí),需要對圖形的位置進(jìn)行一些調(diào)整

    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這個(gè)函數(shù)將使系統(tǒng)發(fā)送WM_PAINT給TGraphicControl

//TGraphicControl的處理函數(shù)將調(diào)用Paint,而它的子類覆蓋了它

//所以實(shí)際就調(diào)用了ShapeEx的Paint函數(shù),從而達(dá)到了重畫的效果

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;

//設(shè)置圖形,同時(shí)引起重畫,以達(dá)到圖形變化,

//最明顯的效果是在設(shè)計(jì)器時(shí)改變Shape屬性時(shí)看到的變化

procedure TShapeEx.SetShape(Value: TShapeType);

begin

  if FShape <> Value then

  begin

    FShape := Value;

    Invalidate;

  end;

end;

 

end.

 

安裝等方法在上一章已經(jīng)說過了,這里不多說。這一次知道了圖形控件的大概做法,其實(shí)無非就是覆蓋Paint來畫自己的圖形控件,而其他,則和我們上一章的說過的一樣。其實(shí)也很簡單。

以上兩個(gè)控件算是比較簡單,但已經(jīng)講清了很多組件制作的概念和技巧,看不看得懂就由你了,我也沒有辦法。有一個(gè)有用的技巧就是多看看VCL的源碼,你會(huì)學(xué)到更多的東西。

接下來,應(yīng)該要做一個(gè)難一點(diǎn)了吧。想知道是什么,且聽下回分解。

上一篇:組件制作之四(定制外觀)

下一篇:組件制作之二(一個(gè)簡單組件的制作過程)

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 汕头市| 兴隆县| 鲜城| 金溪县| 弥渡县| 峡江县| 绵竹市| 霞浦县| 德州市| 陇南市| 赞皇县| 绩溪县| 陇西县| 乌兰浩特市| 汽车| 阳朔县| 渭源县| 凌海市| 静乐县| 察哈| 新巴尔虎右旗| 德庆县| 珠海市| 乌海市| 四会市| 中西区| 邹城市| 绩溪县| 丹凤县| 宜丰县| 宁化县| 枣庄市| 上高县| 安丘市| 龙游县| 庆阳市| 垫江县| 伊春市| 广宁县| 蒲城县| 铅山县|