⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlgnewcard.cpp

📁 通用的餐饮收费系统:其主要技术是通过计算机串口与IC卡相关设备进行数据交互.
💻 CPP
字号:
// DlgNewCard.cpp : implementation file
//

#include "stdafx.h"
#include "ShoolCard.h"
#include "DlgNewCard.h"

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

#include "Global.h"
#include "Config.h"

extern CConfig gConfig;
extern CDatabase gDatabase;

/////////////////////////////////////////////////////////////////////////////
// CDlgNewCard dialog


CDlgNewCard::CDlgNewCard(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgNewCard::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDlgNewCard)
	m_Money = 0.0f;
	m_StudentId = _T("");
	//}}AFX_DATA_INIT
}


void CDlgNewCard::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgNewCard)
	DDX_Control(pDX, IDC_BUTTON_NEW_CARD, m_btnNewCard);
	DDX_Control(pDX, IDC_LIST1, m_ListBox);
	DDX_Text(pDX, IDC_EDIT_MONEY, m_Money);
	DDX_Text(pDX, IDC_EDIT_STUDENT_ID, m_StudentId);
	DDX_Control(pDX, IDC_MSCOMM1, m_ComPort);
	//}}AFX_DATA_MAP
}




BEGIN_MESSAGE_MAP(CDlgNewCard, CDialog)
	//{{AFX_MSG_MAP(CDlgNewCard)
	ON_WM_CLOSE()
	ON_WM_SHOWWINDOW()
	ON_BN_CLICKED(IDC_BUTTON_QUERY, OnButtonQuery)
	ON_NOTIFY(NM_CLICK, IDC_LIST1, OnClickList1)
	ON_BN_CLICKED(IDC_BUTTON_NEW_CARD, OnButtonNewCard)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgNewCard message handlers

void CDlgNewCard::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	if(m_Card.IsOpen()) m_Card.Close();
	if(m_CardUser.IsOpen()) m_Card.Close();
	if(m_CardLookupMaxId.IsOpen()) m_Card.Close();
	//关闭串口
	if(m_ComPort.GetPortOpen()) m_ComPort.SetPortOpen(false);
	CDialog::OnClose();
}

//====================私有函数=======================
bool CDlgNewCard::IsCardInWriter()
{
	CByteArray mByteAry;
	CByteArray mIn;

    //构造上位机报文
	mByteAry.SetSize(4);
	mByteAry.SetAt(0,0x0f);
	mByteAry.SetAt(1,0xf0);
	mByteAry.SetAt(2,0x01);//读物理卡号
	//计算报文的校验位
	mByteAry.SetAt(3,CGlobal::CalCheck(&mByteAry,0,2));

    //发读物理卡号命令
	m_ComPort.SetOutput(COleVariant(mByteAry));
    //等待读卡机的应答信息
    Sleep(60);
	//读串口信息
	if (m_ComPort.GetInBufferCount() != 13) 
	{
		return false;
	}
    //将下位机报文接受到缓冲区
	mIn.SetSize(13);
    COleVariant olearray = m_ComPort.GetInput();
	for(int i=0;i<13;i++)
		mIn.SetAt(i,((unsigned char *)olearray.parray->pvData)[i]);
	//检查校验位
	if(!CGlobal::IsArrayValid(&mIn)) return false;
    //从应答的报文中解析卡号
	if ((mIn[3] == 0xff) && (mIn[4] == 0xff) && (mIn[5] == 0xff) &&
       (mIn[6] == 0xff) && (mIn[7] == 0xff) && (mIn[8] == 0xff) &&
       (mIn[9] == 0xff) && (mIn[10] == 0xff))
	   return true;

	return false;
}

short int CDlgNewCard::WriteCard(CString ACardNo)
{
	CByteArray mByteAry;
	CByteArray mIn;

    //构造上位机报文
	mByteAry.SetSize(13);
	mByteAry.SetAt(0,0x0f);
	mByteAry.SetAt(1,0xf0);
	mByteAry.SetAt(2,0x03);//写命令
	mByteAry.SetAt(3,0x01);//第1区
    
	//卡号数据写入
	mByteAry.SetAt(4,ACardNo.GetAt(0));
	mByteAry.SetAt(5,ACardNo.GetAt(1));
	mByteAry.SetAt(6,ACardNo.GetAt(2));
	mByteAry.SetAt(7,ACardNo.GetAt(3));
	mByteAry.SetAt(8,ACardNo.GetAt(4));
		
	mByteAry.SetAt(9,0x00);//保留
	mByteAry.SetAt(10,0x00);//保留
	mByteAry.SetAt(11,0xff);//数据区以FF结尾
	//计算报文的校验位
	mByteAry.SetAt(12,CGlobal::CalCheck(&mByteAry,0,12));

    //发读第一区的命令
	m_ComPort.SetOutput(COleVariant(mByteAry));
    //等待读卡机的应答信息
    Sleep(60);
	//读串口信息
	if (m_ComPort.GetInBufferCount() != 6) 
	{
		return -2;
	}
    //将下位机报文接受到缓冲区
	mIn.SetSize(13);
    COleVariant olearray = m_ComPort.GetInput();
	for(int i=0;i<13;i++)
		mIn.SetAt(i,((unsigned char *)olearray.parray->pvData)[i]);
	//检查校验位
	if(!CGlobal::IsArrayValid(&mIn) || (mIn.GetAt(4) != 0x0f)) 
		return -3;

    return 1;
	
}

short int CDlgNewCard::WriteTime(CTime ATime)
{

	BYTE year1,year2,month1,month2,day1,day2;
    DecodeInt(ATime.GetYear(),year1,year2);
	DecodeInt(ATime.GetMonth(),month1,month2);
	DecodeInt(ATime.GetDay(),day1,day2);
	

	//======================串口操作==================
	CByteArray mByteAry;
	CByteArray mIn;

        //构造上位机报文
	mByteAry.SetSize(13);
	mByteAry.SetAt(0,0x0f);
	mByteAry.SetAt(1,0xf0);
	mByteAry.SetAt(2,0x03);//写命令
	mByteAry.SetAt(3,0x01);//第2区
    
	//时间数据写入
	mByteAry.SetAt(4,year1);
	mByteAry.SetAt(5,year2);
	mByteAry.SetAt(6,month1);
	mByteAry.SetAt(7,month2);
	mByteAry.SetAt(8,day1);
	mByteAry.SetAt(9,day2);
	mByteAry.SetAt(10,ATime.GetDayOfWeek());
	
	mByteAry.SetAt(11,0xff);//数据区以FF结尾
	//计算报文的校验位
	mByteAry.SetAt(12,CGlobal::CalCheck(&mByteAry,0,12));

    //发读第一区的命令
	m_ComPort.SetOutput(COleVariant(mByteAry));
    //等待读卡机的应答信息
    Sleep(60);
	//读串口信息
	if (m_ComPort.GetInBufferCount() != 6) 
	{
		return -2;
	}
    //将下位机报文接受到缓冲区
	mIn.SetSize(13);
    COleVariant olearray = m_ComPort.GetInput();
	for(int i=0;i<13;i++)
		mIn.SetAt(i,((unsigned char *)olearray.parray->pvData)[i]);
	//检查校验位
	if(!CGlobal::IsArrayValid(&mIn) || (mIn.GetAt(4) != 0x0f)) 
		return -3;
    
	return 1;
}

short int CDlgNewCard::WriteMoney(float AMoney)
{
    //======================串口操作==================
	CByteArray mByteAry;
	CByteArray mIn;

	//构造上位机报文
	mByteAry.SetSize(13);
	mByteAry.SetAt(0,0x0f);
	mByteAry.SetAt(1,0xf0);
	mByteAry.SetAt(2,0x03);//写命令
	mByteAry.SetAt(3,0x03);//第3区

    char chMoney[6];
	//转换为整数
	int nMoney = AMoney * 100;
	//取出每一位
    for(int i=0 ;i<6 ;i++)
	{
		chMoney[i] = nMoney % 10;
		nMoney = nMoney /10;
	}
	
	//卡中的金额数据写入
	mByteAry.SetAt(4,CGlobal::Encrypt(chMoney[0]));
	mByteAry.SetAt(5,CGlobal::Encrypt(chMoney[1]));
	mByteAry.SetAt(6,CGlobal::Encrypt(chMoney[2]));
	mByteAry.SetAt(7,CGlobal::Encrypt(chMoney[3]));
	mByteAry.SetAt(8,CGlobal::Encrypt(chMoney[4]));
	mByteAry.SetAt(9,CGlobal::Encrypt(chMoney[5]));
	
	mByteAry.SetAt(10,CGlobal::CalMoneyCheck(&mByteAry,4,9));
	mByteAry.SetAt(11,0xff);//数据区以FF结尾
	//计算报文的校验位
	mByteAry.SetAt(12,CGlobal::CalCheck(&mByteAry,0,12));

    //发读第一区的命令
	m_ComPort.SetOutput(COleVariant(mByteAry));
    //等待读卡机的应答信息
    Sleep(60);
	//读串口信息
	if (m_ComPort.GetInBufferCount() != 6) 
	{
		return -2;
	}
    //将下位机报文接受到缓冲区
	mIn.SetSize(13);
    COleVariant olearray = m_ComPort.GetInput();
	for(i=0;i<13;i++)
		mIn.SetAt(i,((unsigned char *)olearray.parray->pvData)[i]);
	//检查校验位
	if(!CGlobal::IsArrayValid(&mIn) || (mIn.GetAt(4) != 0x0f)) 
		return -3;

    return 1;

}

CString CDlgNewCard::GetNewCardId()
{
    if(!m_CardLookupMaxId.IsOpen())
	{
	    m_CardLookupMaxId.m_strSort = "card_id";
		m_CardLookupMaxId.Open();
	}
	else 
	    m_CardLookupMaxId.Requery();
	if(m_CardLookupMaxId.IsEOF()&&m_CardLookupMaxId.IsBOF())
        return _T("00001");
	else 
	{
	    m_CardLookupMaxId.MoveLast();
	    return _IntToStr5(atoi(LPCTSTR(m_CardLookupMaxId.m_card_id))+1);
	}
}


void CDlgNewCard::OnShowWindow(BOOL bShow, UINT nStatus) 
{
	CDialog::OnShowWindow(bShow, nStatus);
	
	// TODO: Add your message handler code here
	//打开串口	
	if (!m_ComPort.GetPortOpen())
	{
	    try
		{
			short int nComPort = CGlobal::ComStrToInt(gConfig.Port);
		    m_ComPort.SetCommPort(nComPort);
			CString strSetting = gConfig.Speed + ','
				                +gConfig.CheckBit.GetAt(0) + ','
								+gConfig.DataBit + ','
								+gConfig.StopBit;
			m_ComPort.SetSettings(strSetting);
			m_ComPort.SetPortOpen(true);
		}
		catch(CException ee)
		{
			MessageBox("串口不能打开,请检查串口的配置!");
			return;
		}
	}
    //不显示任何学生
	InitListView();
    OnButtonQuery();
}

void CDlgNewCard::DecodeInt(int A, BYTE &B1, BYTE &B2)
{
    B1 = A % 10;
	B2 = (A / 10) % 10; 
}



void CDlgNewCard::OnButtonQuery() 
{
	UpdateData(CON2VAR);
    CString str;
	str = "user_id = '" + m_StudentId + "'";
	m_CardUser.m_strFilter = str;
	if(m_CardUser.IsOpen()) m_CardUser.Close();
	if(!m_CardUser.Open()) 
	{
		MessageBox("数据表不能打卡,数据库错误!");
		return;
	}
	//利用后台数据更新用户界面
	FillListView();
	ConfigButtons();	
	m_CardUser.Close();
}

void CDlgNewCard::FillListView()
{
    ASSERT(m_CardUser.IsOpen());
	//删除老的显示数据
	m_ListBox.DeleteAllItems();
	//没有数据需要显示
	if(m_CardUser.GetRecordCount() <= 0) return ;

	int nRow = 0;
	m_CardUser.MoveFirst();
	while(!m_CardUser.IsEOF())
	{
		m_ListBox.InsertItem(nRow,"");
		m_ListBox.SetItemText(nRow,0,m_CardUser.m_user_id);
		m_ListBox.SetItemText(nRow,1,m_CardUser.m_name);
		CString str;
		str.Format("%2d",m_CardUser.m_age);
		m_ListBox.SetItemText(nRow,2,str);
        m_ListBox.SetItemText(nRow,3,m_CardUser.m_address);

		nRow++;
		m_CardUser.MoveNext();
	}
}

void CDlgNewCard::InitListView()
{
    m_ListBox.InsertColumn(0,"学号");
	m_ListBox.InsertColumn(1,"姓名");
	m_ListBox.InsertColumn(2,"年龄");
	m_ListBox.InsertColumn(3,"联系地址");

	m_ListBox.SetColumnWidth(0,90);
	m_ListBox.SetColumnWidth(1,150);
	m_ListBox.SetColumnWidth(2,120);
	m_ListBox.SetColumnWidth(3,250);
}

void CDlgNewCard::ConfigButtons()
{
    int nIndex = m_ListBox.GetNextItem(-1, LVNI_SELECTED); 
	if(nIndex == -1)
	{
	    m_btnNewCard.EnableWindow(false);
	}   
	else 
	{
	    m_btnNewCard.EnableWindow(true);   
	}
}

void CDlgNewCard::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	ConfigButtons();
	*pResult = 0;
}

void CDlgNewCard::OnButtonNewCard() 
{
	// TODO: Add your control notification handler code here
    double mMoney;
	CString mCardId;
	CTime mTime;
	short int nRet;
    
    //获取界面数据
	UpdateData(CON2VAR);
    //测试新卡是否放入读卡器
	if(IsCardInWriter())
	{
	    MessageBox("系统检查不到银卡,请将一张新卡放入写卡器!");
		return;
	}
    //在数据库中读取可用的新卡号
    mCardId = GetNewCardId();
    //在数据库中读取可用的新卡号失败
    if(mCardId == "#####")
    {
        MessageBox("数据库中数据错误,请立即和开发方联系!");
		::PostQuitMessage(0);
        return;
	}
    //向数据库中写入数据
    mTime = CTime::GetCurrentTime();
    //设置数据库,开始事务
    m_Card.m_pDatabase = &gDatabase;
    gDatabase.BeginTrans();

	if(!m_Card.IsOpen()) m_Card.Open();
	m_Card.AddNew();
	m_Card.m_card_id = mCardId;
	m_Card.m_user_id = m_StudentId;
	m_Card.m_create_date = mTime;
	m_Card.m_money = m_Money;
	//设置状态为未挂失状态
	m_Card.m_state = "0";
	//提交
	m_Card.Update();

    nRet = WriteCard(mCardId);
    if(nRet < 0) goto Error;
    nRet = WriteTime(mTime);
    if(nRet < 0) goto Error;
    nRet = WriteMoney(mMoney);
    if(nRet < 0) goto Error;

    gDatabase.CommitTrans();
	m_Card.Close();
    MessageBox("新卡办理成功!");
    return;
//错误处理
Error:
    switch(nRet)
	{
	    case -1: MessageBox("写卡器端口打开异常,请检查系统配着!");break;
        case -2: MessageBox("写卡器没有正常应答,请检查写卡器连接是否正确!");break;
        case -3: MessageBox("写卡器读写校验错误,请重试!");break;
	    default: MessageBox("不能确定的读写错误,请重试!");
	}
    gDatabase.Rollback();
	m_Card.Close();
}

void CDlgNewCard::OnDestroy() 
{
    if(m_Card.IsOpen()) m_Card.Close();
	if(m_CardUser.IsOpen()) m_CardUser.Close();
	//关闭串口
	if(m_ComPort.GetPortOpen()) m_ComPort.SetPortOpen(false);
	
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	
}

CString CDlgNewCard::_IntToStr5(int AInt)
{
	CString strRet;
	strRet.Format("%d",AInt);
	switch(strRet.GetLength())
	{
	    case 1:strRet = "0000" + strRet;
			break;
        case 2:strRet = "000" + strRet;
			break;
		case 3:strRet = "00" + strRet;
			break;
		case 4:strRet = "0" + strRet;
			break;
	}
	return strRet;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -