RSS订阅 | 匿名投稿
您的位置:网站首页 > FMX > 正文

DelphiXE10.2.3——跨平台生成验证码图片

作者:admin 来源: 日期:2018/11/6 19:56:33 人气: 标签:

原文地址

Java、PHP、C#等很容易在网上找到生成验证码图片的代码,Delphi却寥寥无几,昨天花了一整天时间,做了个跨平台的验证码,可以用在C/S和B/S端,支持Windows、Linux、Android、IOS等。对于验证码图形的混淆,只做了简单的随机线条生成,并且随机数是使用系统自带的Randomize和Random函数,Randomize随机数初始化函数由于取种子是保存在全局变量中,虽然是integer类型,但不排除非线程安全问题,所以实际应用中,还需要线程保护。

C/S和B/S上的显示效果:

unit uVerifyCode;


interface


uses System.Classes, System.SysUtils, FMX.Types, FMX.Objects, FMX.Graphics,

  System.UIConsts, System.UITypes,

{$IFDEF MSWINDOWS}ActiveX, {$ENDIF MSWINDOWS}

  System.Types;


type

  // 生成验证码组件

  TGenerateVerifyCode = class

  private const

    // 定义字典表,不要零(0),因为零和字母O样子太接近

     arrStr: array [0 .. 34] of char = (

      '1','2','3','4','5','6','7','8','9',

      'A','B','C','D','E','F','G','H','I',

      'J','K','L','M','N','O','P','Q','R',

      'S','T','U','V','W','X','Y','Z');

  private

    FBitmapWidth: integer; // 图片宽度

    FBitmapHeight: integer; // 图片高度

    FCodeCount: integer; // 取验证码字符的个数,默认是4个字符

    FFontName: string; // 字体名称

    FMinFontSize: integer; // 最小字体大小

    FRandomLineCount: integer; // 背景随机线条数

    FTransparency: byte; // 背景随机线条的透明度

    FXRandomLen: integer; // X的随机值长度

    FYRandomLen: integer; // Y的随机值长度

    // 画出验证码函数

    function VerifyCodeDrawImg(Img: TImage): string;

  public

    constructor Create();

    procedure GetVerifyCodeAndImage(ImageStream: TStream;

      var VerifyCode: string);

  published

    property Width: integer read FBitmapWidth write FBitmapWidth;

    property Height: integer read FBitmapHeight write FBitmapHeight;

    property CodeCount: integer read FCodeCount write FCodeCount;

    property FontName: string read FFontName write FFontName;

    property MinFontSize: integer read FMinFontSize write FMinFontSize;

    property RandomLineCount: integer read FRandomLineCount

      write FRandomLineCount;

    property Transparency: byte read FTransparency write FTransparency;

    property XRandomLen: integer read FXRandomLen write FXRandomLen;

    property YRandomLen: integer read FYRandomLen write FYRandomLen;

  end;


implementation


constructor TGenerateVerifyCode.Create();

begin

  inherited;

  FBitmapWidth := 100;

  FBitmapHeight := 30;

  FCodeCount := 4;

  FFontName := '宋体';

  FMinFontSize := 15;

  FRandomLineCount := 100;

  FTransparency := 200;

  FXRandomLen := 5;

  FYRandomLen := 4;

end;


// 获取验证码和影像的流数据

procedure TGenerateVerifyCode.GetVerifyCodeAndImage(ImageStream: TStream;

  var VerifyCode: string);

var

  Img: FMX.Objects.TImage;

begin

{$IFDEF MSWINDOWS}CoInitialize(nil); {$ENDIF MSWINDOWS}

  Img := FMX.Objects.TImage.Create(nil);

  try

    Img.Bitmap := FMX.Graphics.TBitmap.Create(FBitmapWidth, FBitmapHeight);

    // 宽100,高40

    Img.Bitmap.Canvas.BeginScene;

    VerifyCode := VerifyCodeDrawImg(Img);

    Img.Bitmap.Canvas.EndScene;

    Img.Bitmap.SaveToStream(ImageStream); // 写到流中

  finally

    freeandnil(Img);

  end;

end;


// 画出验证码函数

function TGenerateVerifyCode.VerifyCodeDrawImg(Img: TImage): string;

var

  I, j, k: integer;

  X, Y, W, H: Single;

  vLeft: Single;

  strResult: RawByteString;

begin

  // 只取4个字符

  For j := 1 to FCodeCount do

  begin

    Randomize;

    k := Random(1000000) mod 35;

    strResult := strResult + trim(arrStr[k]);

  end;

  vLeft := 5;

  Img.Bitmap.Canvas.Font.Family := FFontName;

  for j := 1 to FRandomLineCount do // 随机画100条线

  begin

    Randomize;

    Img.Bitmap.Canvas.Stroke.Color := MakeColor(Random(256) and $C0,

      Random(256) and $C0, Random(256) and $C0, FTransparency);

    Img.Bitmap.Canvas.DrawLine(pointf(Random(120), Random(50)),

      pointf(Random(120), Random(50)), 1);

  end;

  // 随机字体颜色,这里暂时不用每个字符一个随机颜色

  Img.Bitmap.Canvas.Fill.Color := MakeColor((Random(256) and $C0),

    (Random(256) and $C0), (Random(256) and $C0));

  // 背景色反色

  Img.Bitmap.Clear(Img.Bitmap.Canvas.Fill.Color xor $FFFFFF);

  for I := 1 to length(strResult) do

  begin

    Randomize;

    // 字体大小

    Img.Bitmap.Canvas.Font.Size := Random(8) + FMinFontSize;

    if Img.Bitmap.Canvas.Font.Size < (FMinFontSize + 5) then

      Img.Bitmap.Canvas.Font.Size := Img.Bitmap.Canvas.Font.Size + 5;

    if Random(2) = 1 then

      Img.Bitmap.Canvas.Font.Style := [TFontStyle.fsBold]

    else

      Img.Bitmap.Canvas.Font.Style := [TFontStyle.fsItalic];

    begin

      X := Random(FXRandomLen) + vLeft;

      Y := Random(FYRandomLen);

      W := Img.Bitmap.Canvas.TextWidth(strResult[I]);

      H := Img.Bitmap.Canvas.TextHeight(strResult[I]);

      Img.Bitmap.Canvas.FillText(TRectF.Create(X, Y, X + W, Y + H),

        strResult[I], false, 1, [], TTextAlign.taCenter, TTextAlign.taCenter);

      vLeft := X + W + 1;

    end;

  end;

  Result := strResult; // 返回值

end;


end.


使用方法:

C/S与B/S共同创建方法

var
 FGenerateVerifyCode: TGenerateVerifyCode;
begin
  FGenerateVerifyCode := TGenerateVerifyCode.Create;
end;
一、C/S使用方法:


procedure TForm1.Button1Click(Sender: TObject);
var
  ImageStream: TMemoryStream;
  VerifyCode: string;
begin
  ImageStream:= TMemoryStream.Create;
  try
  GetVerifyCodeAndImage(ImageStream, VerifyCode);
  Label1.Text:=VerifyCode;
  ImageStream.Position:=0;
  Image1.Bitmap.LoadFromStream(ImageStream);
  finally
    ImageStream.Free;
  end;
end;
复制代码
二、B/S使用方法:

1、HTML中加入Img元素

<img src="VerifyCode" id="img-code" class="Verify-Code" style="cursor:pointer" alt="验证码" title="看不清楚?点一下图片刷新">
2、JS代码

$("#img-code").bind( 'click', function () {
        $(this).attr('src','VerifyCode?t='+Math.random());
        });
3、服务端代码


// 获取验证码图片
function TSystemPagePlugin.Method_VerifyCode(Request: TWebRequest;
  Response: TWebResponse): boolean;
VAR
  VerifyCode: string;
begin
  Response.ContentStream := TMemoryStream.Create;
  Response.ContentType := 'application/binary;';
  // 获取验证码图片和数值
   GetVerifyCodeAndImage(Response.ContentStream, VerifyCode);
  result := true;
end;

 感谢作者晴空无彩虹无私的分享!


读完这篇文章后,您心情如何?
0
0
0
0
0
0
0
0
本文网址:
下一篇:没有资料