MFC——对话框的创建及使用(下)

简介: MFC——对话框的创建及使用

综合案例

  • 通过MFC向导创建综合案例(销售信息管理系统)项目。

项目总体框架

整个项目分为登录界面、主界面。而主界面分裂成两个界面显示,分别为左侧选择界面和右侧显示界面。功能上分别有个人信息管理、销售管理窗口、库存信息窗口、库存添加窗口、库存删除窗口以及菜单栏。


文件处理

  • 项目中使用到将数据保存到文件进行保存的功能,这部分设计成一个单独的文件处类CInfoFile。

在解决方案中添加类–>CInfoFile。


  • CInfoFole.h
#pragma once
#include <list>
#include <fstream>
#include <iostream>
#include <string>
#include "pch.h"
#define _F_LOGIN "./login.ini"
#define _F_STOCK "./stock.txt"
struct msg
{
  int id;
  std::string name;
  int price;
  int num;
};
class CInfoFile
{
public:
  CInfoFile();
  ~CInfoFile();
  //读取登录信息
  void ReadLogin(CString& name, CString& pwd);
  //修改密码
  void WritePwd(char* name, char* pwd);
  //读取商品数据
  void ReadDocline();
  //商品写入文件
  void WriteDocline();
  //添加新商品
  void AddLine(CString name, int num, int price);
  std::list<msg> ls; //存储商品容器
  int num; //记录商品个数
};


  • CInfoFole.cpp
#include "pch.h"
#include "CInfoFile.h"
CInfoFile::CInfoFile()
{
}
CInfoFile::~CInfoFile()
{
}
void CInfoFile::ReadLogin(CString& name, CString& pwd)
{
  std::ifstream ifs;//创建文件输入对象
  ifs.open(_F_LOGIN);//打开文件
  char buf[1024] = { 0 };
  ifs.getline(buf, sizeof(buf));//读取第一行
  name = CString(buf);//char * 转为CString
  memset(buf, 0, sizeof(buf));//清空buf
  ifs.getline(buf, sizeof(buf));
  pwd = CString(buf);
  ifs.close();//关闭文件
}
void CInfoFile::WritePwd(char* name, char* pwd)
{
  std::ofstream ofs;//创建文件输出对象
  ofs.open(_F_LOGIN);//打开文件
  ofs << name << std::endl;//将name写入文件并换行
  ofs << pwd << std::endl;//将pwd写入文件并换行
  ofs.close();//关闭文件
}
void CInfoFile::ReadDocline()
{
  std::ifstream ifs(_F_STOCK);//输入方式打开文件
  char buf[1024] = { 0 };
  num = 0;//初始化商品数目
  ls.clear();//初始化容器
  //取出表头
  ifs.getline(buf, sizeof(buf));
  while (!ifs.eof())//循环执行到文件结尾
  {
  msg tmp;//声明暂存变量
  ifs.getline(buf, sizeof(buf));
  num++;
  char* set = strtok(buf, "|");//以|为分隔符切割字符串
  if (set != NULL)
  {
    tmp.id = std::atoi(set);//第一个为商品id
  }
  else
  {
    break;//找不到分隔符则跳出循环
  }
  set = strtok(NULL, "|");
  tmp.name = set;//商品名称
  set = strtok(NULL, "|");
  tmp.price = std::atoi(set);//商品价格
  set = strtok(NULL, "|");
  tmp.num = std::atoi(set);//商品数目
  ls.push_back(tmp);
  }
  ifs.close();//关闭文件
}
void CInfoFile::WriteDocline()
{
  std::ofstream ofs(_F_STOCK);//输出方式打开文件
  if (ls.size() > 0)
  {
  ofs << "商品ID|商品名称|商品价格|库存" << std::endl;//写入表头
  //通过迭代器写入内容
  for (auto it = ls.begin(); it != ls.end(); ++it)
  {
    ofs << it->id << "|";
    ofs << it->name << "|";
    ofs << it->price << "|";
    ofs << it->num << std::endl;
  }
  }
  ofs.close();//关闭文件
}
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;
    CStringA str;
    str = name;
    tmp.name = str.GetBuffer();
    tmp.num = num;
    tmp.price = price;
    ls.push_back(tmp);//放在链表后
  }
  }
}


登录对话框

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

20200409170624395.png

选中对话框 -> 右击 -> 添加类 -> 类名:CLoginDlg,添加关联变量。

20200409170656181.png具体功能实现:


  • 需要重写OnInitDialog
  • 在应用程序类CSaleSystemApp的InitInstance() 里面的APP 创建之前创建登陆对话框。
CLoginDlg dlg;  //创建登陆对话框,需要头文件#include "LoginDlg.h"
  dlg.DoModal();  //以模态方式运行


  • 登录按钮功能实现。

  • CLoginDlg.h


#pragma once
// CLoginDlg 对话框
class CLoginDlg : public CDialogEx
{
  DECLARE_DYNAMIC(CLoginDlg)
public:
  CLoginDlg(CWnd* pParent = nullptr);   // 标准构造函数
  virtual ~CLoginDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
  enum { IDD = IDD_LOGIN };
#endif
protected:
  virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
  DECLARE_MESSAGE_MAP()
private:
  CString m_user;
  CString m_pwd;
public:
  virtual BOOL OnInitDialog();
  afx_msg void OnBnClickedButton2();
  afx_msg void OnBnClickedButton1();
  afx_msg void OnClose();
  virtual void OnOK();
};


  • CLoginDlg.cpp
// CLoginDlg.cpp: 实现文件
//
#include "pch.h"
#include "SaleSystem.h"
#include "CLoginDlg.h"
#include "afxdialogex.h"
#include "CInfoFile.h"
// CLoginDlg 对话框
IMPLEMENT_DYNAMIC(CLoginDlg, CDialogEx)
CLoginDlg::CLoginDlg(CWnd* pParent /*=nullptr*/)
  : CDialogEx(IDD_LOGIN, pParent)
  , m_user(_T(""))
  , m_pwd(_T(""))
{
}
CLoginDlg::~CLoginDlg()
{
}
void CLoginDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialogEx::DoDataExchange(pDX);
  DDX_Text(pDX, IDC_EDIT1, m_user);
  DDX_Text(pDX, IDC_EDIT2, m_pwd);
}
BEGIN_MESSAGE_MAP(CLoginDlg, CDialogEx)
  ON_BN_CLICKED(IDC_BUTTON2, &CLoginDlg::OnBnClickedButton2)
  ON_BN_CLICKED(IDC_BUTTON1, &CLoginDlg::OnBnClickedButton1)
  ON_WM_CLOSE()
END_MESSAGE_MAP()
// CLoginDlg 消息处理程序
BOOL CLoginDlg::OnInitDialog()
{
  CDialogEx::OnInitDialog();
  // TODO:  在此添加额外的初始化
  m_user = TEXT("斧头帮帮主");
  m_pwd = TEXT("123456");
  UpdateData(FALSE);//内容更新到对应控件
  return TRUE;  // return TRUE unless you set the focus to a control
      // 异常: OCX 属性页应返回 FALSE
}
void CLoginDlg::OnBnClickedButton2()
{
  // TODO: 在此添加控件通知处理程序代码
  UpdateData(TRUE);//更新控件数据到数据区
  CInfoFile file;
  CString user, pwd;
  user = TEXT("斧头帮帮主");
  pwd = TEXT("123456");
  //file.ReadLogin(user, pwd);
  if (m_user == user)
  {
  if (m_pwd != pwd)
  {
    MessageBox(TEXT("密码错误"));
    m_user.Empty();
    m_pwd.Empty();
  }
  else
  {
    CDialogEx::OnOK();
  }
  }
  else
  {
  MessageBox(TEXT("用户不存在"));
  m_user.Empty();
  m_pwd.Empty();
  }
}
void CLoginDlg::OnBnClickedButton1()
{
  // TODO: 在此添加控件通知处理程序代码
  exit(0);
}
void CLoginDlg::OnClose()
{
  // TODO: 在此添加消息处理程序代码和/或调用默认值
  exit(0);
  //CDialogEx::OnClose();
}
void CLoginDlg::OnOK()
{
  // TODO: 在此添加专用代码和/或调用基类
  //CDialogEx::OnOK();
}


静态拆分窗口

实现主界面的拆分显示,左侧选择界面显示(CSelectView)和右侧显示界面(CDisplayView)。

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


  • 在CMainFrame类中,声明CSplitterWnd类型的对象:
private:
  CSplitterWnd m_spliter; // 切分窗口类对象


  • 重写框架类CMainFrame的OnCreateClient函数


BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
  // TODO: 在此添加专用代码和/或调用基类
  //return CFrameWnd::OnCreateClient(lpcs, pContext);
  //静态拆分窗口
  m_spliter.CreateStatic(this, 1, 2);
  m_spliter.CreateView(0, 0, RUNTIME_CLASS(CSelectView), CSize(200, 500), pContext);
  m_spliter.CreateView(0, 1, RUNTIME_CLASS(CDisplayView), CSize(600, 500), pContext);
  return TRUE;
}


  • 显示如下:

2020040917160369.png

左侧选择界面树视图实现

  • 添加树视图图标。
  • CSelectView类中声明相应变量:

CTreeCtrl *m_treeCtrl;  //树控件
  CImageList m_imageList; //图标列表


  • 重写CSelectView的OnInitUpdate函数


void CSelectView::OnInitialUpdate()
{
  CTreeView::OnInitialUpdate();
  // TODO: 在此添加专用代码和/或调用基类
  HICON icon = AfxGetApp()->LoadIconW(IDI_ICON_RE);
  //图片列表的串讲,指定图标的宽度和高度
  m_imageList.Create(30, 30, ILC_COLOR32, 1, 1);
  m_imageList.Add(icon);
  //获取树视图中的控件
  m_treeCtrl = &GetTreeCtrl();
  //树控件设置图片列表
  m_treeCtrl->SetImageList(&m_imageList, TVSIL_NORMAL);
  //树控件设置节点
  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);
}

2020040917175968.png

功能节点消息处理

当左侧窗口点击树节点,会发送对应的消息给mainframe,主窗口接收到对应消息后会进行相应处理,将右侧窗口挂载成不同的显示界面。


  • 树节点改变响应处理:


void CSelectView::OnTvnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
  LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
  // TODO: 在此添加控件通知处理程序代码
  //获取当前项目
  HTREEITEM item = m_treeCtrl->GetSelectedItem();
  //根据所选项目获取内容
  CString str = m_treeCtrl->GetItemText(item);
  //MessageBox(str);
  if (str == TEXT("个人信息"))
  {
  ::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);
  }
  *pResult = 0;
}


  • 在CMainFrame.h中声明了对应的消息宏:
#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)


  • 在CMainFrame.cpp中的宏节点声明对应的消息处理声明:


BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  ON_WM_CREATE()
  ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
  ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
  ON_WM_SETTINGCHANGE()
  //自定义消息
  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)
  ON_COMMAND(ID_EDIT_UNDO, &CMainFrame::OnEditUser)
  ON_COMMAND(ID_EDIT_CUT, &CMainFrame::OnEditSell)
  ON_COMMAND(ID_EDIT_COPY, &CMainFrame::OnEditCopy)
  ON_COMMAND(ID_EDIT_PASTE, &CMainFrame::OnEditAdd)
  ON_COMMAND(ID_32771, &CMainFrame::OnEditDel)
END_MESSAGE_MAP()


  • 自定义对应的消息处理函数
//自定义处理消息函数
LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam)
{
  CCreateContext Context;
  switch (wParam)
  {
  case NM_A:
  {
  //MessageBox(TEXT("个人信息界面显示"));
  //界面挂载
  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:
  {
  Context.m_pNewViewClass = RUNTIME_CLASS(CSellDlg);
  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(CSellDlg), CSize(600, 0), &Context);
  CSellDlg* pNewView = (CSellDlg*)m_spliter.GetPane(0, 1);
  m_spliter.RecalcLayout();
  pNewView->OnInitialUpdate();
  m_spliter.SetActivePane(0, 1);
  }
  break;
  case NM_C:
  {
  Context.m_pNewViewClass = RUNTIME_CLASS(CInfoDlg);
  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(CInfoDlg), CSize(600, 0), &Context);
  CInfoDlg* pNewView = (CInfoDlg*)m_spliter.GetPane(0, 1);
  m_spliter.RecalcLayout();
  pNewView->OnInitialUpdate();
  m_spliter.SetActivePane(0, 1);
  }
  break;
  case NM_D:
  {
  Context.m_pNewViewClass = RUNTIME_CLASS(CAddDlg);
  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(CAddDlg), CSize(600, 0), &Context);
  CAddDlg* pNewView = (CAddDlg*)m_spliter.GetPane(0, 1);
  m_spliter.RecalcLayout();
  pNewView->OnInitialUpdate();
  m_spliter.SetActivePane(0, 1);
  }
  break;
  case NM_E:
  {
  Context.m_pNewViewClass = RUNTIME_CLASS(CDelDlg);
  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(CDelDlg), CSize(600, 0), &Context);
  CDelDlg* pNewView = (CDelDlg*)m_spliter.GetPane(0, 1);
  m_spliter.RecalcLayout();
  pNewView->OnInitialUpdate();
  m_spliter.SetActivePane(0, 1);
  }
  break;
  default:
  break;
  }
  /*
  if (wParam == NM_A)
  {
  //MessageBox(TEXT("个人信息界面显示"));
  //界面挂载
  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);
  }
  */
  return LRESULT();
}


个人信息管理窗口

  • 添加对话框资源(ID修改为DIALOG_USER),添加所需控件,在窗口属性中,Border改为None,Style改为Child:

20200409172442980.png

20200409172503519.png

  • 选中对话框 -> 右击 -> 添加类 -> 类名:CUserDlg,基类选择CFormView
  • 根据需求,控件关联所需变量

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

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

20200409172522396.png

  • 重写界面初始化函数OnInitDialog


// CUserDlg 消息处理程序
void CUserDlg::OnInitialUpdate()
{
  CFormView::OnInitialUpdate();
  //初始化代码
  m_user = TEXT("销售员");
  CInfoFile file;
  CString name, pwd;
  file.ReadDocline();
  file.ReadLogin(name, pwd);
  m_name = name;
  UpdateData(FALSE);
  // TODO: 在此添加专用代码和/或调用基类
}


  • 实现确定按钮功能实现



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;
  CString name, pwd;
  file.ReadLogin(name, pwd);
  //新密码与原密码要不一致
  if (m_newPwd == pwd)
  {
  MessageBox(TEXT("新密码与原密码重复!"));
  return;
  }
  //修改密码
  CStringA tmpName;
  CStringA tmpPwd;
  tmpName = name;
  tmpPwd = m_newPwd;
  file.WritePwd(tmpName.GetBuffer(), tmpPwd.GetBuffer());
  MessageBox(TEXT("修改密码成功"));
  //清空输入内容
  m_newPwd.Empty();
  m_surePwd.Empty();
  UpdateData(FALSE);
}


取消按钮功能实现


void CUserDlg::OnBnClickedButton2()
{
  // TODO: 在此添加控件通知处理程序代码
  m_surePwd.Empty();
  m_newPwd.Empty();
  UpdateData(FALSE);
}


销售管理窗口

  • 添加新对话框,

20200409173043938.png

  • 选中对话框 -> 右击 -> 添加类 -> 类名:CSellDlg,基类选择CFormView
  • 根据需求,控件关联所需变量
  • 商品名组合框关联CComboBox m_combo,单价编辑框关联int m_price,个数编辑框关联int m_num,销售信息编辑框关联CString m_sellInfo。

20200409173111404.png

  • 重写OnInitDialog 函数。



void CSellDlg::OnInitialUpdate()
{
  CFormView::OnInitialUpdate();
  // TODO: 在此添加专用代码和/或调用基类
  CInfoFile file;
  file.ReadDocline();//读取商品信息
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  m_combo.AddString((CString)it->name.c_str());
  }
  file.ls.clear();
  m_combo.SetCurSel(0);
}


  • 处理组合框处理实现


void CSellDlg::OnCbnSelchangeCombo1()
{
  // TODO: 在此添加控件通知处理程序代码
  CString text;
  int index = m_combo.GetCurSel();
  m_combo.GetLBText(index, text);//获取当前选择的字符
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  if (text == it->name.c_str())
  {
    m_price = it->price;
    m_num = 0;
    UpdateData(FALSE);//内容更新到显示空间
  }
  }
  file.ls.clear();
}


  • 购买按钮实现


void CSellDlg::OnBnClickedButton1()
{
  // TODO: 在此添加控件通知处理程序代码
  UpdateData(TRUE);//界面数据更新
  if (m_num == 0)
  {
  MessageBox(TEXT("购买个数不能为0"));
  return;
  }
  CString type;
  //获取当前选择项目
  int index = m_combo.GetCurSel();
  m_combo.GetLBText(index, type);
  CString str;
  str.Format(TEXT("商品:%s \r\n 单价:%d \r\n 总价:%d"), type, m_price, m_num, m_price * m_num);
  m_sellInfo = str;
  UpdateData(FALSE);//更新到控件显示
  MessageBox(str);
  //更新到库存文件
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  if (type == it->name.c_str())
  {
    it->num = it->num - m_num;
  }
  }
  file.WriteDocline();//更新内容
  file.ls.clear();
  m_sellInfo.Empty();//清空
  m_num = 0;
  UpdateData(FALSE);
}


  • 取消按钮实现


void CSellDlg::OnBnClickedButton2()
{
  // TODO: 在此添加控件通知处理程序代码
  //取消按钮处理
  m_combo.SetCurSel(0);//选择第一个项目
  m_sellInfo.Empty();
  m_num = 0;
  OnCbnSelchangeCombo1();
}


库存信息窗口

  • 添加对话框资源(ID修改为DIALOG_INFO),添加所需控件。View 属性为 Report(报表表模式):

20200409173351544.png

  • 选中对话框 -> 右击 -> 添加类 -> 类名:CInfoDlg,基类选择CFormView
  • 根据需求,控件关联所需变量列表控件关联CListCtrl m_list:

20200409173424548.png

  • 重写 OnInitDialog 函数,进行商品信息初始化:


void CInfoDlg::OnInitialUpdate()
{
  CFormView::OnInitialUpdate();
  // TODO: 在此添加专用代码和/或调用基类
  m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
  //初始化表
  CString field[] = { TEXT("商品ID"), TEXT("商品名称"), TEXT("商品价格"), TEXT("库存数量") };
  for (int i = 0; i < sizeof(field) / sizeof(field[0]); ++i)
  {
  m_list.InsertColumn(i, field[i], LVCFMT_CENTER, 90);
  }
  //读取数据
  CInfoFile file;
  file.ReadDocline();
  int i = 0;
  CString str;
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  str.Format(TEXT("%d"), it->id);
  m_list.InsertItem(i, str);
  int column = 1;
  m_list.SetItemText(i, column++, (CString)it->name.c_str());
  str.Format(TEXT("%d"), it->price);
  m_list.SetItemText(i, column++, str);
  str.Format(TEXT("%d"), it->num);
  m_list.SetItemText(i, column++, str);
  i++;
  }
}


库存添加窗口

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

20200409173529267.png

  • 选中对话框 -> 右击 -> 添加类 -> 类名:CAddDlg,基类选择CFormView
  • 根据需求,控件关联所需变量添加个数:商品组合框关联CComboBox m_combo,单价编辑框关联int m_price1,个数编辑框关联int m_num1。
  • 添加新产品:商品组合框关联CString m_name2,单价编辑框关联int m_price2,个数编辑框关联int m_num2。

20200409173607756.png

  • 重写 OnInitDialog 函数,进行商品信息初始化:


void CAddDlg::OnInitialUpdate()
{
  CFormView::OnInitialUpdate();
  // TODO: 在此添加专用代码和/或调用基类
  //读取文件数据
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  m_combo.AddString((CString)it->name.c_str());
  }
  file.ls.clear();
  m_combo.SetCurSel(0);
}


  • 处理组合框动作处理


void CAddDlg::OnCbnSelchangeCombo1()
{
  // TODO: 在此添加控件通知处理程序代码
  CString text;
  int index = m_combo.GetCurSel();
  m_combo.GetLBText(index, text);
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  if (text == it->name.c_str())
  {
    m_price1 = it->price;
    m_num1 = 0;
    UpdateData(FALSE);//内容更新到空间
  }
  }
  file.ls.clear();
}


  • 添加个数确定按钮实现


void CAddDlg::OnBnClickedButton1()
{
  // TODO: 在此添加控件通知处理程序代码
  UpdateData(TRUE);
  if (m_num1 == 0)
  {
  MessageBox(TEXT("个数不能为0"));
  return;
  }
  CString type;
  int index = m_combo.GetCurSel();
  m_combo.GetLBText(index, type);
  CString str;
  str.Format(TEXT("添加了商品:%s \r\n 单价:%d \r\n 个数:%d"), type, m_price1, m_num1);
  MessageBox(str);
  //更新到数据文件中
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  if (type == it->name.c_str())
  {
    it->num += m_num1;
  }
  }
  file.WriteDocline();//更新内容
  file.ls.clear();
  m_num1 = 0;
  UpdateData(FALSE);
}


  • 添加个数取消按钮实现


void CAddDlg::OnBnClickedButton2()
{
  // TODO: 在此添加控件通知处理程序代码
  //添加个数取消按键
  m_combo.SetCurSel(0);
  m_num1 = 0;
  OnCbnSelchangeCombo1();
}


  • 添加新商品确定按钮实现


void CAddDlg::OnBnClickedButton3()
{
  // TODO: 在此添加控件通知处理程序代码\
  //添加新商品确定按钮
  UpdateData(TRUE);
  if (m_num2 <= 0 || m_price2 <= 0 || m_name2.IsEmpty())
  {
  MessageBox(TEXT("输入信息有误"));
  return;
  }
  CInfoFile file;
  file.ReadDocline();
  file.AddLine(m_name2, m_num2, m_price2);
  file.WriteDocline();
  file.ls.clear();
  MessageBox(TEXT("添加成功!"));
  m_name2.Empty();
  m_num2 = 0;
  m_price2 = 0;
  UpdateData(FALSE);
}


  • 添加新商品取消按钮实现


void CAddDlg::OnBnClickedButton4()
{
  // TODO: 在此添加控件通知处理程序代码
  //添加新商品取消按钮
  m_name2.Empty();
  m_num2 = 0;
  m_price2 = 0;
  UpdateData(FALSE);
}


库存删除窗口

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

20200409173928342.png

  • 选中对话框 -> 右击 -> 添加类 -> 类名:CDelDlg,基类选择CFormView
  • 根据需求,控件关联所需变量

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

20200409173953607.png

  • 重写 OnInitDialog 函数,进行初始化。


void CDelDlg::OnInitialUpdate()
{
  CFormView::OnInitialUpdate();
  // TODO: 在此添加专用代码和/或调用基类
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  m_combo.AddString((CString)it->name.c_str());
  }
  m_combo.SetCurSel(0);
}


  • 处理组合框事件实现


void CDelDlg::OnCbnSelchangeCombo1()
{
  // TODO: 在此添加控件通知处理程序代码
  CString text;
  int index = m_combo.GetCurSel();
  m_combo.GetLBText(index, text);
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  if (text == it->name.c_str())
  {
    m_price = it->price;
    m_num = 0;
    UpdateData(FALSE);
  }
  }
}


  • 确定按钮功能实现


void CDelDlg::OnBnClickedButton1()
{
  // TODO: 在此添加控件通知处理程序代码
  //确定按钮实现
  UpdateData(TRUE);
  if (m_num == 0)
  {
  MessageBox(TEXT("个数不能为0!"));
  return;
  }
  CString type;
  int index = m_combo.GetCurSel();
  m_combo.GetLBText(index, type);
  CString str;
  str.Format(TEXT("删除商品:%s \r\n 单价:%d \r\n 个数:%d"), type, m_price, m_num);
  MessageBox(str);
  CInfoFile file;
  file.ReadDocline();
  for (auto it = file.ls.begin(); it != file.ls.end(); ++it)
  {
  if (type == it->name.c_str())
  {
    it->num = it->num - m_num;
  }
  }
  file.WriteDocline();//更新数据内容
  file.ls.clear();
  m_num = 0;
  UpdateData(FALSE);//更新显示控件
}


  • 取消按钮功能实现


void CDelDlg::OnBnClickedButton2()
{
  // TODO: 在此添加控件通知处理程序代码
  //取消按钮实现
  m_combo.SetCurSel(0);
  m_num = 0;
  OnCbnSelchangeCombo1();
}


菜单栏实现

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

20200409174157817.png20200409174204446.png

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

20200409174221661.png20200409174226231.png

  • 处理事件函数中发送消息给主框架实现界面切换。


void CMainFrame::OnEditUser()
{
  // TODO: 在此添加命令处理程序代码
  ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_A, (WPARAM)NM_A, (LPARAM)0);
}
void CMainFrame::OnEditSell()
{
  // TODO: 在此添加命令处理程序代码
  ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_B, (WPARAM)NM_B, (LPARAM)0);
}
void CMainFrame::OnEditCopy()
{
  // TODO: 在此添加命令处理程序代码
  ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_C, (WPARAM)NM_C, (LPARAM)0);
}
void CMainFrame::OnEditAdd()
{
  // TODO: 在此添加命令处理程序代码
  ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_D, (WPARAM)NM_D, (LPARAM)0);
}
void CMainFrame::OnEditDel()
{
  // TODO: 在此添加命令处理程序代码
  ::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_E, (WPARAM)NM_E, (LPARAM)0);
}


20200409174930801.gif

最终实现

20200409174930801.gif

相关文章
|
C++ Windows
09 MFC - 创建基于对话框的 MFC 应用程序框架
09 MFC - 创建基于对话框的 MFC 应用程序框架
116 0
|
9月前
[MFC] A对话框调用B对话框
[MFC] A对话框调用B对话框
55 0
|
程序员 Windows
【windows编程之对话框】对话框原理,对话框的创建
【windows编程之对话框】对话框原理,对话框的创建
|
测试技术 BI 区块链
MFC——对话框的创建及使用(上)
MFC——对话框的创建及使用
1290 0
MFC——对话框的创建及使用(上)
在Dll中创建对话框并调用
1、第一步创建一“MFC AppWizard (dll)”工程,接下来选择“Regular Dll using shared MFC DLL”,点击“Finish”。 2、添加一对话框资源到工程中,从菜单中选择Insert->Resource,添加一“Dialog”选择“New”,至此对话框已添加到DLL工程中。
1194 0
|
测试技术
MFC中为菜单或按钮添加快捷键功能
1、新建一快捷键资源,ACCELERATOR,关联相应的ID号,下图所示中,其中,第一个ID为自定义快捷键ID,按CTRL+R,此时响应该ID以应的消息响应函数, 第二个ID为菜单ID,此时按CTRL+V,调出ID_NETWORK_PING菜单对应的响应函数。
1404 0
MFC弹出对话框几种方法总结
一、点击菜单按钮弹出对话框 1、在资源视图中(.rc文件夹下)找到menu,选择需要弹框的菜单项; 2、点击菜单项,修改菜单ID,在主程序中用ON_COMMAND()将ID和函数关联,要在主程序的头文件中声明被关联函数; ...
3759 0