这是一个关于超市综合管理的一个系统其中包括两大部分,主要前台与后台,前台的主要功能就是具有传统收银台的收银功能,还具有队与超市会员信息管理的的功能,除增删查改之外,还增加了积分查询等功能,而后台是管理员操作界面,后台管理员的主要职责是队于员工信息进行增删查改,对于各类商品的进行管理其中包括(新商品入库、清除过期商品、修改商品信息、查询商品信息以及收银报表的查看)等功能。
系统分为前台与后台,我们将项目细分为两个方面,首先我们要做一个有界面的系统,界面界面主要有登录界面、收银界面、管理员界面。登录界面,而设计数据存储的方面我们将会采用MySQL数据库进行存储。
由于我们之前所了解的C++知识很多偏向理论,而且偏向于后台服务器相关的内容,所以对于是实现界面的方面不是很了解,所以老师给我们推荐了一个外部库(DuiLib),通过这套库我们可以轻松实现一些简单界面的操作。但是由于引进的是一个外部库,所以我们要自行对库文件进行编译,我们的
项目主要开发环境是VS2017,对以前编译器功能的配置进行增加才能进行编译,在编译成功后会生成两个文件
在编译完成后就需要生成的文件和DuiLib放到目标文件下,然后就是对于数据库的链接,在项目属性中选择链接和编译中找到数据库安装的路径,然后对于将include和lib文件分别添加到项目中,基本环境搭建就完成了。
首先对于这给项目我们需要给我们的数据库中添加四张表,作为各方面数据的存储,便于后面的管理。其次我们需要做三个窗口,分别是登录窗口、管理员窗口以及收银台窗口。各个窗口实现的功能分别是,登录窗口实现区别前台收银人员与后台管理人进行区分,当不同身份的进行登录,进入的接面和功能都不同。管理员窗口需要实现连接数据库对人员商品信息进行各种操作,收银界面主要是对于商品销售的操作,可以连接数据库对商品相关的表进行操作,还有对于会员信息的表格,对于会员信息进行增删查改的操作,还要将其更新到销售记录中。
登录数据库,创建cash数据库,将四张表格储存在其中。
这就是存在数据库中的四张表。
由于我们以后很多操作都是界面操作,所以对于数据库我们不能数据一旦变动必须打开数据进行更新,所以我们要将数据库的增删查改操作进行封装,这样我们就可以在系统界面无论是人员信息或者商品信息进行了一些操作时就还可以让数据库实时更新。
首先我们先简历一个头文件MySQL.h对于要实现的功能进行罗列:
MySQL.h
#pragma once
#include
#include
#include
#include
using namespace std;
class MySQL
{
public:
MySQL();
bool ConnectMySQL(const char* host, const char* user, const char* passward, const char* dbName);
~MySQL();
bool Insert(const string& strSQL);
bool UpDate(const string& strSQL);
bool Delete(const string& strSQL);
vector> Select(const string& strSQL);
private:
MYSQL* _mySQL;
};
我们要实现数据库的基本操作增删查改,所以罗列了以上四个功能Insert(插入)、UpData(更新)、Delete(删除)、Select(查找),通过构建一个cpp文件用mysql.h头文件中封装好的函数对于这些功能进行实现;
MySQL.cpp
#include "MySQL.h"
#include
using namespace std;
MySQL::MySQL()
{
_mySQL = mysql_init(nullptr);
}
bool MySQL:: ConnectMySQL(const char* host, const char* user, const char* passward, const char* dbName)
{
if (!mysql_real_connect(_mySQL, host, user, passward, dbName, 3306, nullptr, 0))
{
cout << "数据库连接失败" << endl;
return false;
}
mysql_query(_mySQL, "set names 'gbk'");
return true;
}
vector> MySQL::Select(const string& strSQL)
{
vector> vvRet;
if (mysql_query(_mySQL, strSQL.c_str()))
{
// SQL命令响应失败
cout << mysql_error(_mySQL) << endl;
return vvRet;
}
// 获取查询的记录集
MYSQL_RES * mySQLRes = mysql_store_result(_mySQL);
if (nullptr == mySQLRes)
{
cout << mysql_error(_mySQL) << endl;
return vvRet;
}
// 获取记录中有多少个字段
int itemCount = mysql_num_fields(mySQLRes);
MYSQL_ROW mysqlRow;
while (mysqlRow = mysql_fetch_row(mySQLRes))
{
// 已经获取到一条记录
vector vItem;
for (size_t i = 0; i < itemCount; ++i)
{
vItem.push_back(mysqlRow[i]);
}
vvRet.push_back(vItem);
}
mysql_free_result(mySQLRes);
return vvRet;
}
bool MySQL::Insert(const string& strSQL)
{
if (mysql_query(_mySQL, strSQL.c_str()))
{
// SQL命令响应失败
cout << mysql_error(_mySQL) << endl;
return false;
}
return true;
}
bool MySQL::UpDate(const string& strSQL)
{
if (mysql_query(_mySQL, strSQL.c_str()))
{
// SQL命令响应失败
cout << mysql_error(_mySQL) << endl;
return false;
}
return true;
}
MySQL::~MySQL()
{
mysql_close(_mySQL);
}
以上代码核心就是运用mysql_query函数,这个函数有两个参数,第一个是数据库操作句柄MYSQL类型可以通过句柄来对数据库进行操作,第二个是我们所构造的SQL语句,就是我们自己数据库中对表进行的操作。
关于DuiLib
Duilib 界面库使用介绍 一、Duilib 简介 Duilib 是以 DirectUI 为技术原理开发的一款轻量级 Windows 桌面 UI 库,具有入门简单,使用方便等特点,在国内吸引了不少的开发者。其开发原型为国外大神viksoe 的 http://www.viksoe.dk/code/windowless1.htm 文章中提供的源码,国内开源前辈以此为基础:修正 Bug、优化程序结构、提高稳定性和易用性,是一款功能强大,使用方便的界面库。 界面库使用 XML 来描述界面风格,界面布局,可以很方便的构建高效,绚丽的,非常易于扩展的界面。从而很好的将界面和逻辑分离,同时易于实现各种超炫的界面效果如换色,换肤,透明等。 Duilib 界面库的出现解决了使用传统 MFC 界面库开发软件不美观、界面细节处理不好、使用硬编码、开发效率低下、生成程序体积大等问题。
具体使用介绍: https://www.cnblogs.com/Alberl/p/3354459.htmlhttps://www.cnblogs.com/Alberl/p/3354459.html
为什么选择这个库?
1.开源
2.界面制作有特有工具
3.可以用比较简单的方式生成美观的界面
4.开发效率高
登录窗口
该界面中有两个输入框和三个按钮组成,输入框分别是员工姓名和密码,对应数据库表中name和password,三个按钮分别是登录、最小化窗口、关闭窗口。由于提供了设计工具所以对于界面所有的地方都可以进行个性化设计这是我设计的登录界面,用设计工具将接麦你设计完成后,进行保存会生成一个.xml文件,后面在程序中会用到这个文件,所以一定要将它的路径记住。
与数据库操作相同我们先创建一个头文件将需要的操作罗列出来
LogLnWnd.h`
class LogInWnd : public WindowImplBase
{
public:
LogInWnd(MySQL* pMySQL);
virtual void Notify(TNotifyUI& msg);
void LogIn();
protected:
// WindowImplBase:提供的三个纯虚函数
// xml文件对应的目录
virtual CDuiString GetSkinFolder();
// xml文件的名字
virtual CDuiString GetSkinFile();
// 窗口类的名字:在注册窗口时必须提供
virtual LPCTSTR GetWindowClassName(void) const;
MySQL* m_pMySQL;
};
我们通过Notify这个函数对通过DuiLIb提供的TNotifyUI& msg这个变量对鼠标点击的信息进行捕获,这个窗口主要的功能就是登录,通过捕获按钮的被鼠标点击的名字进行相应操作具体实现在LogInWnd.cpp
#include “MainWnd.h”
#include “CashierWnd.h”
// xml文件对应的目录
CDuiString LogInWnd::GetSkinFolder()
{
return _T("");
}
// xml文件的名字
CDuiString LogInWnd::GetSkinFile()
{
return _T(“loginWnd.xml”);
}
// 窗口类的名字:在注册窗口时必须提供
LPCTSTR LogInWnd::GetWindowClassName(void) const
{
return _T(“LogInWnd”);
}
void LogInWnd::Notify(TNotifyUI& msg)
{
CDuiString strName = msg.pSender->GetName();
if (msg.sType == _T(“click”))
{
if (strName == _T(“BTN_MIN”))
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
//SendMessage(WM_SYSCOMMAND,SW_MINIMIZE);
else if (strName == _T(“BTN_CLOSE”))
Close();
else if (strName == _T(“BTN_LOGIN”))
LogIn();
}
}
void LogInWnd::LogIn()
{
// 从编辑框中获取用户名以及密码
CEditUI* pEditUserName = (CEditUI*)m_PaintManager.FindControl(_T(“EDIT_USER_NAME”));
CDuiString strUserName = pEditUserName->GetText();
CEditUI* pEditPassword = (CEditUI*)m_PaintManager.FindControl(_T("EDIT_USER_PASSWORD"));
CDuiString strUserPassWord = pEditPassword->GetText();
if (strUserName.IsEmpty())
{
MessageBox(m_hWnd, _T("请输入用户名"), _T("Cashier"), IDOK);
return;
}
if (strUserPassWord.IsEmpty())
{
MessageBox(m_hWnd, _T("请输入用户密码"), _T("Cashier"), IDOK);
return;
}
// 查询数据库,检测该用户是否存在
string strSQL("select * from employee where Name = '");
// ascII UNICODE
strSQL += UnicodeToANSI(strUserName);
strSQL += "';";
vector> vRet = m_pMySQL->Select(strSQL);
if (vRet.empty())
{
MessageBox(m_hWnd, _T("用户名错误"), _T("Caisher"), IDOK);
return;
}
string userpassward = UnicodeToANSI(strUserPassWord);
if (userpassward != vRet[0][4])
{
MessageBox(m_hWnd, _T("用户密码错误"), _T("Caisher"), IDOK);
return;
}
// 隐藏登录窗口
ShowWindow(false);
if (vRet[0][5] == "管理员")
{
// 创建主窗口
MainWnd mianWnd(m_pMySQL);
mianWnd.Create(NULL, _T("MainWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
mianWnd.CenterWindow();
mianWnd.ShowModal();
}
else
{
// 创建主窗口
CCashierWnd mianWnd(m_pMySQL);
mianWnd.Create(NULL, _T("CashierWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
mianWnd.CenterWindow();
mianWnd.ShowModal();
}}
通过我们对于每个按钮名字都进行了命名,所以我们可以实现对每个按钮的点击进行捕获,有两个可以重复只用就是关闭和最小化,对于登陆我们需要对人员身份进行区分,如果登录人员是管理员就需要打开管理员的界面,如果登录信息是售货员就需打开售货员的界面,所以我们就需要对数据库的数据进行查找通过返回的字符串型二维数组进行身份比较,得出登录人员的身份。
管理员界面
这是一个由若干输入框和下拉表,以及对个按钮实现,由于管理员进行的操作十分复杂,所以我们的界面也更加复杂,这个界面可以实现对所有人员的信息进行增删查改,并且将查到的结果输出到界面上,还可以对
商品进行的信息进行更改,最后对于所有界面上的操作如果涉及到超市人员或者商品信息的变动我们都将会把它放入我们的数据库中。
首先我们还是创建一个头文件对所需要的功能及进行罗列和函数生明Mainwnd.h`
#pragma once
#include "Common.h"
class MainWnd : public WindowImplBase
{
public:
MainWnd(MySQL* pMySQL);
~MainWnd();
virtual void Notify(TNotifyUI& msg);
protected:
// WindowImplBase:提供的三个纯虚函数
// xml文件对应的目录
virtual CDuiString GetSkinFolder();
// xml文件的名字
virtual CDuiString GetSkinFile();
// 窗口类的名字:在注册窗口时必须提供
virtual LPCTSTR GetWindowClassName(void) const;
void SelectEmployeeInfo();
void DeleteEmployeeInfo();
void InsertEmployeeInfo();
private:
MySQL* m_pMySQL;
};
首先前面三个函数是继承自父类,所以前面相同,我们需要实现的使对人员信息的增删查改,所以我们需要建立一个cpp文件来对函数进行实现Maind.cpp
#include "MainWnd.h"
MainWnd::MainWnd(MySQL* pMySQL)
: m_pMySQL(pMySQL)
{
}
MainWnd::~MainWnd()
{
}
// xml文件对应的目录
CDuiString MainWnd::GetSkinFolder()
{
return _T("");
}
// xml文件的名字
CDuiString MainWnd::GetSkinFile()
{
return _T("MainWnd.xml");
}
// 窗口类的名字:在注册窗口时必须提供
LPCTSTR MainWnd::GetWindowClassName(void) const
{
return _T("MainWnd");
}
void MainWnd::Notify(TNotifyUI& msg)
{
CDuiString strName = msg.pSender->GetName();
if (msg.sType == _T("click"))
{
if (strName == _T("BTN_CLOSE"))
PostQuitMessage(0); //Close();
else if (strName == _T("BTN_MIN"))
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
else if (strName == _T("BTN_SELECT"))
SelectEmployeeInfo();
else if (strName == _T("BTN_INSERT"))
InsertEmployeeInfo();
else if (strName == _T("BTN_UPDATE"))
MessageBox(NULL, _T("UpdateBTN"), _T("Cashier"), IDOK);
else if (strName == _T("BTN_DELETE"))
DeleteEmployeeInfo();
else if (strName == _T("BTN_SELL_RECORD"))
MessageBox(NULL, _T("SELLBTN"), _T("Cashier"), IDOK);
}
else if (msg.sType == _T("selectchanged"))
{
CTabLayoutUI* pTab = (CTabLayoutUI*)m_PaintManager.FindControl(_T("tablayout"));
if (strName == _T("OPTION_EMPLOYEE"))
pTab->SelectItem(0);
else
pTab->SelectItem(1);
}
else if (msg.sType == _T("windowinit"))
{
// 窗口在创建期间,将一些空间初始化
CComboBoxUI* pGender = (CComboBoxUI*)m_PaintManager.FindControl(_T("usergender"));
pGender->SelectItem(0);
CComboBoxUI* pPosition = (CComboBoxUI*)m_PaintManager.FindControl(_T("position"));
pGender->SelectItem(0);
CComboBoxUI* pSelect = (CComboBoxUI*)m_PaintManager.FindControl(_T("COMOB_SELECT"));
pSelect->SelectItem(0);
}
}
void MainWnd::SelectEmployeeInfo()
{
string strSQL("select * from employee");
CComboBoxUI* pCombo = (CComboBoxUI*)m_PaintManager.FindControl(_T("COMOB_SELECT"));
CDuiString strStyle = pCombo->GetText();
if (strStyle == _T("无"))
strSQL += ";";
else if (strStyle == _T("名字"))
{
strSQL += " where Name = '";
CDuiString strName = ((CEditUI*)m_PaintManager.FindControl(_T("username")))->GetText();
if (strName.IsEmpty())
{
MessageBox(m_hWnd, _T("请输入查询用户的名字"), _T("Cashier"), IDOK);
return;
}
strSQL += UnicodeToANSI(strName);
strSQL += "';";
}
else if (strStyle == _T("性别"))
;
else if (strStyle == _T("薪资"))
;
vector> vRet = m_pMySQL->Select(strSQL);
if (vRet.empty())
return;
CListUI* pListUI = (CListUI*)m_PaintManager.FindControl(_T("ListEmployeeInfo"));
pListUI->RemoveAll();
for (size_t i = 0; i < vRet.size(); ++i)
{
vector& strItem = vRet[i];
CListTextElementUI* pData = new CListTextElementUI;
pData->SetAttribute(_T("align"), _T("center"));
pListUI->Add(pData);
// 名字
pData->SetText(0, ANSIToUnicode(strItem[1]));
pData->SetText(1, ANSIToUnicode(strItem[2]));
pData->SetText(2, ANSIToUnicode(strItem[3]));
pData->SetText(3, ANSIToUnicode(strItem[5]));
pData->SetText(4, ANSIToUnicode(strItem[6]));
pData->SetText(5, ANSIToUnicode(strItem[7]));
}
}
void MainWnd::DeleteEmployeeInfo()
{
// 获取当前选中
CListUI* pListUI = (CListUI*)m_PaintManager.FindControl(_T("ListEmployeeInfo"));
int lineNo = pListUI->GetCurSel();
CListTextElementUI* pRow = (CListTextElementUI*)pListUI->GetItemAt(lineNo);
// 从数据库中将该员工的信息删除
// 构造SQL命令;
string strSQL("delete ");
CDuiString strName = pRow->GetText(0);
// 从数据库中将该条记录删除
//m_pMySQL->Delete(strSQL);
// 从List中移除
pListUI->RemoveAt(lineNo);
}
void MainWnd::InsertEmployeeInfo()
{
// 从界面中获取员工信息
CDuiString strName = ((CEditUI*)m_PaintManager.FindControl(_T("username")))->GetText();
CDuiString strGender = ((CComboBoxUI*)m_PaintManager.FindControl(_T("usergender")))->GetText();
CDuiString strBirthday = ((CEditUI*)m_PaintManager.FindControl(_T("userbirthday")))->GetText();
CDuiString strPosition = ((CComboBoxUI*)m_PaintManager.FindControl(_T("position")))->GetText();
CDuiString strTel = ((CEditUI*)m_PaintManager.FindControl(_T("telphone")))->GetText();
CDuiString strSalary = ((CEditUI*)m_PaintManager.FindControl(_T("salary")))->GetText();
CListUI* pListUI = (CListUI*)m_PaintManager.FindControl(_T("ListEmployeeInfo"));
char szCount[32] = { 0 };
_itoa(pListUI->GetCount()+1, szCount, 10);
// 构造SQL命令
string strSQL("insert into employee values(");
strSQL += szCount;
strSQL += ",'";
strSQL += UnicodeToANSI(strName);
strSQL += "','";
strSQL += UnicodeToANSI(strGender);
strSQL += "','";
strSQL += UnicodeToANSI(strBirthday);
strSQL += "','000000','";
strSQL += UnicodeToANSI(strPosition);
strSQL += "','";
strSQL += UnicodeToANSI(strTel);
strSQL += "','";
strSQL += UnicodeToANSI(strSalary);
strSQL += "');";
// 响应SQL命令
m_pMySQL->Insert(strSQL);
// 将该员工的信息插入到List
CListTextElementUI* pItem = new CListTextElementUI;
pListUI->Add(pItem);
pItem->SetText(0, strName);
pItem->SetText(1, strGender);
pItem->SetText(2, strBirthday);
pItem->SetText(3, strPosition);
pItem->SetText(4, strTel);
pItem->SetText(5, strSalary);
}
这段代码前三个函数是对于窗口以及初始化,后面利用构建SQL语句来实现对于数据库的操作,这个函数的主体还是一个按钮操作,通过鼠标对于不同按钮的点击就可以实现执行不同操作,后面的函数实现,就只操作的具体实现步骤首先讲插入
1.在界面的输入框输入的内容进行捕获:CDuiString strName = ((CEditUI*)m_PaintManager.FindControl(_T(“username”)))->GetText();
2.对下拉链表的内容进行捕获CDuiString strGender = ((CComboBoxUI*)m_PaintManager.FindControl(_T(“usergender”)))->GetText();
3.对于点击消息进行捕获: CDuiString strName = msg.pSender->GetName();
通过捕获来自不同按钮的捕获我们就可以实现响应不同的消息,并将响应消息与数据库结合起来,从而达到前台与有台同步数据
售货员界面
这个界面主要工鞥能就是收银和对于会员信息的管理,界面设置主要是,一个输入框和部分按钮组成分别用作输入和查询,还有出售商品的计价操作商品数量的操作,我们首先将这些操作进行声明,创建一个头文件
CashierWnd.h
#pragma once
#include "Common.h"
class CCashierWnd : public WindowImplBase
{
public:
CCashierWnd(MySQL* pMySQL);
~CCashierWnd();
virtual void Notify(TNotifyUI& msg);
protected:
// WindowImplBase:提供的三个纯虚函数
// xml文件对应的目录
virtual CDuiString GetSkinFolder();
// xml文件的名字
virtual CDuiString GetSkinFile();
// 窗口类的名字:在注册窗口时必须提供
virtual LPCTSTR GetWindowClassName(void) const;
void SelectGoods();
void AddGoodsCount();
void SubGoodsCount();
void InsertGoodsList();
void CancelOrder();
void CommitOrder();
private:
MySQL* m_pMySQL;
};
我们创建一个cpp文件将这些操作进行具体实现
#include "CashierWnd.h"
CCashierWnd::CCashierWnd(MySQL* pMySQL)
: m_pMySQL(pMySQL)
{
}
CCashierWnd::~CCashierWnd()
{
}
// xml文件对应的目录
CDuiString CCashierWnd::GetSkinFolder()
{
return _T("");
}
// xml文件的名字
CDuiString CCashierWnd::GetSkinFile()
{
return _T("CashierManage.xml");
}
// 窗口类的名字:在注册窗口时必须提供
LPCTSTR CCashierWnd::GetWindowClassName(void) const
{
return _T("CashierWnd");
}
void CCashierWnd::Notify(TNotifyUI& msg)
{
CDuiString strName = msg.pSender->GetName();
if (msg.sType == _T("click"))
{
if (strName == _T("BTN_CLOSE"))
Close();
else if (strName == _T("BTN_MIN"))
::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
else if (strName == _T("BTN_ADD"))
AddGoodsCount();
else if (strName == _T("BTN_SUB"))
SubGoodsCount();
else if (strName == _T("BTN_SELECT"))
SelectGoods();
else if (strName == _T("BTN_COMMIT"))
CommitOrder();
else if (strName == _T("BTN_CANCEL"))
CancelOrder();
else if (strName == _T("BTN_OK"))
InsertGoodsList();
}
}
void CCashierWnd::SelectGoods()
{
// 1. 获取商品名称
CDuiString strGoodsName = ((CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_NAME")))->GetText();
// 2. 构造SQL语句,到数据库中查此商品
string strSQL("select * from goodstable where GoodsName = '");
strSQL += UnicodeToANSI(strGoodsName);
strSQL += "';";
vector> vRet = m_pMySQL->Select(strSQL);
if (vRet.empty())
{
MessageBox(m_hWnd, _T("暂无此商品"), _T("Cashier"), IDOK);
return;
}
// 3. 将商品剩余个数显示到界面编辑框中
((CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_LEFT")))->SetText(ANSIToUnicode(vRet[0][7]));
}
void CCashierWnd::AddGoodsCount()
{
// 库存减1
CEditUI* pGoodsLeft = (CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_LEFT"));
CDuiString strLeft = pGoodsLeft->GetText();
if (strLeft == _T("0"))
{
MessageBox(m_hWnd, _T("库存量不足"), _T("Cashier"), IDOK);
return;
}
int count = 0;
count = atoi(UnicodeToANSI(strLeft).c_str());
--count;
strLeft.Format(_T("%d"), count);
pGoodsLeft->SetText(strLeft);
// 商品个数加1
CEditUI* pGoodsCount = (CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_COUNT"));
CDuiString strCount = pGoodsCount->GetText();
count = atoi(UnicodeToANSI(strCount).c_str());
++count;
strCount.Format(_T("%d"), count);
pGoodsCount->SetText(strCount);
}
void CCashierWnd::SubGoodsCount()
{
// 商品个数减去1
CEditUI* pGoodsCount = (CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_COUNT"));
CDuiString strCount = pGoodsCount->GetText();
if (strCount == _T("0"))
{
MessageBox(m_hWnd, _T("商品个数已经为0!!!"), _T("Cashier"), IDOK);
return;
}
int count = atoi(UnicodeToANSI(strCount).c_str());
--count;
strCount.Format(_T("%d"), count);
pGoodsCount->SetText(strCount);
// 库存减1
CEditUI* pGoodsLeft = (CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_LEFT"));
CDuiString strLeft = pGoodsLeft->GetText();
count = atoi(UnicodeToANSI(strLeft).c_str());
++count;
strLeft.Format(_T("%d"), count);
pGoodsLeft->SetText(strLeft);
}
void CCashierWnd::InsertGoodsList()
{
// 1. 从界面获取商品名称以及购买的数量
CDuiString strGoodsName = ((CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_NAME")))->GetText();
CEditUI* pGoodsCount = (CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_COUNT"));
CDuiString strCount = pGoodsCount->GetText();
// 2. 从数据库中获取商品的价格以及计量单位
string strSQL("select * from goodstable where GoodsName = '");
strSQL += UnicodeToANSI(strGoodsName);
strSQL += "';";
vector> vRet = m_pMySQL->Select(strSQL);
// 3. 合计价格
int count = atoi(UnicodeToANSI(strCount).c_str());
double price = atof(vRet[0][5].c_str());
price = count*price;
CDuiString strPrice;
strPrice.Format(_T("%lf"), price);
// 4. 将信息更新到list中
CListTextElementUI* pItem = new CListTextElementUI;
CListUI* pList = (CListUI*)m_PaintManager.FindControl(_T("OrderList"));
pList->Add(pItem);
pItem->SetText(0, strGoodsName);
pItem->SetText(1, ANSIToUnicode(vRet[0][5]));
pItem->SetText(2, strCount);
pItem->SetText(3, ANSIToUnicode(vRet[0][6]));
pItem->SetText(4, strPrice);
// 5. 将商品数量以及名称的编辑框清0
((CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_NAME")))->SetText(_T(""));
((CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_LEFT")))->SetText(_T(""));
((CEditUI*)m_PaintManager.FindControl(_T("EDIT_GOODS_COUNT")))->SetText(_T("0"));
}
void CCashierWnd::CancelOrder()
{
// 清空所有商品
CListUI* pList = (CListUI*)m_PaintManager.FindControl(_T("OrderList"));
pList->RemoveAll();
}
void CCashierWnd::CommitOrder()
{
// 1. 合计总价格
CListUI* pList = (CListUI*)m_PaintManager.FindControl(_T("OrderList"));
int count = pList->GetCount();
double totalPrice = 0;
for (int i = 0; i < count; ++i)
{
CListTextElementUI* pItem = (CListTextElementUI*)pList->GetItemAt(i);
CDuiString strPrice = pItem->GetText(4);
totalPrice += atof(UnicodeToANSI(strPrice).c_str());
}
CDuiString strTotalPrice;
strTotalPrice.Format(_T("%.02lf"), totalPrice);
((CEditUI*)m_PaintManager.FindControl(_T("EDIT_TOTAL")))->SetText(strTotalPrice);
// 2. 更新商品的数据库
for (int i = 0; i < count; ++i)
{
CListTextElementUI* pItem = (CListTextElementUI*)pList->GetItemAt(i);
CDuiString strCount = pItem->GetText(2);
string strSQL("update goodstable set Inventory='");
strSQL += UnicodeToANSI(strCount);
strSQL += "';";
m_pMySQL->UpDate(strSQL);
}
// 3. 插入本次销售记录
}
这个界面的所有操作与管理员界面的操作类似,有按钮等构成,通过按钮相应不同的功能,调用不同的函数,也是通过构造SQL语句,操作数据库,从而达到改变数据库内部的数据
这个项目就像是,一栋房子,不仅有大框架还有一些基本每个头文件都会用到的函数我们来创建一个头文件来包含它
common.h
#pragma once
#include
using namespace DuiLib;
#include "MySQL.h"
#ifdef _DEBUG
# ifdef _UNICODE
# pragma comment(lib, "DuiLib_ud.lib")
# else
# pragma comment(lib, "DuiLib_d.lib")
# endif
#else
# ifdef _UNICODE
# pragma comment(lib, "DuiLib_u.lib")
# else
# pragma comment(lib, "DuiLib.lib")
# endif
#endif
string UnicodeToANSI(const CDuiString& str);
CDuiString ANSIToUnicode(const string& str);
UnicodeToANSI将编码格式转化为二进制,ANSIToUnicode是将编码格式转化为Unicode格式我们会在后面具体实现common.cpp
#include "Common.h"
string UnicodeToANSI(const CDuiString& str)
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen = WideCharToMultiByte(CP_ACP,
0,
str.GetData(),
-1,
NULL,
0,
NULL,
NULL);
pElementText = new char[iTextLen + 1];
memset((void*)pElementText, 0, sizeof(char)* (iTextLen + 1));
::WideCharToMultiByte(CP_ACP,
0,
str.GetData(),
-1,
pElementText,
iTextLen,
NULL,
NULL);
string strText;
strText = pElementText;
delete[] pElementText;
return strText;
}
CDuiString ANSIToUnicode(const string& str)
{
int len = 0;
len = str.length();
int unicodeLen = ::MultiByteToWideChar(CP_ACP,
0,
str.c_str(),
-1,
NULL,
0);
wchar_t * pUnicode;
pUnicode = new wchar_t[unicodeLen + 1];
memset(pUnicode, 0, (unicodeLen + 1)*sizeof(wchar_t));
::MultiByteToWideChar(CP_ACP,
0,
str.c_str(),
-1,
(LPWSTR)pUnicode,
unicodeLen);
CDuiString rt(pUnicode);
delete pUnicode;
return rt;
}
1.首先环境搭建,如果连接文件有误,或者编译文件出现错误没有生成目标文件
可以已通过报错返回的错误类型如果外部库或者数据库头文件等就是存在环境搭建问题
2.类型转化问题?
很多时候需要将Unicode格式的编码转化为二进制或者将二进制转化为Uicode我们在网上查阅了相关资料编写了相关函数
3.SQL语句编写出错
首先给我的收获就是学会了Duillib这套库的使用,可以制作简单的界面,让我学到了很多界面设计的知识其次我们学会了将自己的在一个项目中,自己会的语言并不是简单的进行组合,更要有大局观,要用语言将所有模块统一组织,更加注重模块之间的关系,而不思简单的对于语言的利用整个项目到这里就差不多了,整个项目从开始到结束历时一个周左右,部分功能可能还有待扩展,但是节本框架完善,可以进行基本操作,在这次项目中让我们学到的知识更加能够利用起来,更加明了,纸上得来终觉浅绝知此事要躬行,在今天我们应届大学生将会是今后社会上的中流砥柱,更加是社会未来的主人,不能只学课本上的知识,更加要将书本与实际相结合,做一个理论素质强,同时兼具动手能力的新时代大学生,才能更好面对将来的挑战。