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

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

1 2 3
4 5 6
7 8 9

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
{
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.

运行之后的效果就是

转载自: https://www.cnblogs.com/DxSoft/archive/2012/07/23/2604941.html

-------------本文已结束赏个小钱吧-------------
×

感谢您的支持,我们会一直保持!

扫码支持
请土豪扫码随意打赏

打开微信扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

64.7K

相关文章推荐