MFC-第四节 案例:销售系统(一)

新建项目

1. 根据向导创建项目

  1. 新建MFC项目,项目名称(SaleSystem)、设置路径
  2. 应用程序类型:
    1. 应用程序类型:单个文档
    2. 项目样式(里面有4种样式):选择MFC standard(MFC 标准)
    3. 下一步,直到“用户界面功能”
  3. 用户界面功能
    1. command bar(menu/toolbar/ribbon)(命令栏(菜单/工具栏/功能区)):选择使用经典菜单
    2. classic menu options:选择 无,即去掉工具栏
  4. 点击完成,即可

2. 添加预处理指令

  1. 由于微软在VS2013中不建议再使用C/C++的传统库函数scanf,strcpy,sprintf等,所以直接使用这些库函数会提示C4996错误。
  2. VS建议采用带_s的函数,如scanf_s、strcpy_s,但这些并不是标准C/C++函数。要想继续使用此函数,需要添加 _CRT_SECURE_NO_WARNINGS这个预定义。
  3. 在项目 -> 属性 -> C/C++->预处理器 -> 预处理器定中添加 _CRT_SECURE_NO_WARNINGS:,或者在使用这些函数的.cpp文件中导入这个宏 #define _CRT_SECURE_NO_WARNINGS

3. 设置窗口属性

  1. 设置图标
    1. 将准备好的icon图片复制到项目根目录res文件夹中
    2. 打开资源视图,右击Icon->添加资源->Icon->导入->打开res->选择导入的图片->打开即可
    3. 添加的2张图片,默认ID为IDI_ICON1、IDI_ICON2,右击IDI_ICON1->属性,修改ID分别为:IDI_ICON_WIN(头像)/IDI_ICON_RE
    4. 在CMainFrame的 OnCreate()中添加如下代码:

       //设置图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数
       SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN));
      
  2. 设置窗口大小和居中显示
    1. 还是在CMainFrame的OnCreate()中接着写代码:

       //设置项目图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数
       SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN));
       //设置窗口的位置和大小:CWnd::MoveWindow
       //0, 0, 起点坐标x和y
       //800, 500, 窗口宽度和高度
       MoveWindow(0, 0, 800, 500);
                  
       //将窗口移动到屏幕中央,CWnd::CenterWindow
       CenterWindow();
      
  3. 设置窗口标题
    1. 在CSaleSystemDoc文档类中的OnNewDocument()函数中添加如下代码:

       //设置窗口标题,CDocument::SetTitle
       SetTitle(TEXT("销售管理系统"));
      
    2. 注意:标题样式:标题左内容-标题右内容

      1. 如果是在CMainFrame的OnCreate()中设置,那么设置的就是”标题右内容”,运行结果为: 无标题-销售管理系统
      2. 如果在CSaleSystemDoc文档类中的OnNewDocument()函数中设置,那么设置的事”标题左内容”,运行结果为:销售管理系统- SaleSystem

        图4

文件处理

  1. 作用
    1. 用于记录当前登录登录的账号、密码
    2. 用于记录当前所有商品的信息
  2. 内容格式分别如下 图4
  3. 设计文件处理类CInfoFile
    1. 添加文件处理类CInfoFile
      1. 类视图下,右击项目SaleSystem-添加->类
      2. 设置类名CInfoFile,.h/.cpp文件名为InfoFile
      3. 基类不继承任何类,点击确定
    2. 头文件(InfoFile.h)的设计
      1. 定义两个配置文件路径宏:
        1. 指定保存登录、商品文件的路径+文件名.后缀名
         #define _F_LOGIN "./login.ini"
         #define _F_STOCK "./stock.txt"
        
      2. 文件代码如下

         //InfoFile.h
         #pragma once
         #include <list>
         #include <fstream>
         #include <iostream>
         #include <string>
                    
                    
         #define _F_LOGIN "./login.ini"
         #define _F_STOCK "./stock.txt"
                    
         using namespace std;
                    
         //1. 添加文件信息结构体,具体如下:
         struct msg
         {
         	int id;				//商品id
         	string name;	//商品名
         	int price;			//商品价格
         	int num;			//商品个数
         };
                    
         //2. 商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量:
         //3. 项目中需要读写的文件有两种,用户信息配置文件和商品信息文件。具体 API 接口如下:
         class CInfoFile
         {
         public:
         	CInfoFile();
         	~CInfoFile();
                    
         	list<msg> ls;	//存储商品容器
         	int num;			//用来记录商品个数
                    
         	//读取登陆信息
         	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. cpp文件实现

       #include "stdafx.h"
       #include "InfoFile.h"
       CInfoFile::CInfoFile()
       {
       }
       CInfoFile::~CInfoFile()
       {
       }
              
       //读取登陆信息
       void CInfoFile::ReadLogin(CString &name, CString &pwd)
       {
       	ifstream ifs; //创建文件输入对象
       	ifs.open(_F_LOGIN); //打开文件
              
       	char buf[1024] = { 0 };
              
       	ifs.getline(buf, sizeof(buf)); //读取一行内容
       	name = CString(buf);			 //char *转换为CString
              
       	ifs.getline(buf, sizeof(buf));
       	pwd = CString(buf);
              
       	ifs.close(); //关闭文件
       }
              
       //修改密码
       void CInfoFile::WritePwd(char* name, char* pwd)
       {
       	ofstream ofs;	 //创建文件输出对象
       	ofs.open(_F_LOGIN); //打开文件
              
       	ofs << name << endl; //name写入文件
       	ofs << pwd << endl;	//pwd写入文件
              
       	ofs.close();	//关闭文件
       }
              
       //读取商品信息
       void CInfoFile::ReadDocline()
       {
       	ifstream ifs(_F_STOCK); //输入方式打开文件
              
       	char buf[1024] = { 0 };
       	num = 0;	//初始化商品数目为0
       	ls.clear();
       	//取出表头
       	ifs.getline(buf, sizeof(buf));
              
       	while (!ifs.eof()) //没到文件结尾
       	{
       		msg tmp;
              
       		ifs.getline(buf, sizeof(buf)); //读取一行
       		num++;	//商品数目加一
              
       		//AfxMessageBox(CString(buf));
       		char *sst = strtok(buf, "|"); //以“|”切割
       		if (sst != NULL)
       		{
       			tmp.id = atoi(sst); //商品id
       		}
       		else
       		{
       			break;
       		}
              
       		sst = strtok(NULL, "|");
       		tmp.name = sst;	//商品名称
              
       		sst = strtok(NULL, "|");
       		tmp.price = atoi(sst);	//商品价格
              
       		sst = strtok(NULL, "|");
       		tmp.num = atoi(sst);	//商品数目
              
       		ls.push_back(tmp); //放在链表的后面
       	}
              
       	ifs.close(); //关闭文件
       }
              
       //商品写入文件
       void CInfoFile::WirteDocline()
       {
       	ofstream ofs(_F_STOCK);//输出方式打开文件
              
       	if (ls.size() > 0)	//商品链表有内容才执行
       	{
       		ofs << "商品ID|商品名称|商品价格|库存" << endl; //写入表头
              
       		//通过迭代器取出链表内容,写入文件,以“|”分隔,结尾加换行
       		for (list<msg>::iterator it = ls.begin(); it != ls.end(); it++)
       		{
       			ofs << it->id << "|";
       			ofs << it->name << "|";
       			ofs << it->price << "|";
       			ofs << it->num << endl;
       		}
       	}
              
       	ofs.close();//关闭文件
       }
              
       //添加新商品
       //name:商品名称,num:库存,price:价格
       void CInfoFile::Addline(CString name, int num, int price)
       {
       	msg tmp;
              
       	if (ls.size() > 0)
       	{
       		//商品名称,库存,价格有效
       		if (!name.IsEmpty() && num > 0 && price > 0)
       		{
       			tmp.id = ls.size() + 1;	//id自动加1
       			CStringA str;
       			str = name;	//CString转CStirngA
       			tmp.name = str.GetBuffer(); //CStirngA转char *,商品名称
       			tmp.num = num;	//库存
       			tmp.price = price;	//价格
              
       			ls.push_back(tmp);	//放在链表的后面
       		}
       	}
       }
      

登录对话框

  1. ui设计
    1. 添加对话框资源(ID修改为DIALOG_LOGIN),添加所需控件:
      1. 点击资源视图->Dialog->右击->插入Dialog
      2. 右击->属性->ID修改为DIALOG_LOGIN
    2. 选中对话框 -> 右击 -> 添加类 -> 类名:CLoginDlg
    3. 布局页面
      1. 修改对话框标题为:登录窗口
        1. 右击->属性->caption: 登录窗口
      2. 拖一个Static Text 控件,修改为:“用户名:”
      3. 拖一个Eidt control 控件,作为用户名输入框
      4. 重复2、3步骤,布局密码部分,注意密码的Eidt control 属性password要设置为true
      5. 再分别过一个button,登录、退出
    4. 根据需求,控件关联所需变量
      1. 用户名编辑区关联CString m_user,密码登陆框关联CString m_pwd。
        1. 右击用户框,添加变量->类别选择“值(value)”->m_user
        2. 同理关联密码框
      2. 双击自动添加登录、退出时间函数监听
    5. 搭建完成如下图: 图4
  2. 功能实现
    1. 登录窗口的创建
      1. 程序启动时应该先加载登录窗口
      2. 在应用程序类CSaleSystemApp的InitInstance() 里面的APP 创建之前创建登陆对话框:
        1. 在InitInstance()方法中找到 CWinApp::InitInstance();
        2. 在这句话上面写(导入头文件CLoginDlg.h)

           CLoginDlg dlg; //创建登陆对话框,需要头文件#include "LoginDlg.h"
           dlg.DoModal(); //以模态方式运行
          
      3. 运行项目可以看到,加载的是登录窗口
    2. 在对话框类中,重写 OnInitDialog 函数,进行初始化,设置一些默认登录信息。
      1. 视图类中右击CLoginDlg类->属性->点击一个绿色矩形小图标(重写)->OnInitDialog->右边下拉箭头->add即可。
      2. OnInitDialog里面添加代码

         // 初始化登陆信息
         //1. 创建文件类
         CInfoFile file;
         CString name;
         CString pwd;
         //2. 获取本地文件存储的用户名、密码
         file.ReadLogin(name, pwd);
                    
         //3. 显示用户名、密码    
         m_user = name;
         m_pwd = pwd;
                        
         //将变量 同步到控件中
         UpdateData(FALSE);
        
      3. 将准备好的login.ini文件复制到项目根目录下,里面写好了登录的用户名、密码
  3. 登陆按钮功能实现

     // CLoginDlg 消息处理程序
     void CLoginDlg::OnBnClickedButton1()
     {
     	// TODO: 在此添加控件通知处理程序代码
     	//登陆功能
        
     	UpdateData(TRUE); //拿到文本框最新的数据
        
     	//检测数据有效性  
     	if (m_user.IsEmpty() || m_pwd.IsEmpty())
     	{
     		MessageBox(TEXT("输入的内容不能为空"));
     		return;
     	}
        
     	CInfoFile file;
     	CString name;
     	CString pwd;
     	//获取本地存储的用户名、密码
     	file.ReadLogin(name, pwd);
        
     	if (name == m_user)
     	{
     		if (pwd == m_pwd)
     		{
     			//关闭当前对话框
     			CDialogEx::OnCancel();
     		}
     		else
     		{
     			MessageBox(TEXT("输入的密码有误!"));
     		}
     	}
     	else
     	{
     		MessageBox(TEXT("输入的用户名有误!"));
     		return;
     	}
     }
    
  4. 取消按钮功能实现

     void CLoginDlg::OnBnClickedButton2()
     {
     	// TODO: 在此添加控件通知处理程序代码
     	//退出按钮实现
     	exit(0);
     }
    
  5. 右上角关闭按钮功能实现
    1. 选中对话框模板 -> 右击 -> 属性 -> 消息 -> WM_CLOSE->add
    2. 代码实现

       void CLoginDlg::OnClose()
       {
       	// TODO: 在此添加消息处理程序代码和/或调用默认值
       	//CDialogEx::OnClose();
       	//退出程序
       	exit(0);
       	CDialogEx::OnClose();
       }
      
  6. 编辑区点击回车键会关闭对话框问题解决
    1. 类视图中选中CLoginDlg类 -> 右击 -> 属性 -> 重写->OnOK->Add
    2. 注释代码

       void CLoginDlg::OnOK()
       {
       	// TODO: 在此添加专用代码和/或调用基类
              
       	//注释改行,解决回车关闭对话框问题
       	//CDialogEx::OnOK();
       }
      

静态拆分窗口

  1. 自定义MFC试图类
    1. 可以将主页窗口拆分为2部分,如下图: 图4
    2. 自定义两个类:CSelectView和CDispalyView(它的基类必须是视图类)。
      1. CSelectView继承于CTreeView,CDispalyView继承于CFormView。
      2. 创建CSelectView类:
        1. 切换到解决方案资源管理器-> 右击源文件->添加新建项->左边列表选择MFC->右边选择MFC类->类名为CSelectView->添加
        2. 基类设置,展开下拉列表,选择基类为CTreeView->点击确定
      3. 创建CDispalyView类:
        1. 注意: 创建继承于CFormView的类时方法有区别!!!(继承于CFormView类必须有对话框)
        2. 资源视图->Dialog->右击,插入Dialog,修改ID为IDD_DISPALYVIEW
        3. 右击对话框->添加类->设置基类为CFormView,类名为CDispalyView,确定即可 (这个类就相当于iOS中的:类+xib)
  2. 通过CSplitterWnd类拆分窗口
    1. 在CMainFrame类中,声明CSplitterWnd类型的成员变量:

       protected:  // 控件条嵌入成员
       CSplitterWnd m_spliter;
      
    2. 重写框架类CMainFrame的OnCreateClient函数
      1. 类视图中右击CMainFrame类->属性->点击重写图标->OnCreateClient->add
      2. 把OnCreateClient()函数的返回值改为Return TRUE:
      3. 静态拆分实现代码如下:(注意别忘了导入头文件CSelectView、CDispalyView)

         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;
         }
        
    3. 运行程序,点击登录,进入主窗口,就会发现主窗口被分成了2部分,左边部分、右边部分。

树视图功能实现

  1. 添加功能节点
    1. 加载图标资源
      1. 资源视图->Icon->右击->添加资源->Icon->导入->打开res文件夹->选择re.ico->打开
      2. 图标资源ID改为:IDI_ICON_RE
    2. CSelectView类中声明相应变量:

       CTreeCtrl* m_treeCtrl; //树控件
       CImageList m_imageList;//图标列表
      
    3. 重写CSelectView的OnInitUpdate函数(步骤略)
    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. 功能节点相应消息处理
    1. 类视图->CSelectView右击->属性->选择消息->TVN_SELECHANGED->Add
    2. 在上面函数,实现获取当前节点选中内容:

       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("库存删除"))
       	{
       	}
          
       }
      

个人信息管理窗口

ui设计

  1. 添加对话框资源(ID修改为DIALOG_USER),添加所需控件
    1. 资源视图->Dialog->右击:插入Dialog
    2. 在窗口属性中,Border改为None,Style改为Child:
    3. 页面布局
      1. 拖入一个Group Box,输入内容为“我的信息”
      2. 再拖入一个,为“修改密码”,然后选中这2个,在工具栏中,点击垂直、水平居中图标
      3. 拖4个static text,身份、用户名、密码、确定密码,然后选中这4个,点击工具栏右对齐图标
      4. 拖入4个edit control,将身份、edit框选中,选中工具栏中的顶端对齐图标,一次设置
      5. 将身份、用户名的属性readOnly设置为TRUE;将密码、确定密码属性password设置为TRUE
    4. 布局完的如下图

      图4

  2. 添加对话框相应的类
    1. 选中对话框 -> 右击 -> 添加类 -> 类名:CUserDlg,基类选择CFormView
  3. 根据需求,控件关联所需变量
    1. 身份编辑区关联CString m_user,用户名编辑框关联CString m_name,
      1. 右击->添加变量->类别选择为值(value)
    2. 新密码编辑框关联CString m_newPwd,确定密码编辑框关联CString m_surePwd。
  4. 添加“确定、取消按钮”,并双击关联事件

界面挂载

  1. 目的:点击CSelectView中相应的节点,显示相应的窗口
  2. 实现思路:
    1. 触发事件在CSelectView的OnTvnSelchanged方法中,针对相应的节点发送一个消息通知。
    2. 接收消息,然后处理消息,加载相应节点的窗口,在CMainFrame类中处理

自定义信息接收

  1. 在CMainFrame 框架类中,添加自定义消息宏(定义消息类型)

     //MainFrm.h中
     //WM_USER 是用户自定义消息的一个起始值 (系统自定义的)
     //WM_USER+100是为了区分系统消息和用户消息,避免冲突
     #define NM_A	(WM_USER + 100)
     #define NM_B	(WM_USER + 101)
     #define NM_C	(WM_USER + 102)
     #define NM_D	(WM_USER + 103)
     #define NM_E	(WM_USER + 104)
    
  2. 在CMainFrame框架类BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间添加自定义消息入口,与自定义消息处理函数绑定。(监听消息相当于iOS的addobserver

     BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
     	ON_WM_CREATE()
     	//ON_MESSAGE响应的是自定义消息
     	//产生NM_X消息,自动调用OnMyChange函数
     	ON_MESSAGE(NM_A, OnMyChange)
     	ON_MESSAGE(NM_B, OnMyChange)
     	ON_MESSAGE(NM_C, OnMyChange)
     	ON_MESSAGE(NM_D, OnMyChange)
     	ON_MESSAGE(NM_E, OnMyChange)
     END_MESSAGE_MAP()
    
  3. 在CMainFrame框架类中添加自定义消息处理函数,并实现

     //.h文件中,声明自定义消息处理函数
     afx_msg LRESULT OnMyChange(WPARAM wParam, LPARAM lParam);
        
     //.cpp中实现
     LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam)
     {
      CCreateContext   Context;
     	switch (wParam)
     	{
     	case NM_A:
     	   //界面挂载
     	   //如果是NM_A信号,则挂载CUserDlg窗口,后面界面的挂载以此类推。
     	   {
         		//MessageBox(_T("NM_A"));
         		//CUserDlg类需要包含头文件#include "UserDlg.h"
             	Context.m_pNewViewClass = RUNTIME_CLASS(CUserDlg); 
             	Context.m_pCurrentFrame = this;
             	Context.m_pLastView = (CFormView *)m_spliter.GetPane(0, 1);
             	m_spliter.DeleteView(0, 1);
             	m_spliter.CreateView(0, 1, RUNTIME_CLASS(CUserDlg), CSize(600,500), &Context);
             	CUserDlg *pNewView = (CUserDlg *)m_spliter.GetPane(0, 1);
             	m_spliter.RecalcLayout();
             	pNewView->OnInitialUpdate();
             	m_spliter.SetActivePane(0, 1);
         	}
     		break;
     	case NM_B:
     		MessageBox(_T("NM_B"));
     		break;
     	case NM_C:
     		MessageBox(_T("NM_C"));
     		break;
     	case NM_D:
     		MessageBox(_T("NM_D"));
     		break;
     	case NM_E:
     		MessageBox(_T("NM_E"));
     		break;
     	default:
     		MessageBox(_T("error"));
     	}
     	return 0;
     }
    

自定义信息发送(就相当于iOS的发送通知)

  1. CMainFrame类监听消息
  2. CSelectView类发送消息
  3. 在CSelectView的OnTvnSelchanged函数中,发送自定义信号:

     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("个人信息"))
     	{
     		//需要包含框架类头文件#include "MainFrm.h" 
     		//CWnd::PostMessage 将一个消息放入窗口的消息队列
     		//AfxGetMainWnd():框架窗口对象的指针
     		//AfxGetMainWnd()->GetSafeHwnd():获取返回窗口的句柄,CWnd::GetSafeHwnd
     		//NM_A:发送自定义消息
     		//(WPARAM)NM_A:指定了附加的消息信息
     		//(LPARAM)0:指定了附加的消息信息,此参数这里没有意义
     		::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_A, (WPARAM)NM_A, (LPARAM)0);
     	}
     	else if (str == TEXT("销售管理"))
     	{
     		::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_B, (WPARAM)NM_B, (LPARAM)0);
     	}
     	else if (str == TEXT("库存信息"))
     	{
     		::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_C, (WPARAM)NM_C, (LPARAM)0);
     	}
     	else if (str == TEXT("库存添加"))
     	{
     		::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_D, (WPARAM)NM_D, (LPARAM)0);
     	}
     	else if (str == TEXT("库存删除"))
     	{
     		::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_E, (WPARAM)NM_E, (LPARAM)0);
     	}
     }
    

个人信息界面功能实现

  1. 在对话框类中,重写 OnInitialUpdate 函数,进行初始化

     void CUserDlg::OnInitialUpdate()
     {
     	CFormView::OnInitialUpdate();
        
     	// TODO: 在此添加专用代码和/或调用基类
     	CInfoFile file;	//需要头文件#include "InfoFile.h"
     	CString name, pwd;
     	file.ReadLogin(name, pwd); //读取文件的用户名和密码
        
     	//初始化个人信息
     	m_user = TEXT("销售员");	//身份
     	m_name = name;	//用户名
        
     	UpdateData(FALSE); //把数据更新到控件上
        
     }
    
  2. 确定修改密码按钮功能实现

     void CUserDlg::OnBnClickedButton1()
     {
     	// TODO: 在此添加控件通知处理程序代码
     	UpdateData(TRUE);//更新控件内容到对应的变量中
        
     	if (m_newPwd.IsEmpty() || m_surePwd.IsEmpty())
     	{
     		MessageBox(TEXT("输入密码不能为空"));
     		return;
     	}
        
     	if (m_newPwd != m_surePwd)
     	{
     		MessageBox(TEXT("输入密码和确定密码不相等"));
     		return;
     	}
        
     	CInfoFile file;	//需要头文件#include "InfoFile.h"
     	CString name, pwd;
     	file.ReadLogin(name, pwd); //读取文件的用户名和密码
        
     	if (m_surePwd == pwd)
     	{
     		MessageBox(TEXT("输入密码和旧密码相等"));
     		return;
     	}
        
     	//把用户名和密码的CString类型转为char *
     	char* tmpName, * tmpPwd;
     	//用户名
     	CStringA tmp1;
     	tmp1 = name;
     	tmpName = tmp1.GetBuffer();
     	//密码
     	CStringA tmp2;
     	tmp2 = m_surePwd;
     	tmpPwd = tmp2.GetBuffer();
        
     	file.WritePwd(tmpName, tmpPwd); //修改密码
        
     	MessageBox(TEXT("密码修改成功"));
        
     	//输入框内容清空
     	m_surePwd.Empty();
     	m_newPwd.Empty();
     	UpdateData(FALSE); //把数据更新到控件上
     }
    
  3. 取消按钮功能实现

     void CUserDlg::OnBnClickedButton3()
     {
     	// TODO: 在此添加控件通知处理程序代码
     	//输入框内容清空
     	m_surePwd.Empty();
     	m_newPwd.Empty();
     	UpdateData(FALSE); //把数据更新到控件上
        
     }
    
Table of Contents