• MFC学习笔记——07-MFC_20day


    在学习MFC总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    07-MFC_20day

    目录:
    一、项目配置
    二、CInfoFile引入
    三、登录窗口实现
    四、静态拆分窗口
    五、树视图功能实现
    六、个人信息管理窗口
    七、销售管理界面
    八、库存信息窗口
    九、库存添加
    十、库存删除
    十一、菜单栏添加

    销售管理系统

    一、项目配置

    1、创建项目

    首先,新建MFC项目(SaleSystem),基于单文档,MFC标准项目,同时,去掉工具栏:

    2、预处理 C4996 :_CRT_SECURE_NO_WARNINGS


    由于微软在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:


    3、窗口进行简单处理

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

    1)打开资源视图,添加本地ICO图标,在res文件夹中添加我们提前准备的图标资源;

    2)在资源的属性中修改ID(IDI_ICON_WIN);

    3)在CMainFrame的 OnCreate()中添加如下代码;

    1 //设置图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数
    2 SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN));

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

    设置窗口标题

    右侧标题:在CMainFrame的OnCreate()中接着写代码:

    1     //修改标题 右侧标题
    2     SetTitle(TEXT("2020/06/26"));

    左侧标题:在CSaleSystemDoc文档类中的OnNewDocument()函数中添加如下代码:

    1     //设置窗口标题,CDocument::SetTitle
    2     SetTitle(TEXT("销售管理系统"));

    (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、插入对话框

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

    2、对界面进行布局

    3、添加类:

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

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

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

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

    1     m_user = TEXT("斧头帮帮主");    //用户名
    2     m_pwd = TEXT("123456");//密码
    3     UpdateData(FALSE); //内容更新到对应的控件

    (2)登陆窗口的创建

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

    1     CLoginDlg dlg;    //创建登陆对话框,需要头文件#include "LoginDlg.h"
    2     dlg.DoModal();    //以模态方式运行

    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

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

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

    四、静态拆分窗口

    1、拆分窗口对象

    自定义MFC视图类

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

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

    2、创建静态拆分

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

    3、具体拆分窗口

     重写框架类CMainFrame的OnCreateClient函数

     

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

    静态拆分实现代码如下:

     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)加载图标资源

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

    2、获取到树控件 GetTreeCtrl()

    CSelectView类中声明相应变量:

    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、捕获事件(选项修改事件)

     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、个人信息界面布局

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

    在窗口属性中,Border改为None,Style改为Child:

     

    (2)选中对话框 -> 右击 -> 添加类 -> 类名:CUserDlg,基类选择CFormView

    (3)根据需求,控件关联所需变量

    身份编辑区关联CString m_user,用户名编辑框关联CString m_name,

    新密码编辑框关联CString m_newPwd,确定密码编辑框关联CString m_surePwd。

    2、功能实现

    (1)在对话框类中,重写 OnInitDialog 函数,进行初始化。

     1 void CUserDlg::OnInitialUpdate()
     2 {
     3     CFormView::OnInitialUpdate();
     4 
     5     // TODO:  在此添加专用代码和/或调用基类
     6 
     7     CInfoFile file;    //需要头文件#include "InfoFile.h"
     8     CString name, pwd;
     9     file.ReadLogin(name, pwd); //读取文件的用户名和密码
    10 
    11     //初始化个人信息
    12     m_user = TEXT("销售员");    //身份
    13     m_name = name;    //用户名
    14 
    15     UpdateData(FALSE); //把数据更新到控件上
    16 }

    (2)确定修改密码按钮功能实现

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

     1 void CUserDlg::OnBnClickedButton1()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     UpdateData(TRUE);//更新控件内容到对应的变量中
     6 
     7     if (m_newPwd.IsEmpty() || m_surePwd.IsEmpty())
     8     {
     9         MessageBox(TEXT("输入密码不能为空"));
    10         return;
    11     }
    12 
    13     if (m_newPwd != m_surePwd)
    14     {
    15         MessageBox(TEXT("输入密码和确定密码不相等"));
    16         return;
    17     }
    18 
    19     CInfoFile file;    //需要头文件#include "InfoFile.h"
    20     CString name, pwd;
    21     file.ReadLogin(name, pwd); //读取文件的用户名和密码
    22 
    23     if (m_surePwd == pwd)
    24     {
    25         MessageBox(TEXT("输入密码和旧密码相等"));
    26         return;
    27     }
    28 
    29     //把用户名和密码的CString类型转为char *
    30     char *tmpName, *tmpPwd;
    31     //用户名
    32     CStringA tmp1;
    33     tmp1 = name;
    34     tmpName = tmp1.GetBuffer();
    35     //密码
    36     CStringA tmp2;
    37     tmp2 = m_surePwd;
    38     tmpPwd = tmp2.GetBuffer();
    39 
    40     file.WritePwd(tmpName, tmpPwd); //修改密码
    41 
    42     MessageBox(TEXT("密码修改成功"));
    43 
    44     //输入框内容清空
    45     m_surePwd.Empty();
    46     m_newPwd.Empty();
    47     UpdateData(FALSE); //把数据更新到控件上
    48 }

    (3)取消按钮功能实现

    1 void CUserDlg::OnBnClickedButton3()
    2 {
    3     // TODO:  在此添加控件通知处理程序代码
    4 
    5     //输入框内容清空
    6     m_surePwd.Empty();
    7     m_newPwd.Empty();
    8     UpdateData(FALSE); //把数据更新到控件上
    9 }

    3、个人信息的界面挂载

    (1)自定义信息发送,消息 define 宏 NM_A~E

    在CMainFrame 框架类中,添加自定义消息宏

    1 //WM_USER 是用户自定义消息的一个起始值
    2 //WM_USER+100是为了区分系统消息和用户消息,避免冲突
    3 #define NM_A    (WM_USER + 100)
    4 #define NM_B    (WM_USER + 101)
    5 #define NM_C    (WM_USER + 102)
    6 #define NM_D    (WM_USER + 103)
    7 #define NM_E    (WM_USER + 104)

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

    在CMainFrame框架类BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间添加自定义消息入口,与自定义消息处理函数绑定。

    1     //ON_MESSAGE响应的是自定义消息
    2     //产生NM_X消息,自动调用OnMyChange函数
    3     ON_MESSAGE(NM_A, OnMyChange)
    4     ON_MESSAGE(NM_B, OnMyChange)
    5     ON_MESSAGE(NM_C, OnMyChange)
    6     ON_MESSAGE(NM_D, OnMyChange)
    7     ON_MESSAGE(NM_E, OnMyChange)
    8     

    (3)实现OnMyChange函数:

    在CMainFrame框架类中添加自定义消息处理函数:

    1 //自定义消息处理函数
    2 afx_msg LRESULT OnMyChange(WPARAM wParam, LPARAM lParam);

    (4)在SelectView发送自定义消息

    对应的.cpp定义其函数

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

    (5)在CSelectView的OnTvnSelchanged函数中,发送自定义信号:

     1 if (str == TEXT("个人信息"))
     2 {
     3     //需要包含框架类头文件#include "MainFrm.h" 
     4     //CWnd::PostMessage 将一个消息放入窗口的消息队列
     5     //AfxGetMainWnd():框架窗口对象的指针
     6     //AfxGetMainWnd()->GetSafeHwnd():获取返回窗口的句柄,CWnd::GetSafeHwnd
     7     //NM_A:发送自定义消息
     8     //(WPARAM)NM_A:指定了附加的消息信息
     9     //(LPARAM)0:指定了附加的消息信息,此参数这里没有意义
    10 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_A, (WPARAM)NM_A, (LPARAM)0);
    11 }
    12 else if (str == TEXT("销售管理"))
    13 {
    14 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_B, (WPARAM)NM_B, (LPARAM)0);
    15 }
    16 else if (str == TEXT("库存信息"))
    17 {
    18 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_C, (WPARAM)NM_C, (LPARAM)0);
    19 }
    20 else if (str == TEXT("库存添加"))
    21 {
    22 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_D, (WPARAM)NM_D, (LPARAM)0);
    23 }
    24 else if (str == TEXT("库存删除"))
    25 {
    26 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_E, (WPARAM)NM_E, (LPARAM)0);
    27 }

    (6)自定义信息处理

    在CMainFrame框架类OnMyChange函数中处理相应消息

     1 LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam)
     2 {
     3     switch (wParam)
     4     {
     5     case NM_A:
     6         MessageBox(_T("NM_A"));
     7         break;
     8     case NM_B:
     9         MessageBox(_T("NM_B"));
    10         break;
    11     case NM_C:
    12         MessageBox(_T("NM_C"));
    13         break;
    14     case NM_D:
    15         MessageBox(_T("NM_D"));
    16         break;
    17     case NM_E:
    18         MessageBox(_T("NM_E"));
    19         break;
    20     default:
    21         MessageBox(_T("error"));
    22     }
    23     return 0;
    24 }

    (7)界面挂载

    如果是NM_A信号,则挂载CUserDlg窗口,后面界面的挂载以此类推。

     1 CCreateContext   Context;
     2 switch (wParam)
     3 {
     4 case NM_A:
     5 {
     6     //CUserDlg类需要包含头文件#include "UserDlg.h"
     7     Context.m_pNewViewClass = RUNTIME_CLASS(CUserDlg); 
     8     Context.m_pCurrentFrame = this;
     9     Context.m_pLastView = (CFormView *)m_spliter.GetPane(0, 1);
    10     m_spliter.DeleteView(0, 1);
    11     m_spliter.CreateView(0, 1, RUNTIME_CLASS(CUserDlg), CSize(600,500), &Context);
    12     CUserDlg *pNewView = (CUserDlg *)m_spliter.GetPane(0, 1);
    13     m_spliter.RecalcLayout();
    14     pNewView->OnInitialUpdate();
    15     m_spliter.SetActivePane(0, 1);
    16 }
    17     break;
    18 case NM_B:
    19 //……………

    七、销售管理界面

    1、创建窗口,修改属性

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

    在窗口属性中,Border改为None,Style改为Child:

    2、布局界面

    3、添加类

    选中对话框 -> 右击 -> 添加类 -> 类名:CSellDlg,基类选择CFormView

    4、添加变量

    根据需求,控件关联所需变量

    商品名组合框关联CComboBox m_combo,单价编辑框关联int m_price,

    个数编辑框关联int m_num,销售信息编辑框关联CString m_sellInfo。

    5、界面挂载

    在CMainFrame类中OnMyChange函数,添加如下代码:

     1     case NM_B:
     2     {
     3         //CSellDlg类需要包含头文件#include "SellDlg.h"
     4         Context.m_pNewViewClass = RUNTIME_CLASS(CSellDlg);
     5         Context.m_pCurrentFrame = this;
     6         Context.m_pLastView = (CFormView *)m_spliter.GetPane(0, 1);
     7         m_spliter.DeleteView(0, 1);
     8         m_spliter.CreateView(0, 1, RUNTIME_CLASS(CSellDlg), CSize(600, 0), &Context);
     9         CSellDlg *pNewView = (CSellDlg *)m_spliter.GetPane(0, 1);
    10         m_spliter.RecalcLayout();
    11         pNewView->OnInitialUpdate();
    12         m_spliter.SetActivePane(0, 1);
    13     }
    14         break;

    6、初始化下拉框

    在对话框类中,重写 OnInitDialog 函数,进行初始化。

     1 void CSellDlg::OnInitialUpdate()
     2 {
     3     CFormView::OnInitialUpdate();
     4 
     5     // TODO:  在此添加专用代码和/或调用基类
     6 
     7     //读取文件,获取商品名,给组合框添加字符串
     8     //需要包含#include "InfoFile.h"
     9     CInfoFile file;
    10     file.ReadDocline(); //读取商品信息
    11     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    12     {
    13         m_combo.AddString((CString)it->name.c_str());
    14     }
    15 
    16     file.ls.clear(); //清空list的内容
    17 
    18     //将第一个商品名设为默认选中项
    19     m_combo.SetCurSel(0);
    20 }

    7、根据用户选择的不同商品,更新商品的库存和单价

    处理组合框所需控制事件

     1 void CSellDlg::OnCbnSelchangeCombo1()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     CString text;
     6     //获取当前选中项
     7     int index = m_combo.GetCurSel();
     8     //获取当前内容
     9     m_combo.GetLBText(index, text);
    10 
    11     //需要包含#include "InfoFile.h"
    12     CInfoFile file;
    13     file.ReadDocline(); //读取商品信息
    14     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    15     {
    16         if (text == it->name.c_str())
    17         {
    18             m_price = it->price;
    19             m_num = 0;
    20             UpdateData(FALSE); //内容更新到对应的控件
    21         }
    22     }
    23 
    24     file.ls.clear(); //清空list的内容
    25 }

    8、购买功能实现

    (1)有效性验证

    (2)读取购买的商品,更新库存量

    (3)提示用户购买成功,显示到右侧购买信息

    (4)将数据同步到文件中

     1 void CSellDlg::OnBnClickedButton1()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4     
     5     //获取控件上的内容,更新到对应关联的变量中
     6     UpdateData(TRUE);
     7 
     8     if (m_num == 0)
     9     {
    10         MessageBox(TEXT("个数不能为0"));
    11         return;
    12     }
    13 
    14     CString type;
    15     //获取当前选中项
    16     int index = m_combo.GetCurSel();
    17     //获取组合框当前内容
    18     m_combo.GetLBText(index, type);
    19 
    20     CString str;
    21     str.Format(_T("商品:%s 
    单价:%d 
    个数:%d 
    总价:%d"), type, m_price, m_num, m_price*m_num);
    22 
    23     m_sellInfo = str; //销售信息
    24     UpdateData(FALSE);
    25     MessageBox(str);
    26 
    27 
    28     //需要包含#include "InfoFile.h"
    29     CInfoFile file;
    30     file.ReadDocline(); //读取商品信息
    31     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    32     {
    33         if (type == it->name.c_str())
    34         {
    35             it->num = it->num - m_num;
    36         }
    37     }
    38     file.WirteDocline(); //更新文件内容
    39 
    40     file.ls.clear(); //清空list的内容
    41 
    42     m_sellInfo.Empty();
    43     m_num = 0;
    44     UpdateData(FALSE); //更新到对应的控件
    45 }

    9、取消按钮——清空内容

    1 void CSellDlg::OnBnClickedButton3()
    2 {
    3     // TODO:  在此添加控件通知处理程序代码
    4 
    5     m_combo.SetCurSel(0); //选择第0项目
    6     m_sellInfo = "";
    7     m_num = 0;
    8     OnCbnSelchangeCombo1();
    9 }

    八、库存信息窗口

    1、ui设计

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

    在窗口属性中,Border改为None,Style改为Child:

    View 属性为 Report(报表表模式):

    2)选中对话框 -> 右击 -> 添加类 -> 类名:CInfoDlg,基类选择CFormView

    3)根据需求,控件关联所需变量

    列表控件关联CListCtrl m_list:

    2、界面挂载

    在CMainFrame类中OnMyChange函数,添加如下代码:

     1     case NM_C:
     2     {
     3         //CInfoDlg类需要包含头文件#include "InfoDlg.h"
     4         Context.m_pNewViewClass = RUNTIME_CLASS(CInfoDlg);
     5         Context.m_pCurrentFrame = this;
     6         Context.m_pLastView = (CFormView *)m_spliter.GetPane(0, 1);
     7         m_spliter.DeleteView(0, 1);
     8         m_spliter.CreateView(0, 1, RUNTIME_CLASS(CInfoDlg), CSize(600, 0), &Context);
     9         CInfoDlg *pNewView = (CInfoDlg *)m_spliter.GetPane(0, 1);
    10         m_spliter.RecalcLayout();
    11         pNewView->OnInitialUpdate();
    12         m_spliter.SetActivePane(0, 1);
    13     }
    14         break;

    3、功能实现

    在对话框类中,重写 OnInitDialog 函数,进行商品信息初始化:

     1 void CInfoDlg::OnInitialUpdate()
     2 {
     3     CFormView::OnInitialUpdate();
     4 
     5     // TODO:  在此添加专用代码和/或调用基类
     6     // 设置扩展风格
     7     //LVS_EX_FULLROWSELECT选中整行,LVS_EX_GRIDLINES网格
     8     m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
     9 
    10     // 初始化表头
    11     CString field[] = { _T("商品ID"), _T("商品名称"), _T("商品价格"), _T("库存数量") };
    12     for (int i = 0; i < sizeof(field) / sizeof(field[0]); ++i)
    13     {
    14         m_list.InsertColumn(i, field[i], LVCFMT_CENTER, 90);
    15     }
    16 
    17     //需要包含#include "InfoFile.h"
    18     CInfoFile file;
    19     file.ReadDocline(); //读取商品信息
    20 
    21     //添加数据
    22     int i = 0;
    23     CString str;
    24     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    25     {
    26         str.Format(_T("%d"), it->id);
    27         m_list.InsertItem(i, str);
    28         int column = 1;
    29         m_list.SetItemText(i, column++, (CString)it->name.c_str());
    30         str.Format(_T("%d"), it->price);
    31         m_list.SetItemText(i, column++, str);
    32         str.Format(_T("%d"), it->num);
    33         m_list.SetItemText(i, column++, str);
    34         i++;
    35     }
    36 
    37     
    38 }

    九、库存添加

    1、添加商品,界面布局

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

    (2)在窗口属性中,Border改为None,Style改为Child。

    2、添加类

    选中对话框 -> 右击 -> 添加类 -> 类名:CAddDlg,基类选择CFormView

    3、添加变量

    根据需求,控件关联所需变量

    添加个数:

    商品组合框关联CComboBox m_combo,单价编辑框关联int m_price1,

    个数编辑框关联int m_num1。

    添加新产品:

    商品组合框关联CString m_name2,单价编辑框关联int m_price2,

    个数编辑框关联int m_num2。

    4、界面挂载

    在CMainFrame类中OnMyChange函数,添加如下代码:

     1     case NM_D:
     2     {
     3         //CInfoDlg类需要包含头文件#include "AddDlg.h"
     4         Context.m_pNewViewClass = RUNTIME_CLASS(CAddDlg);
     5         Context.m_pCurrentFrame = this;
     6         Context.m_pLastView = (CFormView *)m_spliter.GetPane(0, 1);
     7         m_spliter.DeleteView(0, 1);
     8         m_spliter.CreateView(0, 1, RUNTIME_CLASS(CAddDlg), CSize(600, 0), &Context);
     9         CAddDlg *pNewView = (CAddDlg *)m_spliter.GetPane(0, 1);
    10         m_spliter.RecalcLayout();
    11         pNewView->OnInitialUpdate();
    12         m_spliter.SetActivePane(0, 1);
    13     }
    14 
    15         break;

    5、初始化左列,下拉框

    在对话框类中,重写OnInitialUpdate 函数,进行商品信息初始化:

     1 void CAddDlg::OnInitialUpdate()
     2 {
     3     CFormView::OnInitialUpdate();
     4 
     5     // TODO:  在此添加专用代码和/或调用基类
     6 
     7     //读取文件,获取商品名,给组合框添加字符串
     8     //需要包含#include "InfoFile.h"
     9     CInfoFile file;
    10     file.ReadDocline(); //读取商品信息
    11     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    12     {
    13         m_combo.AddString((CString)it->name.c_str());
    14     }
    15 
    16     file.ls.clear(); //清空list的内容
    17 
    18     //将第一个商品名设为默认选中项
    19     m_combo.SetCurSel(0);
    20 }

    6、处理组合框所需控制事件

     1 void CAddDlg::OnCbnSelchangeCombo2()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     CString text;
     6     //获取当前选中项
     7     int index = m_combo.GetCurSel();
     8     //获取当前内容
     9     m_combo.GetLBText(index, text);
    10 
    11     //需要包含#include "InfoFile.h"
    12     CInfoFile file;
    13     file.ReadDocline(); //读取商品信息
    14     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    15     {
    16         if (text == it->name.c_str())
    17         {
    18             m_price1 = it->price;
    19             m_num1 = 0;
    20             UpdateData(FALSE); //内容更新到对应的控件
    21         }
    22     }
    23 
    24     file.ls.clear(); //清空list的内容
    25 }

    7、添加个数按钮实现

     1 void CAddDlg::OnBnClickedButton1()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     //获取控件上的内容,更新到对应关联的变量中
     6     UpdateData(TRUE);
     7 
     8     if (m_num1 == 0)
     9     {
    10         MessageBox(TEXT("个数不能为0"));
    11         return;
    12     }
    13 
    14     CString type;
    15     //获取当前选中项
    16     int index = m_combo.GetCurSel();
    17     //获取组合框当前内容
    18     m_combo.GetLBText(index, type);
    19 
    20     CString str;
    21     str.Format(_T("添加了 商品:%s 
    单价:%d 
    个数:%d"), type, m_price1, m_num1);
    22     MessageBox(str);
    23 
    24 
    25     //需要包含#include "InfoFile.h"
    26     CInfoFile file;
    27     file.ReadDocline(); //读取商品信息
    28     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    29     {
    30         if (type == it->name.c_str())
    31         {
    32             it->num +=  m_num1;
    33         }
    34     }
    35     file.WirteDocline(); //更新文件内容
    36 
    37     file.ls.clear(); //清空list的内容
    38 
    39     m_num1 = 0;
    40     UpdateData(FALSE); //更新到对应的控件
    41 }

    8、添加个数取消按钮实现

    1 void CAddDlg::OnBnClickedButton2()
    2 {
    3     // TODO:  在此添加控件通知处理程序代码
    4 
    5     m_combo.SetCurSel(0);
    6     m_num1 = 0;
    7     OnCbnSelchangeCombo2();
    8 }

    9、添加新商品按钮实现

     1 void CAddDlg::OnBnClickedButton4()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     UpdateData(TRUE); //获取控件内容
     6 
     7     if (m_num2 <= 0 || m_price2 <= 0 || m_name2.IsEmpty())
     8     {
     9         MessageBox(TEXT("输入信息有误"));
    10         return;
    11     }
    12 
    13     //需要包含#include "InfoFile.h"
    14     CInfoFile file;
    15     file.ReadDocline(); //读取商品信息
    16     file.Addline(m_name2, m_num2, m_price2); //添加商品
    17     file.WirteDocline(); //写文件
    18     file.ls.clear(); //清空list的内容
    19     MessageBox(_T("添加成功"));
    20 
    21     m_name2.Empty();
    22     m_num2 = 0;
    23     m_price2 = 0;
    24     UpdateData(FALSE);
    25 }

    10、添加新商品取消按钮实现

    1 void CAddDlg::OnBnClickedButton5()
    2 {
    3     // TODO:  在此添加控件通知处理程序代码
    4     m_name2.Empty();
    5     m_num2 = 0;
    6     m_price2 = 0;
    7     UpdateData(FALSE);
    8 }

    十、库存删除

    1、UI设计

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

    在窗口属性中,Border改为None,Style改为Child。

    (2)选中对话框 -> 右击 -> 添加类 -> 类名:CDelDlg,基类选择CFormView

    (3)根据需求,控件关联所需变量

    商品名组合框关联CComboBox m_combo,单价编辑框关联int m_price,

    个数编辑框关联int m_num。

    2、界面挂载

    在CMainFrame类中OnMyChange函数,添加如下代码:

     1     case NM_E:
     2     {
     3         //CDelDlg类需要包含头文件#include "DelDlg.h"
     4         Context.m_pNewViewClass = RUNTIME_CLASS(CDelDlg);
     5         Context.m_pCurrentFrame = this;
     6         Context.m_pLastView = (CFormView *)m_spliter.GetPane(0, 1);
     7         m_spliter.DeleteView(0, 1);
     8         m_spliter.CreateView(0, 1, RUNTIME_CLASS(CDelDlg), CSize(600, 0), &Context);
     9         CDelDlg *pNewView = (CDelDlg *)m_spliter.GetPane(0, 1);
    10         m_spliter.RecalcLayout();
    11         pNewView->OnInitialUpdate();
    12         m_spliter.SetActivePane(0, 1);
    13     }
    14         break;

    3、功能实现

    (1)在对话框类中,重写 OnInitDialog 函数,进行初始化。

     1 void CDelDlg::OnInitialUpdate()
     2 {
     3     CFormView::OnInitialUpdate();
     4 
     5     //读取文件,获取商品名,给组合框添加字符串
     6     //需要包含#include "InfoFile.h"
     7     CInfoFile file;
     8     file.ReadDocline(); //读取商品信息
     9     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    10     {
    11         m_combo.AddString((CString)it->name.c_str());
    12     }
    13 
    14 
    15     //将第一个商品名设为默认选中项
    16     m_combo.SetCurSel(0);
    17 }

    (2)处理组合框所需控制事件

     1 void CDelDlg::OnCbnSelchangeCombo1()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     CString text;
     6     //获取当前选中项
     7     int index = m_combo.GetCurSel();
     8     //获取当前内容
     9     m_combo.GetLBText(index, text);
    10 
    11     //需要包含#include "InfoFile.h"
    12     CInfoFile file;
    13     file.ReadDocline(); //读取商品信息
    14     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    15     {
    16         if (text == it->name.c_str())
    17         {
    18             m_price = it->price;
    19             m_num = 0;
    20             UpdateData(FALSE); //内容更新到对应的控件
    21         }
    22     }
    23 
    24     
    25 }

    (3)确定按钮功能实现

     1 void CDelDlg::OnBnClickedButton1()
     2 {
     3     // TODO:  在此添加控件通知处理程序代码
     4 
     5     //获取控件上的内容,更新到对应关联的变量中
     6     UpdateData(TRUE);
     7 
     8     if (m_num == 0)
     9     {
    10         MessageBox(TEXT("个数不能为0"));
    11         return;
    12     }
    13 
    14     CString type;
    15     //获取当前选中项
    16     int index = m_combo.GetCurSel();
    17     //获取组合框当前内容
    18     m_combo.GetLBText(index, type);
    19 
    20     CString str;
    21     str.Format(_T("删除商品:%s 
    单价:%d 
    个数:%d "), type, m_price, m_num);
    22     MessageBox(str);
    23 
    24 
    25     //需要包含#include "InfoFile.h"
    26     CInfoFile file;
    27     file.ReadDocline(); //读取商品信息
    28     for (list<msg>::iterator it = file.ls.begin(); it != file.ls.end(); it++)
    29     {
    30         if (type == it->name.c_str())
    31         {
    32             it->num = it->num - m_num;
    33         }
    34     }
    35     file.WirteDocline(); //更新文件内容
    36 
    37     
    38 
    39     m_num = 0;
    40     UpdateData(FALSE); //更新到对应的控件
    41 }

    (4)取消按钮功能实现

    1 void CDelDlg::OnBnClickedButton2()
    2 {
    3     // TODO:  在此添加控件通知处理程序代码
    4 
    5     m_combo.SetCurSel(0); //选择第0项目
    6     m_num = 0;
    7     OnCbnSelchangeCombo1();
    8 }

    十一、菜单栏添加

    1、找Menu菜单

    切换到资源视图的Menu,删除掉所有默认(帮助除外):

    2、添加事件处理程序

    右键菜单栏项,添加事件处理程序,选择COMMAND 消息类型,添加至CMainFrame框架类中。

    3、在事件处理函数中发送自定义信号,其它菜单操作类似。

    1 //个人信息菜单
    2 void CMainFrame::On32772()
    3 {
    4     // TODO:  在此添加命令处理程序代码
    5 ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_A, (WPARAM)NM_A, (LPARAM)0);
    6 }

    在学习MFC总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    c# 测试篇之Linq性能测试
    F# 笔记
    c# DataSource和BindingSource
    .net中配置的保存格式笔记
    泛型约束(转)
    c# 调用showDialog后需要Dispose
    c# 实现ComboBox自动模糊匹配
    c# 二进制或算法实现枚举的HasFlag函数
    C# WinForm自定义控件整理
    微软中文MSDN上的一些文章链接
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_MFC_03.html
Copyright © 2020-2023  润新知