zoukankan      html  css  js  c++  java
  • 【转】DelphiXE10.2.3——跨平台生成验证码图片

    原文地址

    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;

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

  • 相关阅读:
    Netty之SubPage级别的内存分配
    Netty之Page级别的内存分配
    Netty内存池及命中缓存的分配
    新建maven工程问题001
    Eclipse使用技巧
    excel使用技巧
    java 单例模式
    springmvc拦截器验证登录时间
    Filter实现用户名验证
    springMVC的配置文件路径问题
  • 原文地址:https://www.cnblogs.com/kinglandsoft/p/9233873.html
Copyright © 2011-2022 走看看