zoukankan      html  css  js  c++  java
  • Delphi TShape控件解析

    技术交流,DH讲解.

    这个控件在Additional选项卡,位于ExtCtrls.pas中.
    使用的样子:
    image
    这个控件应该就是一个图形控件,所以它应该直接从TGraphicControl继承下来,然后重载Paint方法就可以了,因为也没有其他好做的了.
    我们看看源码吧.

    type
      //这个控件可以设置形状
      TShapeType = (stRectangle, stSquare, stRoundRect, stRoundSquare,
        stEllipse, stCircle);
    
      TShape = class(TGraphicControl)
      private
        //笔(画边框) 和 笔刷(填背景)
        FPen: TPen;
        FBrush: TBrush;
        //什么形状
        FShape: TShapeType;
        //属性的方法,设置属性后,调用Invalidate刷新
        procedure SetBrush(Value: TBrush);
        procedure SetPen(Value: TPen);
        procedure SetShape(Value: TShapeType);
      protected
        //关键是这个
        procedure Paint; override;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        //这个其实就是Invalidate
        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 Touch;
        property Visible;
        property OnContextPopup;
        property OnDragDrop;
        property OnDragOver;
        property OnEndDock;
        property OnEndDrag;
        property OnMouseActivate;
        property OnMouseDown;
        property OnMouseEnter;
        property OnMouseLeave;
        property OnMouseMove;
        property OnMouseUp;
        property OnGesture;
        property OnStartDock;
        property OnStartDrag;
      end;
    我们看看设置属性的代码:
    procedure TShape.SetBrush(Value: TBrush);
    begin
      FBrush.Assign(Value);
    end;
    
    procedure TShape.SetPen(Value: TPen);
    begin
      FPen.Assign(Value);
    end;
    
    procedure TShape.SetShape(Value: TShapeType);
    begin
      if FShape <> Value then
      begin
        FShape := Value;
        Invalidate;
      end;
    end;
    前面2个为什么没有Invalidate?是不是觉得我在忽悠你?嘿嘿,不慌,我们看看Create里面干了什么事?
    constructor TShape.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ControlStyle := ControlStyle + [csReplicatable];//这个属性什么用,看我转的上一篇文章ControlStyle的意义吧
      Width := 65;
      Height := 65;
      FPen := TPen.Create;
      FPen.OnChange := StyleChanged;
      FBrush := TBrush.Create;
      FBrush.OnChange := StyleChanged;
    end;
    
    destructor TShape.Destroy;
    begin
      FPen.Free;
      FBrush.Free;
      inherited Destroy;
    end;
    看见了设置了Pen和Brush的OnChange事件为StyleChanged,也就是Pen或者Brush有改变就执行StyleChanged方法:
    procedure TShape.StyleChanged(Sender: TObject);
    begin
      Invalidate;
    end;
    我之前说了Invalidate是刷新,也就是调用Paint方法,那么我们看看Paint:
    procedure TShape.Paint;
    var
      X, Y, W, H, S: Integer;
    begin
      with Canvas do
      begin
        //设置画布的属性 和TShape一致
        Pen := FPen;
        Brush := FBrush;
        //确定画图区域,起始位置要注意笔的线宽的一半
        X := Pen.Width div 2;
        Y := X;
        W := Width - Pen.Width + 1;
        H := Height - Pen.Width + 1;
        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;
        //最后一步根据 形状 调用不同的Canvas方法画图形
        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);
        end;
      end;
    end;
    很简单吧,这个控件的确很简单,我们看源代码的时候,一步一步来就好了,关键思路要清晰.
    我是DH.
  • 相关阅读:
    分布式哈希和一致性哈希算法
    消息队列rabbitmq的五种工作模式(go语言版本)
    Mysql查询缓存
    数据库的三大设计范式
    二叉树的常见算法
    消息队列选型分析
    Mysql防止索引失效原则
    Mysql索引优化单表、两表、三表实践
    数据结构 【栈与队列】
    谷歌实用插件
  • 原文地址:https://www.cnblogs.com/huangjacky/p/1677037.html
Copyright © 2011-2022 走看看