• Delphi实现类似Android锁屏的密码锁控件


        好久没写过博客咯!瞎忙的不得了!整来整去没整出个正经东西,目前自己实现的电子病历已经投入使用,功能还不全面,很弱,质控以及标准化都还没去细整,平时业余的时间一个人整,还真是没那么多的时间与精力去一一的细化!哎,只能慢慢的来吧!年初整了个小米手机,功能上还是不错的,不像某些人说的那么垃圾,总之我用的还是很不错的。各种游戏,神马的跑动起来小意思,流畅狠。今天要整的主题就是手机上的一个功能了,直接给搬运到Delphi上来。那就是手机锁屏之后,开屏的时候,要求咱们输入密码的那个滑动效果输入的控件。想想,整在软件中,用来在客户离开计算机,锁屏的时候还是蛮不错的一种方式,而且一般的图形图像给人的记忆比纯粹的数字文字类的更能让人印象深刻。所以决定将这个东西整到PC上来。

       Android的那个锁屏的效果,用过的人应该都知道是个什么效果,也就是横竖各3行,排列成九宫格的效果,然后由用户在上面滑动以此来达到密码输入进而进行解锁和加密的效果。那么首先,俺们可以分析一下,他的具体形成思路,实际上是很简单的,就是一个排列,然后根据滑动产生的内容形成密码来达到解密的目的,那么最主要的就是这个密码和他本身的密码是如何对应解密的,实际上很简单,咱们给他排列的九宫格,都固定好位置

    1 2 3
    4 5 6
    7 8 9

    就像这样,排列的给他的位置固定好,然后每一个格子表示一个字符或者说字符串,进而用户滑动的时候,将对应的位置序列进入到一个列表中去保存,然后鼠标放开的时候,那么入队的选择位置进行组合,那么就是对应的密码了,比如

    这样的输入就是表示123,如此顺序记录,就可以形成密码了,然后用户进行滑屏录入之后和以前的进行比较就可以知道密码是否正确了,当然我这个组合是相当简单的,如果想要整的复杂,可以给每个顺序位置给定复杂的字符串,这样形成的密码就足够的复杂了!给一般人去看,也是看不明白的。

    那么分析清楚了,思路也就简单了,鼠标按下的时候,开始可以滑动形成密码,鼠标按下的第一个点,作为队列的第一个,然后再滑过的就顺序的一一的记录到队列中,鼠标放开的时候,从队列中获取各个顺序位置,组合形成密码然后和原密码比对,判断密码是否正确!源码如下:

    {
      Delphi实现的类似Android鼠标锁屏效果的控件
      作者:不得闲
      2012-7-23
    }
    unit AndroidLockControl;
    
    interface
    uses Windows,Classes,SysUtils,Graphics,Controls;
    
    type
      TDxLockItem = class
      private
        r: TRect;
        IsEnter: Boolean;
        IsChecked: Boolean;
        Value: AnsiChar;
        FRadio: TPoint;
      public
        constructor Create;
      end;
    
      TInPutPwdEvent = procedure(Sender: TObject;InputPwd: string) of object;
      TDxAndroidLock = class(TGraphicControl)
      private
        FItemSpace: Integer;
        FRowCount: Integer;
        FColCount: Integer;
        FItemRaidio: Integer;
        Items: TList;
        FUseNum: Boolean;
        FPassword: string;
        IsDown: Boolean;
        LastInItem: TDxLockItem;
        PwdItems: TList;
        FOnInputPwd: TInPutPwdEvent;
        procedure SetItemSpace(const Value: Integer);
        procedure SetItemRaidio(const Value: Integer);
        procedure SetUseNum(const Value: Boolean);
      protected
        procedure paint;override;
        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;
        procedure CalcItemRects;
      public
        constructor Create(AOwner: TComponent);override;
        destructor Destroy;override;
        property Password: string read FPassword write FPassWord;
      published
        property ItemSpace: Integer read FItemSpace write SetItemSpace default 10;
        property OnInputPwd: TInPutPwdEvent read FOnInputPwd write FOnInputPwd;
        property ItemRaidio: Integer read FItemRaidio write SetItemRaidio default 20;
        property UseNum: Boolean read FUseNum write SetUseNum;
      end;
    implementation
    uses pngimage;
    {$R LockRc.RES}
    var
      PngIn,PngOut: TPngImage;
    { TDxAndroidLock }
    
    procedure TDxAndroidLock.CalcItemRects;
    var
      i,j: Integer;
      p: TPoint;
      r: TRect;
      item: TDxLockItem;
    begin
      p.Y := FItemRaidio;
      for i := 1 to 3 do
      begin
        p.X := FItemRaidio;
        r.Left := p.X - FItemRaidio;r.Top := p.Y - FItemRaidio;
        r.Right := p.x + FItemRaidio;r.Bottom := p.Y + FItemRaidio;
        for j := 1 to 3 do
        begin
          item := Items[3*(i-1)+j - 1];
          item.Value := AnsiChar(3*(i-1)+j+48);
          item.FRadio := p;
          item.r := r;
          p.X := p.X + FItemRaidio * 2 + FItemSpace;
          r.Left := p.X - FItemRaidio;r.Right := p.X + FItemRaidio;
        end;
        p.Y := p.Y + FItemRaidio * 2 + FItemSpace;
      end;
    end;
    
    constructor TDxAndroidLock.create(AOwner: TComponent);
    var
      i: Integer;
    begin
      inherited;
      LastInItem := nil;
      PwdItems := TList.Create;
      FPassWord := '';
      Items := TList.Create;
      FItemSpace := 10;
      FRowCount := 3;
      FColCount := 3;
      FItemRaidio := 20;
      Width := FItemRaidio * 2 * 3 + FItemSpace * 2;
      Height := FItemRaidio * 2 * 3 + FItemSpace * 2;
      for i := 0 to 8 do
      begin
        Items.Add(TDxLockItem.Create);
      end;
      CalcItemRects;
    end;
    
    destructor TDxAndroidLock.Destroy;
    begin
      while Items.Count > 0 do
      begin
        TDxLockItem(Items[Items.Count - 1]).Free;
        Items.Delete(Items.Count - 1);
      end;
      PwdItems.Free;
      inherited;
    end;
    
    procedure TDxAndroidLock.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer);
    begin
      IsDown := Button = mbLeft;
      if IsDown then
      begin
        if LastInItem <> nil then
        begin
          LastInItem.IsChecked := IsDown;
          PwdItems.Add(LastInItem);
        end;
        Invalidate;
      end;
    end;
    
    procedure TDxAndroidLock.MouseMove(Shift: TShiftState; X, Y: Integer);
    var
      i: Integer;
      p: TPoint;
      OldInItem,Item: TDxLockItem;
    begin
      OldInItem := LastInItem;
      p := Point(x,y);
      LastInItem := nil;
      for i := 0 to items.Count - 1 do
      begin
        item := Items[i];
        if PtInRect(Item.r,p) then
        begin
          LastInItem := Item;
          LastInItem.IsEnter := True;
          LastInItem.IsChecked := IsDown;
          Break;
        end;
      end;
      if LastInItem <> OldInItem then
      begin
        if OldInItem <> nil then
          OldInItem.IsEnter := False;
        if IsDown then
        begin
          if LastInItem <> nil then
          begin
            PwdItems.Add(LastInItem);
          end;
          Invalidate;
        end;
      end;
    end;
    
    procedure TDxAndroidLock.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer);
    var
      i: Integer;
      item: TDxLockItem;
      Np: string;
    begin
      IsDown := False;
      for i := 0 to items.Count - 1 do
      begin
        item := Items[i];
        item.IsChecked := False;
      end;
      for i := 0 to PwdItems.Count - 1 do
        Np := Np + TDxLockItem(PwdItems[i]).Value;
      PwdItems.Clear;
      Invalidate;
      if Assigned(FOnInputPwd) then
        FOnInputPwd(self,Np);
    end;
    
    procedure DrawLineArrow(canvas: TCanvas; p1, p2: TPoint);
    const
      l = 6; //箭头长度
      w = 4; //箭头宽度
    var
      slope, angle: Double;
      points: array[0..2] of TPoint;
      Xl,b: Single;
    begin
      canvas.Brush.Color := canvas.Pen.Color;
      canvas.Brush.Style := bsSolid;
      canvas.MoveTo(p1.X,p1.Y);
      canvas.LineTo(p2.X,p2.Y);
      if (p2.Y <> p1.Y) and (P2.X <> p1.X) then
      begin
        xl := (P2.Y - p1.Y) / (P2.X - p1.X);
        b := p2.Y - xl * p2.X;
        p2.X := (p2.X - p1.X) div 2 + p1.X;
        p2.Y := Trunc(p2.X * xl + b);
      end
      else if p2.Y = p1.Y then
        p2.X := (p2.X - p1.X) div 2 + p1.X
      else P2.Y := (p2.Y - p1.Y) div 2 + p1.Y;
    //画箭头
      points[0] := Point(p2.x, p2.y);//箭头顶点
      if (p2.x - p1.x = 0) then
      begin //垂直
        if (p2.y - p1.y > 0) then slope := -1 else slope := 1;
        points[1] := Point(p2.x - w, p2.y + Trunc(l * slope));
        points[2] := Point(p2.x + w, p2.y + Trunc(l * slope));
      end else
      begin //倾斜
        slope := (p2.y - p1.y) / (p2.x - p1.x);
        angle := ArcTan(slope);
        if (p2.x - p1.x > 0) then angle := angle - PI;
        points[1] := Point(p2.x + trunc(l * cos(angle) - w * sin(angle)),
          p2.y + trunc(l * sin(angle) + w * cos(angle)));
        points[2] := Point(p2.x + Trunc(l * cos(angle) + w * sin(angle)),
          p2.y + Trunc(l * sin(angle) - w * cos(angle)));
      end;
      canvas.Polygon(points);
    end;
    
    procedure TDxAndroidLock.paint;
    var
      i: Integer;
      item,item1: TDxLockItem;
      r: TRect;
    begin
      if not IsDown then
      begin
        for i := 0 to Items.Count - 1 do
        begin
          item := items[i];
          r.Left := item.FRadio.X - 5;r.Right := item.FRadio.X + 5;
          r.Top := item.FRadio.Y - 5;r.Bottom := item.FRadio.Y + 5;
          Canvas.Draw(r.Left,r.Top,pngIn);
        end;
      end
      else
      begin
        //绘制指向线条
        Canvas.Pen.Width := 2;
        Canvas.Pen.Color := clGreen;
        for i := 0 to PwdItems.Count - 2 do
        begin
          item := PwdItems[i];
          item1 := PwdItems[i + 1];
          Canvas.MoveTo(item.FRadio.X,item.FRadio.Y);
          Canvas.LineTo(item1.FRadio.X,item1.FRadio.Y);
          DrawLineArrow(Canvas,item.FRadio,item1.FRadio);
        end;
        for i := 0 to Items.Count - 1 do
        begin
          item := items[i];
          if item.IsChecked then
          begin
            Canvas.Draw(item.r.Left,item.r.Top,pngOut);
          end;
          r.Left := item.FRadio.X - 5;r.Right := item.FRadio.X + 5;
          r.Top := item.FRadio.Y - 5;r.Bottom := item.FRadio.Y + 5;
          Canvas.Draw(r.Left,r.Top,pngIn);
        end;
      end;
    end;
    
    procedure TDxAndroidLock.SetItemRaidio(const Value: Integer);
    begin
      FItemRaidio := Value;
    end;
    
    procedure TDxAndroidLock.SetItemSpace(const Value: Integer);
    begin
      FItemSpace := Value;
    end;
    
    procedure TDxAndroidLock.SetUseNum(const Value: Boolean);
    begin
      FUseNum := Value;
    end;
    
    { TDxLockItem }
    
    constructor TDxLockItem.Create;
    begin
      r := Rect(0,0,0,0);
      IsEnter := False;
    end;
    
    initialization
     PngIn := TPngImage.Create;
     PngIn.LoadFromResourceName(Hinstance,'InnerGra');
     PngOut := TPngImage.Create;
     PngOut.LoadFromResourceName(Hinstance,'Outer');
    
    finalization
      PngIn.Free;
      PngOut.Free;
    end.

    运行之后的效果就是

    作者:不得闲
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原
    文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    http响应状态码大全
    Oracle中start with...connect by子句的用法
    sql的连接查询
    spring框架等web程序在tomcat下的启动顺序
    rest模式get,post,put,delete简单讲解
    context-param和init-param的区别
    spring的webutils包。适用于访问httpservletrequest和httpservletresponse
    java日志的相关配置文件知识
    jquery开发插件提供的几种方法
    Node.js实现网络编程
  • 原文地址:https://www.cnblogs.com/DxSoft/p/2604941.html
Copyright © 2020-2023  润新知