Delphi实现类似Android锁屏的密码锁控件
? ? 好久沒寫過博客咯!瞎忙的不得了!整來整去沒整出個(gè)正經(jīng)東西,目前自己實(shí)現(xiàn)的電子病歷已經(jīng)投入使用,功能還不全面,很弱,質(zhì)控以及標(biāo)準(zhǔn)化都還沒去細(xì)整,平時(shí)業(yè)余的時(shí)間一個(gè)人整,還真是沒那么多的時(shí)間與精力去一一的細(xì)化!哎,只能慢慢的來吧!年初整了個(gè)小米手機(jī),功能上還是不錯(cuò)的,不像某些人說的那么垃圾,總之我用的還是很不錯(cuò)的。各種游戲,神馬的跑動(dòng)起來小意思,流暢狠。今天要整的主題就是手機(jī)上的一個(gè)功能了,直接給搬運(yùn)到Delphi上來。那就是手機(jī)鎖屏之后,開屏的時(shí)候,要求咱們輸入密碼的那個(gè)滑動(dòng)效果輸入的控件。想想,整在軟件中,用來在客戶離開計(jì)算機(jī),鎖屏的時(shí)候還是蠻不錯(cuò)的一種方式,而且一般的圖形圖像給人的記憶比純粹的數(shù)字文字類的更能讓人印象深刻。所以決定將這個(gè)東西整到PC上來。
? ?Android的那個(gè)鎖屏的效果,用過的人應(yīng)該都知道是個(gè)什么效果,也就是橫豎各3行,排列成九宮格的效果,然后由用戶在上面滑動(dòng)以此來達(dá)到密碼輸入進(jìn)而進(jìn)行解鎖和加密的效果。那么首先,俺們可以分析一下,他的具體形成思路,實(shí)際上是很簡(jiǎn)單的,就是一個(gè)排列,然后根據(jù)滑動(dòng)產(chǎn)生的內(nèi)容形成密碼來達(dá)到解密的目的,那么最主要的就是這個(gè)密碼和他本身的密碼是如何對(duì)應(yīng)解密的,實(shí)際上很簡(jiǎn)單,咱們給他排列的九宮格,都固定好位置
| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |
就像這樣,排列的給他的位置固定好,然后每一個(gè)格子表示一個(gè)字符或者說字符串,進(jìn)而用戶滑動(dòng)的時(shí)候,將對(duì)應(yīng)的位置序列進(jìn)入到一個(gè)列表中去保存,然后鼠標(biāo)放開的時(shí)候,那么入隊(duì)的選擇位置進(jìn)行組合,那么就是對(duì)應(yīng)的密碼了,比如
這樣的輸入就是表示123,如此順序記錄,就可以形成密碼了,然后用戶進(jìn)行滑屏錄入之后和以前的進(jìn)行比較就可以知道密碼是否正確了,當(dāng)然我這個(gè)組合是相當(dāng)簡(jiǎn)單的,如果想要整的復(fù)雜,可以給每個(gè)順序位置給定復(fù)雜的字符串,這樣形成的密碼就足夠的復(fù)雜了!給一般人去看,也是看不明白的。
那么分析清楚了,思路也就簡(jiǎn)單了,鼠標(biāo)按下的時(shí)候,開始可以滑動(dòng)形成密碼,鼠標(biāo)按下的第一個(gè)點(diǎn),作為隊(duì)列的第一個(gè),然后再滑過的就順序的一一的記錄到隊(duì)列中,鼠標(biāo)放開的時(shí)候,從隊(duì)列中獲取各個(gè)順序位置,組合形成密碼然后和原密碼比對(duì),判斷密碼是否正確!源碼如下:
{Delphi實(shí)現(xiàn)的類似Android鼠標(biāo)鎖屏效果的控件作者:不得閑2012-7-23 } unit AndroidLockControl;interface uses Windows,Classes,SysUtils,Graphics,Controls;typeTDxLockItem = classprivater: TRect;IsEnter: Boolean;IsChecked: Boolean;Value: AnsiChar;FRadio: TPoint;publicconstructor Create;end;TInPutPwdEvent = procedure(Sender: TObject;InputPwd: string) of object;TDxAndroidLock = class(TGraphicControl)privateFItemSpace: 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);protectedprocedure 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;publicconstructor Create(AOwner: TComponent);override;destructor Destroy;override;property Password: string read FPassword write FPassWord;publishedproperty 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} varPngIn,PngOut: TPngImage; { TDxAndroidLock }procedure TDxAndroidLock.CalcItemRects; vari,j: Integer;p: TPoint;r: TRect;item: TDxLockItem; beginp.Y := FItemRaidio;for i := 1 to 3 dobeginp.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 dobeginitem := 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); vari: Integer; begininherited;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 dobeginItems.Add(TDxLockItem.Create);end;CalcItemRects; end;destructor TDxAndroidLock.Destroy; beginwhile Items.Count > 0 dobeginTDxLockItem(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); beginIsDown := Button = mbLeft;if IsDown thenbeginif LastInItem <> nil thenbeginLastInItem.IsChecked := IsDown;PwdItems.Add(LastInItem);end;Invalidate;end; end;procedure TDxAndroidLock.MouseMove(Shift: TShiftState; X, Y: Integer); vari: Integer;p: TPoint;OldInItem,Item: TDxLockItem; beginOldInItem := LastInItem;p := Point(x,y);LastInItem := nil;for i := 0 to items.Count - 1 dobeginitem := Items[i];if PtInRect(Item.r,p) thenbeginLastInItem := Item;LastInItem.IsEnter := True;LastInItem.IsChecked := IsDown;Break;end;end;if LastInItem <> OldInItem thenbeginif OldInItem <> nil thenOldInItem.IsEnter := False;if IsDown thenbeginif LastInItem <> nil thenbeginPwdItems.Add(LastInItem);end;Invalidate;end;end; end;procedure TDxAndroidLock.MouseUp(Button: TMouseButton; Shift: TShiftState; X,Y: Integer); vari: Integer;item: TDxLockItem;Np: string; beginIsDown := False;for i := 0 to items.Count - 1 dobeginitem := Items[i];item.IsChecked := False;end;for i := 0 to PwdItems.Count - 1 doNp := Np + TDxLockItem(PwdItems[i]).Value;PwdItems.Clear;Invalidate;if Assigned(FOnInputPwd) thenFOnInputPwd(self,Np); end;procedure DrawLineArrow(canvas: TCanvas; p1, p2: TPoint); constl = 6; //箭頭長(zhǎng)度w = 4; //箭頭寬度 varslope, angle: Double;points: array[0..2] of TPoint;Xl,b: Single; begincanvas.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) thenbeginxl := (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);endelse if p2.Y = p1.Y thenp2.X := (p2.X - p1.X) div 2 + p1.Xelse P2.Y := (p2.Y - p1.Y) div 2 + p1.Y; //畫箭頭points[0] := Point(p2.x, p2.y);//箭頭頂點(diǎn)if (p2.x - p1.x = 0) thenbegin //垂直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 elsebegin //傾斜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; vari: Integer;item,item1: TDxLockItem;r: TRect; beginif not IsDown thenbeginfor i := 0 to Items.Count - 1 dobeginitem := 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;endelsebegin//繪制指向線條Canvas.Pen.Width := 2;Canvas.Pen.Color := clGreen;for i := 0 to PwdItems.Count - 2 dobeginitem := 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 dobeginitem := items[i];if item.IsChecked thenbeginCanvas.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); beginFItemRaidio := Value; end;procedure TDxAndroidLock.SetItemSpace(const Value: Integer); beginFItemSpace := Value; end;procedure TDxAndroidLock.SetUseNum(const Value: Boolean); beginFUseNum := Value; end;{ TDxLockItem }constructor TDxLockItem.Create; beginr := Rect(0,0,0,0);IsEnter := False; end;initializationPngIn := TPngImage.Create;PngIn.LoadFromResourceName(Hinstance,'InnerGra');PngOut := TPngImage.Create;PngOut.LoadFromResourceName(Hinstance,'Outer');finalizationPngIn.Free;PngOut.Free; end.運(yùn)行之后的效果就是
轉(zhuǎn)載于:https://www.cnblogs.com/DxSoft/archive/2012/07/23/2604941.html
總結(jié)
以上是生活随笔為你收集整理的Delphi实现类似Android锁屏的密码锁控件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 多线程,解决处理大数据时窗体(不能
- 下一篇: uva 755487--3279