基于VC++的车辆定位和实时管理系统设计与实现

目 录

引言 1
1 系统概述 1
1.1 系统开发背景 1
1.2 基于GPS和电子地图的车辆管理系统开发前景和意义 2
2 系统需求分析 2
2.1 车辆管理 3
2.1.1 车辆资料管理 4
2.1.2 派/收车管理 4
2.1.3 终端管理 5
2.2 权限管理 5
2.2.1 系统用户管理 5
2.2.2 角色管理 5
2.2.3 权限管理 6
2.2.4 系统用户对应的角色的管理 6
2.2.5 角色对应车队的管理 6
2.3 地图 6
2.3.1 GPS功能 7
2.3.2 地图编辑 8
3 相关技术和开发平台 9
3.1 Microsoft Visual C++ 6.0 9
3.2 SQL Server 2000 9
3.3 SOGOU地图API 9
3.4 C/S 结构 9
3.5 系统所需配置简介 10
3.6 系统开发所需关键技术 10
3.6.1 MFC 跟JS 的通信 10
3.6.2 JS 跟MFC 的通信 11
4 总体设计 12
4.1 系统设计目的 12
4.2 系统总体构架 12
4.3 平台系统结构 15
4.4 数据库设计 16
4.4.1 车辆管理 17
4.4.2 权限管理 21
4.4.3 地图 23
5 系统功能模块的技术实现 25
5.1 登录 25
5.2 车辆管理 26
5.2.1 车辆资料管理 27
5.2.2 派车/收车管理 28
5.2.3 终端管理 30
5.3 权限管理 32
5.3.1 保存权限 32
5.4 地图功能 33
5.4.1 地图初始化 34
5.4.2 GPS功能 34
5.4.3 地图编辑 37
6 系统测试 38
6.1 测试目的 38
6.2 开发与测试环境 38
6.3 测试计划 38
6.4 测试过程 39
6.4.1 登录模块的测试 40
6.4.2 地图模块的测试 40
6.4.3 轨迹回放模块的测试 41
6.4.4 动态跟踪模块的测试 42
6.4.5 数据分析模块的测试 42
6.5 测试结论 43
7 出错处理设计 43
7.1 出错输出信息 43
7.2 出错处理对策 44
8 安全保密设计 44
结论 44
致 谢 45
【参考文献】 46
具体的需求如下:
车辆管理
车辆管理是车辆管理系统最基本的需求之一,车辆管理包括车辆资料管理、派车/收车管理、终端管理等功能,用户可通过这些功能来完成车辆的日常管理和一些基础资料的管理,比如查询、新增、修改、删除和派车/收车等。车辆管理必须设计得尽可能的易用、简单而又不失实用性。为了满足日常管理的一些需求,目前在该功能需求中包括三个子功能:车辆资料管理、派车/收车管理、终端管理。
2.1.1车辆资料管理
车辆资料管理主要提供的是对车辆基本资料的管理,包括车辆信息查询、查看、新增、修改、删除等一些基本功能。不过要想使用这些功能,必须管理员分配这些权限方能使用,如果没有使用这些功能的权限是无法执行这些功能的。车辆资料的内容有:车辆编码、车牌号、品牌型号、车辆类型、所属部门、车辆状态、驾驶员、购买日期、登记日期、终端号码,需要实现的功能有:
新增车辆资料
修改车辆资料
删除车辆资料
查看选中的某车辆资料
根据条件查询车辆资料
打印(可选项)
2.1.2派/收车管理
车辆管理系统一般都提供有派车/收车的功能,本系统同样也不能例外。用户可通过派车/收车管理的功能来分配车辆的使用和收回已经派出的车辆,根据情况来分配车辆可提高车辆的使用效率,减少费用。因为用户有时候需求查阅历史派车记录或收车记录,所以在该功能里面,必须能够根据用户所提供的查询条件来查阅这些记录,同时,为了能够方便用户收车,也要提供一个查阅未收车辆的查阅的功能,这样,用户就能够通过该功能来轻松查阅未收车辆和很方便的对未收车辆进行收车。
因为在派车的时候可能会对同一辆车进行多次派车,而这些派车之间也可能会产生时间冲突,所以在派车的时候要先对该车辆的使用时间进行检测,如果与其它的派车时间产生冲突就要提示用户冲突的时间,这样就方便用户改变派车时间或使用其它没有冲突的车辆。
派车/收车记录所维护的信息有:车辆编码、车牌号、驾驶员、驾驶员电话、用车人、用车人电话、用车部门、用车时间、估计返程时间、出发地点、途经地点、目的地点、用车原因、派车人、审批人、登记日期、是否已收车、收车人、备注。
如果想要使用这些功能的用户必须具备这些权限。需要实现的功能有:
派车
收车
根据条件查询历史派车记录
根据条件查询历史收车记录
根据条件查询未收记录
2.1.3终端管理
因为车辆要与地图和GPS结合起来,所以必须要在汽车上安装一个定位地理位置并将位置信息发送到服务器上的终端。
在终端管理功能模块中,用户可对终端信息进行新增、修改、删除,同时也可指定查询信息对终端进行查询操作。终端中的一些动态信息会根据终端返回到服务器的数据进行实时更新,比如终端对应车辆所处的实时地理位置信息和车辆的实时速度等。终端信息的内容有:终端号、终端名、当前地址、证书、终端电话、权限、是否在线、所属车队、用户组、备注、登记时间。
使用该功能的用户必须具备该权限。需要实现的功能有:
新增终端资料
修改终端资料
删除终端资料
根据条件查询终端资料
权限管理
为了让系统用户的操作在一个可控的安全范围之内,本系统将权限管理作为一个基础功能需求,权限管理包括了系统用户管理、角色管理、和权限管理。有权限的用户可通过该功能来给用户分配角色、给角色分配权限或给角色分配车队(该角色有权限管理的车队),同时也可对用户、角色进行管理,即:权限管理不单纯的是权限管理,同时也包括了系统用户、系统角色的管理,这些都被隶属于权限管理之中。
2.2.1系统用户管理
系统用户是登入系统的凭证,进入系统后只能使用该用户有权限使用的功能。为了提高系统的可控性以及实用性,本系统提供了系统用户管理,使得系统管理员可对系统用户进行有效的一致性管理。系统用户所维护的信息有:id、名称、密码、性别、生日、地址、籍贯、证件号码、部门、入职时间、手机号码、家庭号码、创建时间(注册时间)、创建者ID。其中密码需要使用MD5算法加密。需要实现的功能有
新增用户资料
修改用户资料
删除用户资料
根据条件查询用户资料
2.2.2角色管理
为了使系统中与用户对应的权限易于管理,系统引进了角色管理,每个角色对应不同的权限,给需要给用户分配权限时,只需给用户分配角色即可,一个用户可对应多个角色,他真正的权限就是他所对应角色的权限的并集。需要实现的功能有:
新增角色
删除角色
2.2.3权限管理
系统中有很多的功能,但为了使系统更安全、稳定、可控,并不是每个系统用户都能使用所有的这些功能,而权限是决定系统用户是否能够使用某个系统功能的标志,所以在本系统中,用户能够使用的功能都是根据权限来分配,而用户的权限都是根据他所对应的角色来获取,这就产生了两个映射:用户 角色;角色 权限。需要实现的功能:
给角色添加权限
给角色删除权限
保存角色—权限的对应关系
2.2.4系统用户对应的角色的管理
为了方便用户权限的管理,如果需要给用户分配权限,只需要给用户分配对应的角色即可。一个用户可对应多个角色,他的权限就是用户所对应角色的权限的并集。这种权限管理方式大大提高了权限分配的方便性,也大大减少了系统管理员的工作量。需要实现的功能有:
给用户分配角色
给用户删除角色
保存用户—角色的对应关系
2.2.5角色对应车队的管理
在系统中可能会存在多个车队,而为了让管理划分得更清晰明了,也不是每个系统用户都能对所有的车队进行管理。给用户分配车队也是基于角色来分配的,我们只需要给角色分配该角色有权限管理的车辆,然后按照需要来给用户分配对应的角色即可。用户所能管理的车队就是该用户对应的角色有权限管理的车队的并集,换句话说,我们只要能获取到该用户的角色,就知道该用户能管理哪些车队。需要实现的功能有:
给角色添加车队
给角色删除车队
保存角色—车队对应关系
地图
地图功能是本系统的新特性。
提供地图除了可以让用户对车辆管理有一个全新的体验外,还大大地提高了系统的实用性,系统管理员可借助该功能让管理变得更实体化,对于车辆的监控变得更加明显、可靠。本系统将车辆与地图和GPS有效地结为一体,将车辆的实时位置在地图上显示出来,让用户能够在地图上实时监控车辆的实时位置信息和速度信息,同时还可以在地图上添加标注、绘制路线、绘制区域,也可以将绘制的区域分配给指定的车辆,规定该车辆不能进区域或不能出区域,大大地提高了监控的方便性和系统的实用性。在该功能模块中主要包含了以下的子功能模块:
GPS功能
地图编辑
具备的功能需求如下:
2.3.1GPS功能
要想在地图上定位车辆的位置信息,必须要将GPS跟车辆关联起来。GPS功能就是将GPS终端跟车辆结合起来的一个功能,因为一个终端跟一辆车是一对一的关系,所以只要通过终端将位置信息发送到服务器就可定位到地图上的一辆车。
同时为了更好地对车辆进行管理,在该功能模块中还必须要提供对某个车辆进行动态跟踪、数据统计和轨迹回放的功能,通过这几个功能,用户可以很方便地了解车辆的历史状态信息的实时状态信息。在本功能模块中需要实现的功能列表如下
查找车辆:可以按车牌号、编号、驾驶员、终端号、终端名等模糊信息查找,只要按确定后会自动转到该车在地图上的位置,同时在车辆信息列表栏中也会选中。
列表车辆:在树型列表KH 按照车队分类来列出用户有权限管理的车辆,列表车辆时显示车辆在线/不在线的标志,在树型列表选中车辆时,在地图上显示车辆和车辆详细信息,地图以车辆为中心。
查看车辆信息:可以查看地图上看到的车辆信息,包括运行状态和车辆详细信息。
车辆信息查询:可以实时查询在地图上看见的任何一辆车子的静态信息,无需去车辆详细信息管理栏去找,并可了解当前车辆的运行状况。
车辆跟踪定位:实时性地对车辆的情况进行跟踪,双击车辆信息列表栏的车牌号,自动转到该车在地图上的位置。
动态跟踪:新建窗口对选定的车辆进行实时监控,显示车辆轨迹,地图以车辆为中心,也就是地图会随着车辆的移动而移动。
轨迹回放:可以随时查看每台车辆任意时间段行驶轨迹图,方便直观地展示某车在某时间段内的行驶轨迹,能在回放结束之后选择重新回放或重新选择时间段来回放。半年内的数据均可调出进行回话,方便管理人员对车辆进行系统的监控和检查。
数据统计:可根据时间区段和设定的速度阀值绘制速度曲线图,非常直观地显示车辆工作过程中的速度变化,对超速和车辆的平稳驾驶性一目了然,便于管理从员了解车辆的违规情况以及驾驶平稳性的情况。列表超速信息,双击超速信息会转到地图上相应的超速位置,并绘制出超速的轨迹。还能够列表出失去监控车辆的统计列表并打印。
2.3.2地图编辑
为了方便用户的使用,提高地图的实用性,本系统增加了地图编辑的功能,在该功能模块中,用户可根据需要在地图上添加自己的标注、绘制区域,并可选择将之保存到数据库中,以后登录时都会在地图上显示该用户对应的标注和路线,同时用户也可对这些标注和路线进行管理,比如重命名、删除等。区域是针对整个系统来管理而不是针对用户来管理的的,即一个用户绘制了一个区域并保存到数据库中时,其他的系统用户同样能对该区域进行分配、管理。在本功能模块中要实现以下几个子功能模块以满足用户的需求:
搜索:可通过输入地名来进行地图搜索。
刷新地图:可对地图进行刷新。刷新后系统会重新从数据库中查询标注、路线、区域、车辆终端来在地图上标注出来。相当于对车辆终端进行重新定位。
添加标注:用户可根据需要在地图上添加自己的标注,比如为了方便查找某个地方,可在该地方加上一个标注,以后可通过该标注找到该地方。标注可以选择保存到数据库中,如果不保存到数据库中下次登录时将不会在地图上显示标注。每次登录时系统都会从数据库查询出属于该登录用户的标注来在地图上显示出来
绘制路线:当有的一些道路比较偏僻地图上没有或者不详细,可自己进行绘制并给该道路命名。绘制好的路线同样可以保存到数据库中,如果不保存到数据库中下次登录时将不会在地图上显示出来。每次登录时系统都会从数据库查询出属于该登录用户的路线来在地图上显示出来
绘制区域:可以在地图上绘制区域并用于分配给车辆,并选择是进报警区域(某车辆进入该区域时报警)还是出报警区域(某车辆出了该区域时报警),绘制的区域可选择保存到数据库中,不保存到数据库中的区域无效,下次登录时也不会在地图上显示。每个系统用户,只要具有使用地图功能的权限,都可对区域进行修改、删除等编辑操作,因为区域是针对于整个系统的。
给车辆终端分配/删除报警区域:如果需要给车辆终端分配报警区域时要使用该功能。通过列表出来的区域和车辆终端,本文转载自http://www.biyezuopin.vip/onews.asp?id=14552可以把指定区域分配给指定的车辆终端,分配时需要能够选择该区域是进报警区域还是出报警区域,需要能够同时给一个车队或者一个车辆的终端分配一个或多个报警区域。删除报警区域跟分配报警区域差不多,也需要能够同时删除一个车队或一个车辆的一个或多个报警区域。
双击区域时跳转到地图对应位置上:为了方便查看区域或某车辆终端对应的报警区域,双击区域进可自动跳转到地图的对应位置上。

// ManageCarDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CarManage.h"
#include "ManageCarDlg.h"
#include "InOutOpt.h"
#include "InOutDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CManageCarDlg dialog

CManageCarDlg::CManageCarDlg(CString &purviewCoding, CWnd* pParent /*=NULL*/)
	: CSizingDialog(CManageCarDlg::IDD, pParent), purviewCoding(purviewCoding)
{
}

void CManageCarDlg::DoDataExchange(CDataExchange* pDX)
{
	CSizingDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CManageCarDlg)
	DDX_Control(pDX, IDC_ENDTIME, m_endctrl);
	DDX_Control(pDX, IDC_STARTTIME, m_startctrl);
	DDX_Control(pDX, IDC_LIST1, m_list);
	DDX_Text(pDX, IDC_EDIT2, m_dept);
	DDX_DateTimeCtrl(pDX, IDC_STARTTIME, m_starttime);
	DDX_DateTimeCtrl(pDX, IDC_ENDTIME, m_endtime);
	DDX_Text(pDX, IDC_DEST, m_dest);
	DDX_Text(pDX, IDC_EDIT4, m_user);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CManageCarDlg, CSizingDialog)
	//{{AFX_MSG_MAP(CManageCarDlg)
	ON_BN_CLICKED(IDC_BUTTON1, OnSearch)
	ON_BN_CLICKED(IDC_BUTTON4, OnClear)
	ON_BN_CLICKED(IDC_RADIO2, OnInRecord)
	ON_BN_CLICKED(IDC_RADIO3, OnUnInRecord)
	ON_BN_CLICKED(IDC_RADIO1, OnOutRecord)
	ON_BN_CLICKED(IDC_BUTTON2, OnOutCar)
	ON_BN_CLICKED(IDC_BUTTON3, OnBackCar)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CManageCarDlg message handlers

BOOL CManageCarDlg::OnInitDialog() 
{
	CSizingDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	// 以下这段代码可解决无法设置对话框无边框、大小不可变的问题
	DWORD dwStyle = GetStyle(); //获取旧样式  
    DWORD dwNewStyle = WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU | WS_CHILD | 
		WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;  
    dwNewStyle&=dwStyle; //按位与将旧样式去掉  
    SetWindowLong(this->m_hWnd, GWL_STYLE, dwNewStyle); //设置成新的样式 1073741892 
    DWORD dwExStyle = GetExStyle(); //获取旧扩展样式  
    DWORD dwNewExStyle = WS_EX_LEFT |
		WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
    dwNewExStyle&=dwExStyle; //按位与将旧扩展样式去掉
    SetWindowLong(this->m_hWnd, GWL_EXSTYLE, dwNewExStyle); //设置新的扩展样式  
	//告诉windows:我的样式改变了,窗口位置和大小保持原来不变!
    SetWindowPos(NULL, 0, 0, 0, 0,
		SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

	this->SetWindowText("管理收/派车");
	m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT); // 设置列表选中一整行
	m_list.SetBkColor(RGB(223, 232, 238)); // 设置背景颜色

	AddCtrl(); // 添加自动适应控件
	((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);

	m_ioOpt = new CInOutOpt();

	// 设置两个时间控件的初始时间,如果是 DEBUG 版本
	// 默认初始时间为当前时间,但如果是 RELEASE 版本
	// 默认的初始时间却不是当前时间,这是为什么啊
	CTime curTime = CTime::GetCurrentTime();
	m_startctrl.SetTime(&curTime);
	m_endctrl.SetTime(&curTime);

	ModuleSetup(purviewCoding);
	InitList();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CManageCarDlg::AddCtrl()
{
	int woc;
	HWND hwndChild = ::GetWindow(m_hWnd, GW_CHILD);

	while (hwndChild) {
		woc = ::GetDlgCtrlID(hwndChild);
		this->AddControl(woc, _T("RXY"));

		hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
	}
}

// ModuleSetup() : 根据权限设置模块的功能是否可用
void CManageCarDlg::ModuleSetup(CString &purviewCoding)
{
	// 如果编码长度为零,直接返回,不再进行功能模块设置
	// 这会产生一个问题,即当编码为空的时候,所有的都将会默认为可用的
	CWnd* pWnd = this->GetWindow(GW_CHILD);
    char cClassName[255]={0}; 
    while(pWnd)
    {   
		if (purviewCoding.GetLength() < 1) {
			return;
		}

		//得到控件的类名,主要有Edit,Button,Static等等
        GetClassName(pWnd->GetSafeHwnd(),cClassName,255);
		
		if (strcmp(cClassName, "Button") == 0) {
			if (((CButton *)pWnd)->GetButtonStyle() == 
				BS_PUSHBUTTON) {
				// 如果控件对应的编码为1,为可用,否则不可用
				if (purviewCoding.GetAt(0) == '1') {
					pWnd->EnableWindow();
				} else {
					pWnd->EnableWindow(FALSE);
				}
				purviewCoding.Delete(0); // 删除遍历过的编码
			}
		}

        pWnd = pWnd->GetWindow(GW_HWNDNEXT); // 下一控件
     }
}

// InitList() : 初始化列表
void CManageCarDlg::InitList()
{
	m_list.InsertColumn(0, _T("编码"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(1, _T("车牌号"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(2, _T("驾驶员"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(3, _T("驾驶员电话"), LVCFMT_LEFT, 100);
	m_list.InsertColumn(4, _T("用车人"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(5, _T("用车人电话"), LVCFMT_LEFT, 100);
	m_list.InsertColumn(6, _T("用车部门"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(7, _T("用车时间"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(8, _T("估计返程时间"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(9, _T("出发地点"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(10, _T("途经地点"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(11, _T("目的地点"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(12, _T("用车原因"), LVCFMT_LEFT, 100);
	m_list.InsertColumn(13, _T("派车人"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(14, _T("审批人"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(15, _T("登记日期"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(16, _T("是否已收车"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(17, _T("收车人"), LVCFMT_LEFT, 80);
	m_list.InsertColumn(18, _T("备注"), LVCFMT_LEFT, 100);

	_RecordsetPtr res;
	m_ioOpt->QueryRecord(res);

	FillList(res);
}

// FillList() : 往列表中填充内容
// res : 查询数据库得到的记录集
void CManageCarDlg::FillList(_RecordsetPtr &res)
{
	UINT row;

	m_list.DeleteAllItems();

	row = 0;
	while (!res->adoEOF)
	{
		// 设置前 7 个列的内容
		m_list.InsertItem(row, (CString)res->GetCollect("coding").bstrVal);
		for (int col = 1; col < 7; ++col) {
			if (VT_NULL != res->GetCollect(long(col)).vt) {
				CString tmp = res->GetCollect(long(col)).bstrVal;
				m_list.SetItemText(row, col, 
					(CString)res->GetCollect(long(col)).bstrVal);
			} else {
				m_list.SetItemText(row, col, "");
			}
		}

		// 设置 7,8 列的时间内容
		if (VT_NULL != res->GetCollect("usetime").vt) {
			_variant_t date = res->GetCollect("usetime");
			m_list.SetItemText(row, col++, COleDateTime(date).Format("%Y-%m-%d"));
		} else {
			m_list.SetItemText(row, col++, "");
		}

		if (VT_NULL != res->GetCollect("backtime").vt) {
			_variant_t date = res->GetCollect("backtime");
			m_list.SetItemText(row, col, COleDateTime(date).Format("%Y-%m-%d"));
		} else {
			m_list.SetItemText(row, col, "");
		}

		// 设置后面列的内容
		for (col = 9; col < 19; ++col) {
			if (col != 15) {
				if (VT_NULL != res->GetCollect(long(col)).vt) {
					m_list.SetItemText(row, col,
						(CString)res->GetCollect(long(col)).bstrVal);
				} else {
					m_list.SetItemText(row, col, "");
				}
			} else { // 如果是登记时间列,则读取时间
				if (VT_NULL != res->GetCollect("entertime").vt) {
					_variant_t date = res->GetCollect("entertime");
					m_list.SetItemText(row, col,
						COleDateTime(date).Format("%Y-%m-%d"));
				} else {
					m_list.SetItemText(row, col, "");
				}
			}
		}

		res->MoveNext();
		++row;
	}
}

// AddToLstTail() : 将一条记录添加到列表尾部
// content : 记录内容
void CManageCarDlg::AddToLstTail(std::vector<std::string> &content)
{
	std::vector<std::string>::iterator begin = content.begin();
	std::vector<std::string>::iterator end   = content.end();
	UINT row = m_list.GetItemCount();

	m_list.InsertItem(row, (*begin).data());
	++begin;

	for (int col = 1; begin != end; ++begin, ++col) {
		m_list.SetItemText(row, col, (*begin).data());
	}
}

// UpdateLstRow() : 更新某行记录的内容
// nIndex : 指定的某行
// content : 将要更新的内容
void CManageCarDlg::UpdateLstRow(const int &nIndex,
								 std::vector<std::string> &content)
{
	std::vector<std::string>::iterator begin = content.begin();
	std::vector<std::string>::iterator end   = content.end();
	begin += 2;

	for (int col = 2; begin != end; ++begin, ++col) {
		m_list.SetItemText(nIndex, col, (*begin).data());
	}
}

// GetIndexContent() : 获取某行的内容
// nIndex : 指定的一行 
// content : 保存某行的内容
void CManageCarDlg::GetIndexContent(const UINT &nIndex,
									std::vector<std::string> &content)
{
	CString text;
	CHeaderCtrl *m_pHeader = m_list.GetHeaderCtrl();
	UINT count = m_pHeader->GetItemCount();

	for (int col = 0; col < count; ++col) {
		if (col == 16 || col == 17) {
			continue;
		}
		content.push_back(m_list.GetItemText(nIndex, col).GetBuffer(0));
	}
}

void CManageCarDlg::OnSearch() 
{
	// TODO: Add your control notification handler code here
	CString searchText = "";
	unsigned char count = 0;
	CString time;
	_RecordsetPtr res;

	UpdateData();

	// 获取控件内容
	time = m_starttime.Format("%Y-%m-%d"); // 起始时间
	if (!time.IsEmpty()) {
		searchText += " usetime>='" + time + "' and";
		++count;
	}
	time = m_endtime.Format("%Y-%m-%d"); // 结束时间
	if (!time.IsEmpty()) {
		searchText += " usetime<='" + time + "' and";
		++count;
	}

	if (!m_dest.IsEmpty()) { // 目的地
		searchText += " destination like '%" + m_dest + "%' and";
		++count;
	}
	if (!m_user.IsEmpty()) { // 用车人
		searchText += " [user] like '%" + m_user + "%' and";
		++count;
	}
	if (!m_dept.IsEmpty()) { // 部门
		searchText += " dept in (select id from depts where \
						name like '%" + m_dept + "%') and";
		++count;
	}

	if (count > 0) { // 如果用户已经输入查询条件,查询
		searchText.Delete(searchText.GetLength() - 4, 4);
		m_ioOpt->QueryRecord(res, (LPCTSTR)searchText, m_radSelect); // 查询
	} else { // 如果用户没有输入任何查询条件,则刷新列表
		m_ioOpt->QueryRecord(res);
	}
	
	FillList(res);
}

void CManageCarDlg::OnClear() 
{
	// TODO: Add your control notification handler code here
	m_dest.Empty();
	m_user.Empty();
	m_dept.Empty();

	UpdateData(FALSE);
}

void CManageCarDlg::OnOutRecord() 
{
	// TODO: Add your control notification handler code here
	if (m_radSelect == 0) { // 如果不改变选择,直接返回不做处理
		return;
	}

	_RecordsetPtr res;

	m_radSelect = 0;
	GetDlgItem(IDC_BUTTON3)->EnableWindow(TRUE);

	m_ioOpt->QueryRecord(res);
	FillList(res);
}

void CManageCarDlg::OnInRecord() 
{
	// TODO: Add your control notification handler code here
	if (m_radSelect == 1) {
		return;
	}

	_RecordsetPtr res;
	
	m_radSelect = 1;
	GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE);

	m_ioOpt->QueryRecord(res, TRUE);
	FillList(res);
}

void CManageCarDlg::OnUnInRecord() 
{
	// TODO: Add your control notification handler code here
	if (m_radSelect == 2) {
		return;
	}

	_RecordsetPtr res;

	m_radSelect = 2;
	GetDlgItem(IDC_BUTTON3)->EnableWindow(TRUE);

	m_ioOpt->QueryRecord(res, FALSE);
	FillList(res);
}


void CManageCarDlg::OnOutCar() 
{
	// TODO: Add your control notification handler code here
	CInOutDlg ioDlg(TRUE);

	if (ioDlg.DoModal() == IDOK) {
		std::vector<std::string> content =
			ioDlg.GetContent();

		this->AddToLstTail(content);
	}
}

void CManageCarDlg::OnBackCar() 
{
	// TODO: Add your control notification handler code here
	UINT nIndex = m_list.GetNextItem(-1, LVNI_SELECTED);
	if (nIndex == -1) {
		MessageBox("没有选中任何项", "提示信息", MB_ICONWARNING);
		return;
	}

	// 先检测该车辆是否已经收车
	CString backstatus = m_list.GetItemText(nIndex, 16);
	if (backstatus.Compare("已收") == 0) {
		MessageBox("车辆号为: " + m_list.GetItemText(nIndex, 1) +
					" 的车辆已收车", "提示信息", MB_OK);
		return;
	}	

	std::vector<std::string> content;

	GetIndexContent(nIndex, content);
	CInOutDlg ioDlg(FALSE, content);

	if (ioDlg.DoModal() == IDOK) {
		content = ioDlg.GetContent();
		UpdateLstRow(nIndex, content);
	}
}

BOOL CManageCarDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
		OnSearch();
		return TRUE;
	}
	if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)   
		return TRUE;

	return CSizingDialog::PreTranslateMessage(pMsg);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


版权声明:本文为newlw原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。