手把手教你做一个 法院速录测试系统

0.最终效果展示

这里写图片描述

1.环境以及材料准备

  • VS2010
  • pdflib.dll
  • pdflib.h
  • pdflib.lib

2.开始开发

2.1创建一个项目

新建一个mfc项目,名称任意,在此以myapp_1命名,如图所示

这里写图片描述

应用程序类型使用基于对话框,如图
这里写图片描述

用户功能界面去掉系统菜单的对勾,如图
这里写图片描述

点击完成,至此应用创建完毕。

2.2界面搭建

这一步主要靠拖动控件,完成界面搭建,完成图如下所示
这里写图片描述

2.3倒计时功能搭建

这一步的功能是,点击开始考试按钮,时间开始倒计时

首先给开始考试按钮修改一下ID,在其属性界面更改ID,如图更改成IDC_BEGIN_TEST,主要是为了更好辨认

这里写图片描述

给这个按钮添加一个与之关联的变量
选中这个按钮右键->添加变量 变量名:btn_begin_test
这里写图片描述

双击按钮添加处理程序,定位到这段代码

void Cmyapp_1Dlg::OnBnClickedBeginTest()
{
    // TODO: 在此添加控件通知处理程序代码

}

添加以下几行代码

//这里需要判断用户输入的准考证信息,身份证信息是否合法,暂时先省略
    btn_begin_test.EnableWindow(FALSE);//让按钮无法点击
    SetTimer(1,1000,NULL);//设置一个定时器,这里有三个参数,第一个参数:定时器id,第二个参数:时间间隔,第三个参数:需要触发的函数,当值为NULL交给系统处理

最后应该是这个样子的

void Cmyapp_1Dlg::OnBnClickedBeginTest()
{
    // TODO: 在此添加控件通知处理程序代码

    //这里需要判断用户输入的准考证信息,身份证信息是否合法,暂时先省略
    btn_begin_test.EnableWindow(FALSE);//让按钮无法点击
    SetTimer(1,1000,NULL);//设置一个定时器,这里有三个参数,第一个参数:定时器id,第二个参数:时间间隔,第三个参数:需要触发的函数,当值为NULL交给系统处理


}

然后复写一个监听时间变化消息的函数

首先切换到类视图,如图
这里写图片描述

右键CmyApp_1Dlg->类向导->消息 添加 WM_TIMER

这里写图片描述

添加处理程序,应该多出一个方法

这里写图片描述

添加一个记录时间的变量,time_sum

找到 类视图->Cmyapp1Dlg->添加变量
这里写图片描述

添加一个函数 getFormatTime, 参数 int,返回值CString

找到 类视图->Cmyapp1Dlg->添加函数
这里写图片描述

这里写图片描述

应该多一个方法,类似于

CString Cmyapp_1Dlg::getFormatTime(int time_left)
{
    return CString();
}

复写这个方法


CString Cmyapp_1Dlg::getFormatTime(int time_left)
{
    int sum = 15*60 - time_left;
    int second = sum % 60;
    int minute = sum / 60;
    CString t;
    t.Format(L"%d分%d秒",minute,second);
    return t;
}

给剩余时间修改ID为 IDC_TIME_LEFT
这里写图片描述

这里写图片描述

并且添加变量 tv_time_left,类别选Value

这里写图片描述

复写OnTimer函数

void Cmyapp_1Dlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CDialogEx::OnTimer(nIDEvent);
}

最后应该是:

void Cmyapp_1Dlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    UpdateData(TRUE);
    tv_time_left = getFormatTime(++time_sum);
    UpdateData(FALSE);
    CDialogEx::OnTimer(nIDEvent);
}

现在运行程序,点击开始考试,就能开始倒计时了,倒计时功能至此完成,附图:
这里写图片描述
如果不行,请检查以上步骤。

2.4判断用户输入

开发目标:准考证号为11位数字,身份证号为18位,还应该判断年龄,如果不符合则提示用户修改。

为准考证的输入框,以及身份证的输入框添加变量,et_zkz , et_sfz 如图(注意 类别为Value 不是 Control):
这里写图片描述

这里写图片描述

设置准考证只能输入数字:
准考证输入框->属性->Number = True
这里写图片描述

现在我们添加两个函数来判断:
int check_zkz(CString zkz) //返回值为0 为正常,下同
int check_sfz(CString sfz)//同上

添加check_zkz(CString zkz)函数的过程:
类视图->Cmyapp_1Dlg->添加函数

这里写图片描述

添加完应该是这样的


int Cmyapp_1Dlg::check_zkz(CString zkz)
{
    return 0;
}

复写这个函数,判断准考证位数是不是11位,不是返回1,是返回0

int Cmyapp_1Dlg::check_zkz(CString zkz)
{
    int length = zkz.GetLength();
    if(length == 11)
        return 0;
    return 1;
}

在点击“开始考试”按钮时调用准考证判断函数
修改前的函数

void Cmyapp_1Dlg::OnBnClickedBeginTest()
{
    // TODO: 在此添加控件通知处理程序代码

    //这里需要判断用户输入的准考证信息,身份证信息是否合法,暂时先省略
    btn_begin_test.EnableWindow(FALSE);//让按钮无法点击
    SetTimer(1,1000,NULL);//设置一个定时器,这里有三个参数,第一个参数:定时器id,第二个参数:时间间隔,第三个参数:需要触发的函数,当值为NULL交给系统处理
}

可以把之前暂时省略的判断代码加上去

void Cmyapp_1Dlg::OnBnClickedBeginTest()
{
    // TODO: 在此添加控件通知处理程序代码

    //这里需要判断用户输入的准考证信息,身份证信息是否合法,暂时先省略

    //判断用户的准考证号
    UpdateData(TRUE);
    int zkz_result = check_zkz(et_zkz);
    if (zkz_result == 1)
    {
        MessageBox(_T("准考证为11位数字"));
        return;
    }
    btn_begin_test.EnableWindow(FALSE);//让按钮无法点击
    SetTimer(1,1000,NULL);//设置一个定时器,这里有三个参数,第一个参数:定时器id,第二个参数:时间间隔,第三个参数:需要触发的函数,当值为NULL交给系统处理
}

至此,完成了验证输入的准考证号码是否为11位的功能,测试如图:
这里写图片描述

判断身份证号的有效性
大致流程与上面一样

添加一个函数 ,int check_sfz(CString sfz)
去类视图->Cmyapp_1Dlg->添加函数,如图:
这里写图片描述

复写这个函数:

int Cmyapp_1Dlg::check_sfz(CString sfz)
{
    return 0;
}

现在确定返回值以及其代表的状态
0.身份证号正常
1.身份证号为18位数字(最后一位可以是x,支持大小写)
2.对不起,您的年龄不在合法的职工年龄范围
3.身份证号码错误
由于我懒得写这么复杂的身份证号码的判断逻辑,所以一下我简略判断,我只是判断一下长度,其他的在此不做判断,请读者自行补充代码。

int Cmyapp_1Dlg::check_sfz(CString sfz)
{
    //此处代码不完整,需自行补充,对于不同的错误,应该返回不同的状态值,例如,年龄不满18岁,应该返回2,身份证号码错误,应返回3
    int length = sfz.GetLength();
    if (length != 18)
    {
        return 1;
    }
    return 0;
}

对于“开始考试” 按钮添加调用验证身份证格式的代码,如下:


void Cmyapp_1Dlg::OnBnClickedBeginTest()
{
    // TODO: 在此添加控件通知处理程序代码

    //这里需要判断用户输入的准考证信息,身份证信息是否合法,暂时先省略

    //判断用户的准考证号
    UpdateData(TRUE);
    int zkz_result = check_zkz(et_zkz);
    if (zkz_result == 1)
    {
        MessageBox(_T("准考证为11位数字"));
        return;
    }

    int sfz_result = check_sfz(et_sfz);
    if (sfz_result == 1)
    {
        MessageBox(_T("身份证号为18位数字(最后一位可以是x,支持大小写)"));
        return;
    }
    if (sfz_result == 2)
    {
        MessageBox(_T("对不起,您的年龄不在合法的职工年龄范围"));
        return;
    }
    if (sfz_result == 3)
    {
        MessageBox(_T("身份证号码错误"));
        return;
    }

    btn_begin_test.EnableWindow(FALSE);//让按钮无法点击
    SetTimer(1,1000,NULL);//设置一个定时器,这里有三个参数,第一个参数:定时器id,第二个参数:时间间隔,第三个参数:需要触发的函数,当值为NULL交给系统处理


}

效果演示:
这里写图片描述

目前考题这个下拉框的内容为空,往里面添加01 02 03 三个选项
方式如下:
找到下拉框的属性页面
这里写图片描述

在Data里面添加 01;02;03
Type 选择:Drop List
完成以后效果如下:
这里写图片描述

2.5 集成pdflib模块

最后生成的pdf效果图:
这里写图片描述

由pdflib模块提供支持。
pdflib模块包含:pdflib.h pdflib.lib pdflib.dll

在项目的文件目录加入三个文件,如图
这里写图片描述

这里写图片描述

把pdflib.h 文件加入到项目,拖进去
这里写图片描述

把三个文件同时加到工程目录的debug目录

这里写图片描述
添加引用的头文件

#include "stdafx.h"
#include "myapp_1.h"
#include "myapp_1Dlg.h"
#include "afxdialogex.h"
#include "pdflib.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#pragma comment(lib, "PDFLib.lib")

添加了以下两行

#include "pdflib.h"
#pragma comment(lib, "PDFLib.lib")

开始写调用代码:

这里写图片描述

图片上的参数列表显示的并不完整:
完整的参数列表如下:
CString zkz, CString sfz, double zhun_que_lv, double da_zi_su_du, double cheng_ji, CString nei_rong

生成的函数如下:

void Cmyapp_1Dlg::write_pdf(CString zkz, CString sfz, double zhun_que_lv, double da_zi_su_du, double cheng_ji, CString nei_rong)
{
}

在此之前先给,文字内容输入框绑定一个变量
这里写图片描述

这里写图片描述

变量名设置为:et_content
否则会影响后面调用。

myapp_1Dlg.cpp 添加头文件:


#include <string>

#include <stdio.h>

using namespace std;

添加完之后是这样的

#include "stdafx.h"
#include "myapp_1.h"
#include "myapp_1Dlg.h"
#include "afxdialogex.h"
#include "pdflib.h"
#include <string>

#include <stdio.h>

using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#pragma comment(lib, "PDFLib.lib")

是时候往里面添加写pdf的代码了

复写write_pdf函数

复写完是这样的:

void Cmyapp_1Dlg::write_pdf(CString zkz, CString sfz, double zhun_que_lv, double da_zi_su_du, double cheng_ji, CString nei_rong)
{


    remove("成绩单.pdf");

    PDF *p;

    if ((p = PDF_new()) == (PDF *) 0){
        printf("Couldn't create PDFlib object (out of memory)!/n");
        return;
    }

    PDF_TRY(p) {
        /* This means we must check return values of load_font() etc. */
        //PDF_set_parameter(p, "errorpolicy", "return");

        if (PDF_begin_document(p, "./成绩单.pdf", 0, "") == -1) {
            printf("Error: %s/n", PDF_get_errmsg(p));
            return;
        }

        /* This line is required to avoid problems on Japanese systems */
        PDF_set_parameter(p, "hypertextencoding", "host");
        //PDF_set_parameter(p, "fakebold", "true");



        PDF_set_info(p, "Creator", "hello.c");
        PDF_set_info(p, "Author", "Thomas Merz");
        PDF_set_info(p, "Title", "Hello, world (C)!");

        PDF_begin_page_ext(p, a4_width, a4_height, "");

        int font_song = PDF_findfont(p,"STSong-Light", "GB-EUC-H", 0);
        PDF_setfont(p,font_song, 12);
        PDF_set_text_pos(p,50, a4_height - 50);



        USES_CONVERSION;
        string s = T2A(( zkz.GetBuffer()));
        s = "准考证号:" + s;
        PDF_show(p,s.c_str());

        PDF_set_text_pos(p,50, a4_height - 65);
        s = T2A(( sfz.GetBuffer()));
        s = "身份证号:" + s;
        PDF_show(p,s.c_str());

        PDF_setfont(p,font_song, 8);
        PDF_set_text_pos(p,50, a4_height - 85);
        CString cs;
        cs.Format(L"您打字的正确率是%f,速度是%f字/分钟,本次考试的成绩是%f分",zhun_que_lv,da_zi_su_du,cheng_ji);
        s = T2A(cs.GetBuffer());
        PDF_show(p,s.c_str());

        PDF_setfont(p,font_song, 8);
        PDF_set_text_pos(p,50, a4_height - 100);
        s="以下是您本次考试录入的内容:";
        PDF_show(p,s.c_str());

        PDF_set_text_pos(p,50, a4_height - 130);
        s = T2A(nei_rong.GetBuffer());
        PDF_show(p,s.c_str());
        //PDF_setcolor(p, "fill", "cmyk", 1, 0,0,0);
        //PDF_rect(p, 250,250, 250, 250);




        //PDF_fill(p);

        PDF_end_page_ext(p, "");
        PDF_end_document(p, "");
    }

    PDF_CATCH(p) {
        printf("PDFlib exception occurred in sample:/n");
        printf("[%d] %s: %s/n",
            PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p));
        CString cs;
        cs.Format(L"[%d] %s: %s/n",
            PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p));
        PDF_delete(p);

        return;
    }

    PDF_delete(p);
    return;
}

调用上面的代码
这里写图片描述

双击 提交 按钮:

加入一下两行

UpdateData(TRUE);
write_pdf(et_zkz,et_sfz,100.0,88.0,100,et_content);

最后应该是差不多这个样子的(函数名可能有些不同 ,这个不重要)

void Cmyapp_1Dlg::OnBnClickedOk()
{
    // TODO: 在此添加控件通知处理程序代码
    //CDialogEx::OnOK();
    UpdateData(TRUE);
    write_pdf(et_zkz,et_sfz,100.0,88.0,100,et_content);
}

点提交之后生成的pdf界面展示:
这里写图片描述

目前的代码还存在的一些问题:

  • 调用函数 write_pdf(et_zkz,et_sfz,100.0,88.0,100,et_content); 里面的打字速度,正确率,成绩等没有经过计算就传进去了一个默认值,实际中需要根据用户的输入来进行计算。(读者自己可以完善此功能)
  • 没有读取配置文件的信息,也没有写此模块,后期可能会加入此功能。

bug修复记录:

  • void Cmyapp_1Dlg::OnTimer(UINT_PTR nIDEvent)存在一个bug,描述:在按下开始考试按钮时,下面的输入框无法输入内容。目前已经修复。
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值