在学习MFC总结了笔记,并分享出来

07-MFC_20day

 

 

一、项目配置

1、创建项目

2、预处理 C4996 :_CRT_SECURE_NO_WARNINGS

3、窗口进行简单处理

(1)修改窗口图标,setClassLong(窗口句柄,修改图标,具体图标加载)

(2)标题 setTitle 分左右侧:左侧:CSaleSystemDoc-OnNewDocument;右侧:CMainFrame-OnCreate中修改

(3)设置窗口大小:MoveWindow

(4)居中CenterWindow

CMainFrame-OnCreate中:


1     //设置图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数
2 SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN));
3
4 //修改标题 右侧标题
5 SetTitle(TEXT("2020/06/26"));
6
7 //修改窗口大小
8 MoveWindow(0, 0, 800, 500);
9
10 //居中显示
11 CenterWindow();



CSaleSystemDoc-OnNewDocument中:



1 //左侧标题设置 2 SetTitle(TEXT("销售管理系统"));



二、CInfoFile引入

1、文件内容及格式 添加资源

在项目文件夹下添加login.ini,中:



1 斧头帮帮主 2 123456



在项目文件夹下添加stock.txt,中:



1 商品ID|商品名称|商品价格|库存 2 1|商品1|123|440 3 2|商品2|1123|555 4 3|商品3|1333|541 5 4|商品4|144423|547 6 5|商品5|14423|555 7 6|商品6|1123|554 8 7|商品7|1223|544 9 8|商品8|1233|555 10 9|商品9|1234|554 11 10|商品10|1523|555 12 11|商品11|5123|555 13 12|商品12|133|333 14 13|商品13|444|444 15 14|商品14|1111|111 16 15|测试|10|8



2、将CInfoFile类导入到项目中

(1)添加CInfoFile类

(2)头文件(InfoFile.h)的设计

定义两个配置文件路径宏:



1 #define _F_LOGIN "./login.ini"
2 #define _F_STOCK "./stock.txt"



添加文件信息结构体,具体如下:



1 struct msg
2 {
3 int id; //商品id
4 string name; //商品名,别忘包含相应头文件
5 int price; //商品价格
6 int num; //商品个数
7 };



商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量:



1     list<msg> ls;    //存储商品容器,别忘包含相应头文件
2 int num; //用来记录商品个数



项目中需要读写的文件有两种,用户信息配置文件和商品信息文件。具体 API 接口如下:


1 //读取登陆信息
2 void ReadLogin(CString &name, CString &pwd);
3
4 //修改密码
5 void WritePwd(char* name, char* pwd);
6
7 // 读取商品数据
8 void ReadDocline();
9
10 //商品写入文件
11 void WirteDocline();
12
13 //添加新商品
14 void Addline(CString name, int num, int price);



InfoFile.h全部代码如下:


1 #pragma once
2
3 #include <list>
4 #include <fstream>
5 #include <iostream>
6 #include <string>
7
8 #define _F_LOGIN "./login.ini"
9 #define _F_STOCK "./stock.txt"
10
11 using namespace std;
12
13 struct msg
14 {
15 int id; //商品id
16 string name; //商品名
17 int price; //商品价格
18 int num; //商品个数
19 };
20
21 class CInfoFile
22 {
23 public:
24 CInfoFile();
25 ~CInfoFile();
26
27 //读取登陆信息
28 void ReadLogin(CString &name, CString &pwd);
29
30 //修改密码
31 void WritePwd(char* name, char* pwd);
32
33 // 读取商品数据
34 void ReadDocline();
35
36 //商品写入文件
37 void WirteDocline();
38
39 //添加新商品
40 void Addline(CString name, int num, int price);
41
42 list<msg> ls; //存储商品容器
43 int num; //用来记录商品个数
44 };



InfoFile.cpp全部代码如下:


1 #include "stdafx.h"
2 #include "InfoFile.h"
3
4
5 CInfoFile::CInfoFile()
6 {
7 }
8
9
10 CInfoFile::~CInfoFile()
11 {
12 }
13
14 //读取登录信息
15 void CInfoFile::ReadLogin(CString &name, CString &pwd)
16 {
17 ifstream ifs; //创建文件输入对象
18 ifs.open(_F_LOGIN); //打开文件
19
20 char buf[1024] = { 0 };
21
22 ifs.getline(buf, sizeof(buf)); //读取一行内容
23 name = CString(buf); //char *转换为CString
24
25 ifs.getline(buf, sizeof(buf));
26 pwd = CString(buf);
27
28 ifs.close(); //关闭文件
29 }
30
31 //修改密码
32 void CInfoFile::WritePwd(char* name, char* pwd)
33 {
34 ofstream ofs; //创建文件输出对象
35 ofs.open(_F_LOGIN); //打开文件
36
37 ofs << name << endl; //name写入文件
38 ofs << pwd << endl; //pwd写入文件
39
40 ofs.close(); //关闭文件
41 }
42
43 //读取商品信息
44 void CInfoFile::ReadDocline()
45 {
46 ifstream ifs(_F_STOCK); //输入方式打开文件
47
48 char buf[1024] = { 0 };
49 num = 0; //初始化商品数目为0
50 ls.clear();
51 //取出表头
52 ifs.getline(buf, sizeof(buf));
53
54 while (!ifs.eof()) //没到文件结尾
55 {
56 msg tmp;
57
58 ifs.getline(buf, sizeof(buf)); //读取一行
59 num++; //商品数目加一
60
61 //AfxMessageBox(CString(buf));
62 char *sst = strtok(buf, "|"); //以“|”切割
63 if (sst != NULL)
64 {
65 tmp.id = atoi(sst); //商品id
66 }
67 else
68 {
69 break;
70 }
71
72 sst = strtok(NULL, "|");
73 tmp.name = sst; //商品名称
74
75 sst = strtok(NULL, "|");
76 tmp.price = atoi(sst); //商品价格
77
78 sst = strtok(NULL, "|");
79 tmp.num = atoi(sst); //商品数目
80
81 ls.push_back(tmp); //放在链表的后面
82 }
83
84 ifs.close(); //关闭文件
85 }
86
87 //商品写入文件
88 void CInfoFile::WirteDocline()
89 {
90 ofstream ofs(_F_STOCK);//输出方式打开文件
91
92 if (ls.size() > 0) //商品链表有内容才执行
93 {
94 ofs << "商品ID|商品名称|商品价格|库存" << endl; //写入表头
95
96 //通过迭代器取出链表内容,写入文件,以“|”分隔,结尾加换行
97 for (list<msg>::iterator it = ls.begin(); it != ls.end(); it++)
98 {
99 ofs << it->id << "|";
100 ofs << it->name << "|";
101 ofs << it->price << "|";
102 ofs << it->num << endl;
103 }
104 }
105
106 ofs.close();//关闭文件
107 }
108
109 //添加新商品
110 //name:商品名称,num:库存,price:价格
111 void CInfoFile::Addline(CString name, int num, int price)
112 {
113 msg tmp;
114
115 if (ls.size() > 0)
116 {
117 //商品名称,库存,价格有效
118 if (!name.IsEmpty() && num > 0 && price > 0)
119 {
120 tmp.id = ls.size() + 1; //id自动加1
121 CStringA str;
122 str = name; //CString转CStirngA
123 tmp.name = str.GetBuffer(); //CStirngA转char *,商品名称
124 tmp.num = num; //库存
125 tmp.price = price; //价格
126
127 ls.push_back(tmp); //放在链表的后面
128 }
129 }
130 }


3、进行简单测试,读取用户名、密码、修改密码

 

三、登录窗口实现

1、插入对话框

1)添加对话框资源(ID修改为DIALOG_LOGIN),添加所需控件

2、对界面进行布局

3、添加类:

2)选中对话框 -> 右击 -> 添加类 -> 类名:CLoginDlg

4、添加变量 m_user、m_pwd;根据需求,控件关联所需变量;用户名编辑区关联CString m_user,密码登陆框关联CString m_pwd。

MFC学习笔记——07-MFC_20day_控件

5、初始化:用户名、密码

(1)在对话框类中,重写 OnInitDialog 函数,进行初始化,设置一些默认登录信息

MFC学习笔记——07-MFC_20day_#include_02

MFC学习笔记——07-MFC_20day_#include_03

(2)登陆窗口的创建

在应用程序类CSaleSystemApp的InitInstance() 里面的APP 创建之前创建登陆对话框:

MFC学习笔记——07-MFC_20day_ico_04

6、功能实现

(1)登录按钮



1 //登陆按钮处理函数
2 void CLoginDlg::OnBnClickedButton1()
3 {
4 // TODO: 在此添加控件通知处理程序代码
5
6 UpdateData(TRUE); //更新控件的数据到对应的变量
7
8 CInfoFile file; //创建操作文件类对象,需要头文件#include "InfoFile.h"
9 CString user, pwd;
10
11 //读取配置文件,获取用户名密码,参数为引用传递
12 file.ReadLogin(user, pwd);
13
14 if (m_user == user)//用户名相等
15 {
16 if (m_pwd != pwd)
17 {
18 MessageBox(_T("密码错误"));
19 m_user.Empty(); //清空
20 m_pwd.Empty();
21 }
22 else
23 {
24 CDialogEx::OnOK();
25 }
26 }
27 else
28 {
29 MessageBox(_T("用户名不存在"));
30 m_user.Empty();
31 m_pwd.Empty();
32 }
33 }



(2)取消按钮



1 //取消按钮功能实现
2 void CLoginDlg::OnBnClickedButton2()
3 {
4 // TODO: 在此添加控件通知处理程序代码
5 exit(0); //结束整个程序
6 }



(3)右上角关闭按钮功能实现

选中对话框模板 -> 右击 -> 属性 -> 消息 -> WM_CLOSE

MFC学习笔记——07-MFC_20day_#include_05



1 //关闭按钮 2 void CLoginDlg::OnClose() 3 { 4 // TODO: 在此添加消息处理程序代码和/或调用默认值 5 exit(0); //结束整个程序 6 7 CDialogEx::OnClose(); 8 }



(4)编辑区回车键关闭对话框问题解决——重写OnOk

MFC学习笔记——07-MFC_20day_ico_06

MFC学习笔记——07-MFC_20day_ico_07

 

四、静态拆分窗口

1、拆分窗口对象

自定义MFC视图类

》自定义两个类:CSelectView和CDispalyView(它的基类必须是视图类)。

》CSelectView继承于CTreeView,CDispalyView继承于CFormView。

MFC学习笔记——07-MFC_20day_#include_08

MFC学习笔记——07-MFC_20day_控件_09

MFC学习笔记——07-MFC_20day_ico_10

2、创建静态拆分

通过CSplitterWnd类拆分窗口
CMainFrame类中,声明CSplitterWnd类型的对象:

MFC学习笔记——07-MFC_20day_ico_11

3、具体拆分窗口

 重写框架类CMainFrame的OnCreateClient函数

 

MFC学习笔记——07-MFC_20day_ico_12

 把OnCreateClient()函数的返回值改为Return TRUE:

MFC学习笔记——07-MFC_20day_ico_13

静态拆分实现代码如下:

MFC学习笔记——07-MFC_20day_控件_14


1 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
2 {
3 // TODO: 在此添加专用代码和/或调用基类
4
5 // 静态拆分窗口,1行2列,CSplitterWnd::CreateStatic
6 m_spliter.CreateStatic(this, 1, 2);
7
8 // 创建视图:CSplitterWnd::CreateView
9 //0, 0 : 放在第0行第0列的位置
10 //RUNTIME_CLASS(CSelectView) :需要头文件#include "SelectView.h", CSelectView在SelectView.h中声明
11 // CSize(250, 500):指定视图宽度和高度
12 //pContext : 为OnCreateClient()最后一个形参
13 m_spliter.CreateView(0, 0, RUNTIME_CLASS(CSelectView), CSize(200, 500), pContext);
14
15 //0, 1: 放在第0行第1列的位置
16 //CDispalyView,需要头文件#include "DispalyView.h"
17 m_spliter.CreateView(0, 1, RUNTIME_CLASS(CDispalyView), CSize(600, 500), pContext);
18
19 //return CFrameWnd::OnCreateClient(lpcs, pContext);
20 return TRUE;
21 }


五、树视图功能实现

1、数据准备

(1)加载图标资源

MFC学习笔记——07-MFC_20day_控件_15

(2)图标资源ID改为:IDI_ICON_RE

2、获取到树控件 GetTreeCtrl()

CSelectView类中声明相应变量:

MFC学习笔记——07-MFC_20day_ico_16

3、设置图片集合 、设置节点

重写CSelectView的OnInitUpdate函数,在CSelectView的OnInitUpdate函数中,完成初始化功能



1 void CSelectView::OnInitialUpdate()
2 {
3 CTreeView::OnInitialUpdate();
4
5 // TODO: 在此添加专用代码和/或调用基类
6
7 //图标资源的加载 CWinApp::LoadIcon
8 //IDI_ICON_RE为图标资源ID
9 HICON icon = AfxGetApp()->LoadIconW(IDI_ICON_RE);
10
11 //图片列表的创建 CImageList::Create
12 //30, 30:指定图标的宽度和高度
13 //ILC_COLOR32:图标格式
14 //1, 1:有多少图标就写多少
15 m_imageList.Create(30, 30, ILC_COLOR32, 1, 1);
16
17 //图片列表追加图标 CImageList::Add
18 m_imageList.Add(icon);
19
20 //获取数视图中的树控件 CTreeView::GetTreeCtrl
21 m_treeCtrl = &GetTreeCtrl();
22
23 //数控件设置图片列表 CTreeCtrl::SetImageList
24 m_treeCtrl->SetImageList(&m_imageList, TVSIL_NORMAL);
25
26 //树控件设置节点 CTreeCtrl::InsertItem
27 m_treeCtrl->InsertItem(TEXT("个人信息"), 0, 0, NULL);
28 m_treeCtrl->InsertItem(TEXT("销售管理"), 0, 0, NULL);
29 m_treeCtrl->InsertItem(TEXT("库存信息"), 0, 0, NULL);
30 m_treeCtrl->InsertItem(TEXT("库存添加"), 0, 0, NULL);
31 m_treeCtrl->InsertItem(TEXT("库存删除"), 0, 0, NULL);
32 }



 4、捕获事件(选项修改事件)

MFC学习笔记——07-MFC_20day_控件_17



1 void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
2 {
3 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
4 // TODO: 在此添加控件通知处理程序代码
5 *pResult = 0;
6
7 //获取当前节点选中项目 CTreeCtrl::GetSelectedItem
8 HTREEITEM item = m_treeCtrl->GetSelectedItem();
9
10 //获取选中项的文本内容 CTreeCtrl::GetItemText
11 CString str = m_treeCtrl->GetItemText(item);
12 //MessageBox(str);
13
14 if (str == TEXT("个人信息"))
15 {
16 }
17 else if (str == TEXT("销售管理"))
18 {
19 }
20 else if (str == TEXT("库存信息"))
21 {
22 }
23 else if (str == TEXT("库存增加"))
24 {
25 }
26 else if (str == TEXT("库存删除"))
27 {
28 }
29 }



 

六、个人信息界面布局

 

 

七、个人信息的界面挂载

1、自定义消息 define 宏 NM_A~E

2、在分界宏声明自定义消息 :ON_MESSAGE(NM_A, OnMyChange)

3、实现OnMyChange函数:



afx_msg LRESULT OnMyChange(WPARAM wParam, LPARAM lParam);



4、在SelectView发送自定义消息



1 LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam) 2 3 { 4 5 6 7 }



5、捕获消息,进行界面挂载



 

八、个人信息功能实现

1、搭建界面

2、功能实现

3、初始化界面:身份、用户名

4、修改密码功能

(1)有效性验证:内容不能为空,密码两次输入要一致,与原密码不一样

(2)取消:清空内容

 

九、销售管理界面

 

 

十、添加商品

 

 

十一、添加新商品

 

 

十二、菜单栏添加

 

 

在学习MFC总结了笔记,并分享出来

商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量: