Android的那个锁屏的效果,用过的人应该都知道是个什么效果,也就是横竖各3行,排列成九宫格的效果,然后由用户在上面滑动以此来达到密码输入进而进行解锁和加密的效果。那么首先,俺们可以分析一下,他的具体形成思路,实际上是很简单的,就是一个排列,然后根据滑动产生的内容形成密码来达到解密的目的,那么最主要的就是这个密码和他本身的密码是如何对应解密的,实际上很简单,咱们给他排列的九宫格,都固定好位置
就像这样,排列的给他的位置固定好,然后每一个格子表示一个字符或者说字符串,进而用户滑动的时候,将对应的位置序列进入到一个列表中去保存,然后鼠标放开的时候,那么入队的选择位置进行组合,那么就是对应的密码了,比如
那么分析清楚了,思路也就简单了,鼠标按下的时候,开始可以滑动形成密码,鼠标按下的第一个点,作为队列的第一个,然后再滑过的就顺序的一一的记录到队列中,鼠标放开的时候,从队列中获取各个顺序位置,组合形成密码然后和原密码比对,判断密码是否正确!源码如下:
{
Delphi实现的类似Android鼠标锁屏效果的控件
作者:不得闲
-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.