1 新建项目
1.1 根据向导创建项目
首先,新建MFC项目(SaleSystem),基于单文档,MFC标准项目,同时,去掉工具栏:
1.2 添加预处理指令
由于微软在VS2013中不建议再使用C/C++的传统库函数scanf,strcpy,sprintf等,所以直接使用这些库函数会提示C4996错误。
VS建议采用带_s的函数,如scanf_s、strcpy_s,但这些并不是标准C/C++函数。要想继续使用此函数,需要添加 _CRT_SECURE_NO_WARNINGS
这个预定义。
在项目 -> 属性 -> C/C+±>预处理器 -> 预处理器定中添加 _CRT_SECURE_NO_WARNINGS:
1.3 设置窗口属性
- 设置图标
打开资源视图,添加本地ICO图标,在res文件夹中添加我们提前准备的图标资源:
在资源的属性中修改ID(IDI_ICON_WIN):
在CMainFrame的 OnCreate()中添加如下代码:
//设置图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数 SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN));
- 设置窗口大小和居中显示
还是在CMainFrame的OnCreate()中接着写代码:
//设置窗口的位置和大小:CWnd::MoveWindow //0, 0, 起点坐标x和y //800, 500, 窗口宽度和高度 MoveWindow(0, 0, 800, 500); //将窗口移动到屏幕中央,CWnd::CenterWindow CenterWindow();
- 设置窗口标题
在CSaleSystemDoc文档类中的OnNewDocument()函数中添加如下代码:
//设置窗口标题,CDocument::SetTitle SetTitle(TEXT("销售管理系统"));
程序运行效果图如下:
2 文件处理
2.1 文件内容格式
登陆用户信息:
商品信息:
2.2 设计文件处理类CInfoFile
- 添加文件处理类CInfoFile
- 头文件(InfoFile.h)的设计
定义两个配置文件路径宏:
#define _F_LOGIN "./login.ini" #define _F_STOCK "./stock.txt"
添加文件信息结构体,具体如下:
struct msg { int id; //商品id string name; //商品名,别忘包含相应头文件 int price; //商品价格 int num; //商品个数 };
商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量:
list<msg> ls; //存储商品容器,别忘包含相应头文件 int num; //用来记录商品个数
项目中需要读写的文件有两种,用户信息配置文件和商品信息文件。具体 API 接口如下:
//读取登陆信息 void ReadLogin(CString &name, CString &pwd); //修改密码 void WritePwd(char* name, char* pwd); // 读取商品数据 void ReadDocline(); //商品写入文件 void WirteDocline(); //添加新商品 void Addline(CString name, int num, int price);
3 登陆对话框
3.1 ui设计
1)添加对话框资源(ID修改为DIALOG_LOGIN),添加所需控件:
2)选中对话框 -> 右击 -> 添加类 -> 类名:CLoginDlg
3)根据需求,控件关联所需变量
用户名编辑区关联CString m_user,密码登陆框关联CString m_pwd。
3.2 功能实现
1)在对话框类中,重写 OnInitDialog 函数,进行初始化,设置一些默认登录信息。
m_user = TEXT("斧头帮帮主"); //用户名 m_pwd = TEXT("123456");//密码 UpdateData(FALSE); //内容更新到对应的控件
2)登陆窗口的创建
在应用程序类CSaleSystemApp的InitInstance() 里面的APP 创建之前创建登陆对话框:
CLoginDlg dlg; //创建登陆对话框,需要头文件#include "LoginDlg.h" dlg.DoModal(); //以模态方式运行
3)登陆按钮功能实现
//登陆按钮处理函数 void CLoginDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); //更新控件的数据到对应的变量 CInfoFile file; //创建操作文件类对象,需要头文件#include "InfoFile.h" CString user, pwd; //读取配置文件,获取用户名密码,参数为引用传递 file.ReadLogin(user, pwd); if (m_user == user)//用户名相等 { if (m_pwd != pwd) { MessageBox(_T("密码错误")); m_user.Empty(); //清空 m_pwd.Empty(); } else { CDialogEx::OnOK(); } } else { MessageBox(_T("用户名不存在")); m_user.Empty(); m_pwd.Empty(); } }
4)取消按钮功能实现
//取消按钮功能实现 void CLoginDlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 exit(0); //结束整个程序 }
5)右上角关闭按钮功能实现
选中对话框模板 -> 右击 -> 属性 -> 消息 -> WM_CLOSE
//关闭按钮 void CLoginDlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 exit(0); //结束整个程序 CDialogEx::OnClose(); }
6)编辑区回车键关闭对话框问题解决
4 静态拆分窗口
4.1 自定义MFC视图类
自定义两个类:CSelectView和CDispalyView(它的基类必须是视图类)。
CSelectView继承于CTreeView,CDispalyView继承于CFormView。
4.2 通过CSplitterWnd类拆分窗口
1)CMainFrame类中,声明CSplitterWnd类型的对象:
private: CSplitterWnd m_spliter; // 切分窗口类对象
2)重写框架类CMainFrame的OnCreateClient函数
把OnCreateClient()函数的返回值改为Return TRUE:
静态拆分实现代码如下:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // TODO: 在此添加专用代码和/或调用基类 // 静态拆分窗口,1行2列,CSplitterWnd::CreateStatic m_spliter.CreateStatic(this, 1, 2); // 创建视图:CSplitterWnd::CreateView //0, 0 : 放在第0行第0列的位置 //RUNTIME_CLASS(CSelectView) :需要头文件#include "SelectView.h", CSelectView在SelectView.h中声明 // CSize(250, 500):指定视图宽度和高度 //pContext : 为OnCreateClient()最后一个形参 m_spliter.CreateView(0, 0, RUNTIME_CLASS(CSelectView), CSize(200, 500), pContext); //0, 1: 放在第0行第1列的位置 //CDispalyView,需要头文件#include "DispalyView.h" m_spliter.CreateView(0, 1, RUNTIME_CLASS(CDispalyView), CSize(600, 500), pContext); //return CFrameWnd::OnCreateClient(lpcs, pContext); return TRUE; }
程序运行效果图如下:
5 树视图功能实现
5.1 添加功能节点
1)加载图标资源
图标资源ID改为:IDI_ICON_RE
2)CSelectView类中声明相应变量:
CTreeCtrl *m_treeCtrl; //树控件 CImageList m_imageList; //图标列表
3)重写CSelectView的OnInitUpdate函数
void CSelectView::OnInitialUpdate() { CTreeView::OnInitialUpdate(); // TODO: 在此添加专用代码和/或调用基类 }
4)在CSelectView的OnInitUpdate函数中,完成初始化功能
void CSelectView::OnInitialUpdate() { CTreeView::OnInitialUpdate(); // TODO: 在此添加专用代码和/或调用基类 //图标资源的加载 CWinApp::LoadIcon //IDI_ICON_RE为图标资源ID HICON icon = AfxGetApp()->LoadIconW(IDI_ICON_RE); //图片列表的创建 CImageList::Create //30, 30:指定图标的宽度和高度 //ILC_COLOR32:图标格式 //1, 1:有多少图标就写多少 m_imageList.Create(30, 30, ILC_COLOR32, 1, 1); //图片列表追加图标 CImageList::Add m_imageList.Add(icon); //获取数视图中的树控件 CTreeView::GetTreeCtrl m_treeCtrl = &GetTreeCtrl(); //数控件设置图片列表 CTreeCtrl::SetImageList m_treeCtrl->SetImageList(&m_imageList, TVSIL_NORMAL); //树控件设置节点 CTreeCtrl::InsertItem m_treeCtrl->InsertItem(TEXT("个人信息"), 0, 0, NULL); m_treeCtrl->InsertItem(TEXT("销售管理"), 0, 0, NULL); m_treeCtrl->InsertItem(TEXT("库存信息"), 0, 0, NULL); m_treeCtrl->InsertItem(TEXT("库存添加"), 0, 0, NULL); m_treeCtrl->InsertItem(TEXT("库存删除"), 0, 0, NULL); }
程序运行效果图如下:
5.2 功能节点相应消息处理
void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; }
在上面函数,实现获取当前节点选中内容:
void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; //获取当前节点选中项目 CTreeCtrl::GetSelectedItem HTREEITEM item = m_treeCtrl->GetSelectedItem(); //获取选中项的文本内容 CTreeCtrl::GetItemText CString str = m_treeCtrl->GetItemText(item); //MessageBox(str); if (str == TEXT("个人信息")) { } else if (str == TEXT("销售管理")) { } else if (str == TEXT("库存信息")) { } else if (str == TEXT("库存增加")) { } else if (str == TEXT("库存删除")) { } }