Qt,C++实现图片验证码

摘要:支持多种自定义功能。支持长度自定义,字体自定义,颜色自定义,噪点干扰线各种属性自定义,话不多说,先上图。

Qt,C++实现图片验证码_第1张图片

动态设置背景和边框颜色

Qt,C++实现图片验证码_第2张图片

动态修改圆角矩形,圆角比例可自定义

Qt,C++实现图片验证码_第3张图片

Qt,C++实现图片验证码_第4张图片

 动态更改验证码长度和噪点以及感染线数量

Qt,C++实现图片验证码_第5张图片

Qt,C++实现图片验证码_第6张图片

 Qt,C++实现图片验证码_第7张图片

 支持自定义的范围包括但不限于上图内容,有关所有自定义功能参考下面的结构体定义

 /// 图片验证码控件风格数据结构体
  typedef struct LQTIMGVERUIFY_STYLE_{
    double         dRcRoundRadius = 0.01;                ///矩形背景圆角半径
    uint           uObstructPoint = 200;                ///噪点数量
    double         dObstructPsize = 2.0;                ///噪点大小
    bool           bAoutPointSize = true;               ///是否为自动噪点大小
    bool           bAutoPointClrs = true;               ///使用自动噪点颜色
    QColor         cObstructPoint = QColor(235,98,30);  ///指定噪点颜色

    uint           uObstructLines = 50;                 ///干扰线数量
    double         dObstructLsize = 2.0;                ///干扰线大小
    bool           bAutoLinesSize = true;               ///使用自动干扰大小
    bool           bAutoLinesClrs = true;               ///使用自动干扰线颜色
    QColor         cObstructLines = QColor(53,177,146); ///指定干扰线颜色

    bool           bDarwBkgColors = true;               ///绘制背景
    bool           bDrawFrmBorder = true;               ///绘制边框
    double         dBordersWidths = 1.0;                ///边框宽度

    uint           uCodeMaxLength = 10;                 ///验证码字符最大长度
    uint           uCodeMinLength = 4;                  ///验证码字符最小长度
    uint           uCodeSetLength = 6;                  ///验证码字符设置长度

    bool           bCaseSensitive = false;              ///区分大小写
    bool           bAutoTextColor = true;               ///自动验证码文字颜色
    QColor         cCodeTextColor = QColor(11,11,29);   ///指定验证码文字颜色

    QFont          fCodeTextFonts;                      ///验证码文字字体


    QColor         cBkgndColorVal = QColor(220,220,220);///背景颜色
    QColor         cBordersColors = QColor(192,192,192);///边框颜色

    bool           bAutoFontSizes = true;               ///自动字体大小

    bool operator == (const LQTIMGVERUIFY_STYLE_& rhs) // == 操作运算符重载
    {
      return (uObstructPoint == rhs.uObstructPoint)
          && (QString("%1").arg(dRcRoundRadius) == QString("%1").arg(rhs.dRcRoundRadius))
          && (QString("%1").arg(dObstructPsize) == QString("%1").arg(rhs.dObstructPsize))
          && (bAoutPointSize == rhs.bAoutPointSize)
          && (bAutoPointClrs == rhs.bAutoPointClrs)
          && (cObstructPoint == rhs.cObstructPoint)
          && (uObstructLines == rhs.uObstructLines)
          && (QString("%1").arg(dObstructLsize) == QString("%1").arg(rhs.dObstructLsize))
          && (bAutoLinesSize == rhs.bAutoLinesSize)
          && (bAutoLinesClrs == rhs.bAutoLinesClrs)
          && (cObstructLines == rhs.cObstructLines)
          && (bDarwBkgColors == rhs.bDarwBkgColors)
          && (bDrawFrmBorder == rhs.bDrawFrmBorder)
          && (QString("%1").arg(dBordersWidths) == QString("%1").arg(rhs.dBordersWidths))
          && (uCodeMaxLength == rhs.uCodeMaxLength)
          && (uCodeMinLength == rhs.uCodeMinLength)
          && (uCodeSetLength == rhs.uCodeSetLength)
          && (bCaseSensitive == rhs.bCaseSensitive)
          && (bAutoTextColor == rhs.bAutoTextColor)
          && (cCodeTextColor == rhs.cCodeTextColor)
          && (cBkgndColorVal == rhs.cBkgndColorVal)
          && (cBordersColors == rhs.cBordersColors)
          && (bAutoFontSizes == rhs.bAutoFontSizes);
    }

    bool operator != (const LQTIMGVERUIFY_STYLE_& rhs) // != 操作运算符重载
    {
      return !(*this == rhs);
    }
  }LQTIMGVERUIFY_STYLE,*PLQTIMGVERUIFY_STYLE;

 下面上正菜,头文件主要代码如下

protected:
    ///重写鼠标按钮按下事件
    void mousePressEvent(QMouseEvent *event) override;

    ///重写系统绘制事件
    void paintEvent(QPaintEvent *event) override;

    ///绘制验证码
    void OnDrawVerifyCode(QPainter *painter);

    ///重写大小更改事件
    void resizeEvent(QResizeEvent *event) override;
  private:
    ///控件风格数据结构体
    LQTIMGVERUIFY_STYLE tCtrlStyleData;

    ///验证码文字数据
    QString             sVerifyCodeTxt;

    ///使用内部验证码生成
    bool                bInneBuildCode = true;
  private:
    /// 生成验证码随机文本
    /// \brief BuildRandCodeVal
    ///
    void BuildRandCodeVal();

    /// 绘制验证码图片
    /// \brief DrawVerifyImages
    /// \return
    ///
    QPixmap DrawVerifyImages();
  public:
    ///更新图形验证码
    /// \brief UpdateImagesCode
    ///
    void UpdateImagesCode();

    /// 验证字符是否与验证码匹配
    /// \brief VerifyImagesCode
    /// \param sCode
    /// \return
    ///
    bool VerifyImagesCode(const QString& sCode);

    /// 保存验证码图片
    /// \brief SavVerifyCodeImg
    /// \param sFileName
    /// \param sErr
    /// \return
    ///
    bool SavVerifyCodeImg(const std::u16string &sFileName,std::u16string &sErr);

    /// 复制验证码图片到剪贴板
    /// \brief CpyVerifyCodeImg
    /// \return
    ///
    bool CpyVerifyCodeImg();
  public:
    QSize sizeHint() const override;

    QSize minimumSizeHint() const override;

 核心绘图代码如下:

///重写鼠标按钮按下事件
  void Lncf_QImageVerify::mousePressEvent(QMouseEvent *event)
  {
    if(this->bInneBuildCode)
      UpdateImagesCode();
    else emit VerifyCodeClicks();
    QWidget::mousePressEvent(event);
  }

  ///重写系统绘制事件
  void Lncf_QImageVerify::paintEvent(QPaintEvent *event)
  {
    QWidget::paintEvent(event);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform);

    OnDrawVerifyCode(&painter);
  }

  ///绘制验证码
  void Lncf_QImageVerify::OnDrawVerifyCode(QPainter *painter)
  {
    painter->setBrush(tCtrlStyleData.bDarwBkgColors?tCtrlStyleData.cBkgndColorVal:Qt::transparent);
    painter->setPen(tCtrlStyleData.bDrawFrmBorder?QPen(tCtrlStyleData.cBordersColors,tCtrlStyleData.dBordersWidths):Qt::NoPen);

    QRectF rcGlobal = this->rect().adjusted(tCtrlStyleData.dBordersWidths,tCtrlStyleData.dBordersWidths,-tCtrlStyleData.dBordersWidths,-tCtrlStyleData.dBordersWidths);
    double dRectRadius = this->rect().height()*this->tCtrlStyleData.dRcRoundRadius;

    QPainterPath pathGlobal;
    pathGlobal.addRoundedRect(rcGlobal,dRectRadius,dRectRadius);
    painter->fillPath(pathGlobal,QBrush(tCtrlStyleData.bDarwBkgColors?tCtrlStyleData.cBkgndColorVal:Qt::transparent));

    painter->drawRoundedRect(rcGlobal,dRectRadius,dRectRadius);

    QRectF rcBkgd = rcGlobal.adjusted(tCtrlStyleData.dBordersWidths+dRectRadius,tCtrlStyleData.dBordersWidths,-tCtrlStyleData.dBordersWidths-dRectRadius,-tCtrlStyleData.dBordersWidths);

    QPen pen;
    //画点
    double dPointSize = tCtrlStyleData.bAoutPointSize?rcBkgd.height()/8.0:tCtrlStyleData.dObstructPsize;

    int rcOffsetVal = tCtrlStyleData.dBordersWidths+1;

    if(dPointSize<1.0) dPointSize = 1.0;
    //pen.setWidthF(dPointSize);
    painter->setPen(Qt::NoPen);
    painter->setBrush(this->tCtrlStyleData.cObstructPoint);
    double dPointRadius = this->tCtrlStyleData.dObstructPsize;
    if(dPointRadius<0.75)dPointRadius=1.0;
    for(uint i = 0;i < tCtrlStyleData.uObstructPoint;++i)
      {
        if(this->tCtrlStyleData.bAutoPointClrs){
#if QT_DEPRECATED_SINCE(5, 15)
            painter->setBrush(QColor(QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256)));
#else
            painter->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));
#endif
          }
        if(tCtrlStyleData.bAoutPointSize){
#if QT_DEPRECATED_SINCE(5, 15)
            dPointRadius = QRandomGenerator::global()->bounded(dPointSize);
#else
            dPointRadius = qrand()%(int)dPointSize;
#endif
            if(dPointRadius<0.75)dPointRadius=1.0;
          }
#if QT_DEPRECATED_SINCE(5, 15)
        painter->drawEllipse(QRandomGenerator::global()->bounded((int)(rcBkgd.left()+rcOffsetVal),rcBkgd.right()),QRandomGenerator::global()->bounded(rcOffsetVal,rcBkgd.height()-rcOffsetVal),dPointRadius,dPointRadius);
#else
        painter->drawEllipse(qrand()%(int)(rcBkgd.width()-rcOffsetVal),qrand()%(int)(rcBkgd.height()-rcOffsetVal),dPointRadius,dPointRadius);
#endif
      }

    //画线
    double dLinesSize = tCtrlStyleData.bAutoLinesSize?rcBkgd.height()/20.0:tCtrlStyleData.dObstructLsize;
    pen.setColor(this->tCtrlStyleData.cObstructLines);
    painter->setBrush(Qt::NoBrush);
    double dLineWidth = this->tCtrlStyleData.dObstructLsize;
    if(dLineWidth<0.75)dLineWidth = 1.0;
    pen.setWidthF(dLineWidth);

    for(uint i = 0;i < tCtrlStyleData.uObstructLines;++i)
      {
        if(this->tCtrlStyleData.bAutoLinesClrs){
#if QT_DEPRECATED_SINCE(5, 15)
            pen.setColor(QColor(QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256)));
#else
            pen.setColor(QColor(qrand()%256,qrand()%256,qrand()%256));
#endif
          }
        int nIndex = 1;

#if QT_DEPRECATED_SINCE(5, 15)
        nIndex =QRandomGenerator::global()->bounded(1,8);
#else
        nIndex =qrand()%8;
#endif
        pen.setStyle((Qt::PenStyle)nIndex);
        if(tCtrlStyleData.bAutoLinesSize){
#if QT_DEPRECATED_SINCE(5, 15)
            dLineWidth = QRandomGenerator::global()->bounded(dLinesSize);
#else
            dLineWidth = qrand()%(int)dLinesSize;
#endif
            if(dLineWidth<0.75)dLineWidth = 1.0;
            pen.setWidthF(dLineWidth);
          }
        painter->setPen(pen);

#if QT_DEPRECATED_SINCE(5, 15)
        painter->drawLine(QRandomGenerator::global()->bounded((int)(rcBkgd.left()+rcOffsetVal),rcBkgd.right()),QRandomGenerator::global()->bounded(rcOffsetVal,rcBkgd.height()),
                          QRandomGenerator::global()->bounded((int)(rcBkgd.left()+rcOffsetVal),rcBkgd.right()),QRandomGenerator::global()->bounded(rcOffsetVal,rcBkgd.height()));
#else
        painter->drawLine(qrand()%(int)rcBkgd.width(),qrand()%(int)(rcBkgd.height()-rcOffsetVal),
                          qrand()%(int)rcBkgd.width(),qrand()%(int)(rcBkgd.height()-rcOffsetVal));
#endif

      }

    double dTextMargin = 2.0;
    QRectF rcText = rcBkgd.adjusted(dTextMargin,dTextMargin,-dTextMargin,-dTextMargin);

    double dFontMaxSize = rcText.height();
    QFont fTextObjs = tCtrlStyleData.fCodeTextFonts;
    fTextObjs.setBold(true);
    fTextObjs.setPointSize(dFontMaxSize/3);
    painter->setFont(fTextObjs);

    //绘画字
    pen.setColor(this->tCtrlStyleData.cCodeTextColor);
    painter->setPen(pen);

    if(this->sVerifyCodeTxt.length()!=tCtrlStyleData.uCodeSetLength){
        this->sVerifyCodeTxt = "";
        for(uint i=0;itCtrlStyleData.uCodeSetLength;i++){
            this->sVerifyCodeTxt.append("0");
          }
      }

    for(uint i = 0;i < this->tCtrlStyleData.uCodeSetLength;i++)
      {
        if(this->tCtrlStyleData.bAutoTextColor){
#if QT_DEPRECATED_SINCE(5, 15)
            pen.setColor(QColor(QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256)));
#else
            pen.setColor(QColor(qrand()%256,qrand()%256,qrand()%256));
#endif
            painter->setPen(pen);
          }
        if(this->tCtrlStyleData.bAutoFontSizes){
#if QT_DEPRECATED_SINCE(5, 15)
            fTextObjs.setPointSize(QRandomGenerator::global()->bounded((int)(dFontMaxSize/5),(dFontMaxSize/2)));
#else
            fTextObjs.setPointSize(qrand()(dFontMaxSize/2));
#endif

            painter->setFont(fTextObjs);
          }
        float fLeftMargin = rcText.left()+i*((rcText.width()/(tCtrlStyleData.uCodeSetLength)));
        float fCharsWidth = rcText.width()/tCtrlStyleData.uCodeSetLength;

        QRectF rcChar = QRectF(fLeftMargin,rcText.top(),fCharsWidth,rcText.height());

        painter->drawText(rcChar,Qt::AlignCenter,sVerifyCodeTxt.at(i));
      }
  }

困了,先到这里

有关详细信息和技术交流,移步QQ群:717743458。

你可能感兴趣的:(qt,c++,网络)