MFC—SaleSystem project (middle)

4 Static split window

4.1 Custom MFC view class

Customize two classes: CSelectView and CDispalyView (its base class must be a view class).

CSelectView inherits from CTreeView, and CDispalyView inherits from CFormView.

4.2 Split the window through the CSplitterWnd class

1) In the CMainFrame class, declare an object of type CSplitterWnd:

private:
CSplitterWnd m_spliter; // Split window class object

2) Rewrite the OnCreateClient function of the frame class CMainFrame

Change the return value of the OnCreateClient() function to Return TRUE:

The static splitting implementation code is as follows:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{<!-- -->
// TODO: Add specialized code here and/or call the base class

// Static split window, 1 row and 2 columns, CSplitterWnd::CreateStatic
m_spliter.CreateStatic(this, 1, 2);

//Create view: CSplitterWnd::CreateView
//0, 0: Place it at row 0 and column 0
//RUNTIME_CLASS(CSelectView): Requires header file #include "SelectView.h", CSelectView is declared in SelectView.h
// CSize(250, 500): Specify the view width and height
//pContext: The last formal parameter of OnCreateClient()
m_spliter.CreateView(0, 0, RUNTIME_CLASS(CSelectView), CSize(200, 500), pContext);

//0, 1: Place it at row 0 and column 1
//CDispalyView, requires header file #include "DispalyView.h"
m_spliter.CreateView(0, 1, RUNTIME_CLASS(CDispalyView), CSize(600, 500), pContext);

//return CFrameWnd::OnCreateClient(lpcs, pContext);
return TRUE;
}

The program running effect diagram is as follows:

##5 Implementation of tree view function

5.1 Add function node

1) Load icon resources


The icon resource ID is changed to: IDI_ICON_RE

2) Declare the corresponding variables in the CSelectView class:

CTreeCtrl *m_treeCtrl; //Tree control
CImageList m_imageList; //Icon list

3) Rewrite the OnInitUpdate function of CSelectView

void CSelectView::OnInitialUpdate()
{<!-- -->
CTreeView::OnInitialUpdate();

// TODO: Add specialized code here and/or call the base class
}

4) In the OnInitUpdate function of CSelectView, complete the initialization function

void CSelectView::OnInitialUpdate()
{<!-- -->
CTreeView::OnInitialUpdate();

// TODO: Add specialized code here and/or call the base class

//Loading of icon resources CWinApp::LoadIcon
//IDI_ICON_RE is the icon resource ID
HICON icon = AfxGetApp()->LoadIconW(IDI_ICON_RE);

//Creation of image list CImageList::Create
//30, 30: Specify the width and height of the icon
//ILC_COLOR32: Icon format
//1, 1: Write as many icons as there are
m_imageList.Create(30, 30, ILC_COLOR32, 1, 1);

//Add icon to image list CImageList::Add
m_imageList.Add(icon);

//Get the tree control in the data view CTreeView::GetTreeCtrl
m_treeCtrl = & amp;GetTreeCtrl();

//Count control set image list CTreeCtrl::SetImageList
m_treeCtrl->SetImageList( & amp;m_imageList, TVSIL_NORMAL);

//Tree control setting node CTreeCtrl::InsertItem
m_treeCtrl->InsertItem(TEXT("Personal Information"), 0, 0, NULL);
m_treeCtrl->InsertItem(TEXT("Sales Management"), 0, 0, NULL);
m_treeCtrl->InsertItem(TEXT("Inventory Information"), 0, 0, NULL);
m_treeCtrl->InsertItem(TEXT("Inventory Add"), 0, 0, NULL);
m_treeCtrl->InsertItem(TEXT("Inventory Delete"), 0, 0, NULL);
}

The program running effect diagram is as follows:

5.2 Function node corresponding message processing

void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{<!-- -->
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: Add control notification handler code here
*pResult = 0;
}

In the above function, obtain the selected content of the current node:

void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{<!-- -->
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: Add control notification handler code here
*pResult = 0;

//Get the selected item of the current node CTreeCtrl::GetSelectedItem
HTREEITEM item = m_treeCtrl->GetSelectedItem();

//Get the text content of the selected item CTreeCtrl::GetItemText
CString str = m_treeCtrl->GetItemText(item);
//MessageBox(str);

if (str == TEXT("Personal information"))
{<!-- -->
}
else if (str == TEXT("Sales Management"))
{<!-- -->
}
else if (str == TEXT("Inventory information"))
{<!-- -->
}
else if (str == TEXT("Inventory increase"))
{<!-- -->
}
else if (str == TEXT("Inventory Delete"))
{<!-- -->
}
}

6 Personal information management window

6.1 UI design

1) Add a dialog box resource (change the ID to DIALOG_USER) and add the required controls:

In the window properties, change Border to None and Style to Child:


2) Select the dialog box -> right-click -> Add class -> Class name: CUserDlg, select CFormView as the base class

3) According to the requirements, the control associates the required variables
The identity editing area is associated with CString m_user, and the username editing box is associated with CString m_name.
The new password edit box is associated with CString m_newPwd, and the sure password edit box is associated with CString m_surePwd.

6.2 Function Implementation

1) In the dialog class, rewrite the OnInitDialog function to initialize it.

void CUserDlg::OnInitialUpdate()
{<!-- -->
CFormView::OnInitialUpdate();

// TODO: Add specialized code here and/or call the base class
}
void CUserDlg::OnInitialUpdate()
{<!-- -->
CFormView::OnInitialUpdate();

// TODO: Add specialized code here and/or call the base class

CInfoFile file; //Header file required #include "InfoFile.h"
CString name, pwd;
file.ReadLogin(name, pwd); //Read the username and password of the file

//Initialize personal information
m_user = TEXT("Salesperson"); //Identity
m_name = name; //user name

UpdateData(FALSE); //Update data to the control
}

2) Confirm that the change password button function is implemented

void CUserDlg::OnBnClickedButton1()
{<!-- -->
// TODO: Add control notification handler code here

UpdateData(TRUE);//Update the content of the control to the corresponding variable

if (m_newPwd.IsEmpty() || m_surePwd.IsEmpty())
{<!-- -->
MessageBox(TEXT("Enter password cannot be empty"));
return;
}

if (m_newPwd != m_surePwd)
{<!-- -->
MessageBox(TEXT("Enter password and confirm password are not equal"));
return;
}

CInfoFile file; //Header file required #include "InfoFile.h"
CString name, pwd;
file.ReadLogin(name, pwd); //Read the username and password of the file

if (m_surePwd == pwd)
{<!-- -->
MessageBox(TEXT("The entered password is equal to the old password"));
return;
}

//Convert the CString type of username and password to char *
char *tmpName, *tmpPwd;
\t//username
CStringA tmp1;
tmp1 = name;
tmpName = tmp1.GetBuffer();
\t//password
CStringA tmp2;
tmp2 = m_surePwd;
tmpPwd = tmp2.GetBuffer();

file.WritePwd(tmpName, tmpPwd); //Change password

MessageBox(TEXT("Password changed successfully"));

//Clear the content of the input box
m_surePwd.Empty();
m_newPwd.Empty();
UpdateData(FALSE); //Update data to the control
}

3) Implementation of cancel button function

void CUserDlg::OnBnClickedButton3()
{<!-- -->
// TODO: Add control notification handler code here

//Clear the content of the input box
m_surePwd.Empty();
m_newPwd.Empty();
UpdateData(FALSE); //Update data to the control
}

7 interface mounting

7.1 Customized message sending

1) In the CMainFrame frame class, add a custom message macro

//WM_USER is a starting value for user-defined messages
//WM_USER + 100 is to distinguish system messages and user messages to avoid conflicts
#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) Add a custom message processing function in the CMainFrame framework class:

//Custom message processing function
afx_msg LRESULT OnMyChange(WPARAM wParam, LPARAM lParam);

3) The corresponding .cpp defines its function

LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam)
{<!-- -->

}

4) Add a custom message entry between the CMainFrame framework class BEGIN_MESSAGE_MAP and END_MESSAGE_MAP and bind it to the custom message processing function.

 //ON_MESSAGE responds to a custom message
//Generate NM_X message and automatically call OnMyChange function
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)

5) Send custom signals
In the OnTvnSelchanged function of CSelectView, send a custom signal:

if (str == TEXT("Personal information"))
{<!-- -->
//Need to include the framework class header file #include "MainFrm.h"
//CWnd::PostMessage puts a message into the window's message queue
//AfxGetMainWnd(): Pointer to the frame window object
//AfxGetMainWnd()->GetSafeHwnd(): Get the handle of the returned window, CWnd::GetSafeHwnd
//NM_A: Send custom message
//(WPARAM)NM_A: Specifies additional message information
//(LPARAM)0: Additional message information is specified. This parameter has no meaning here.
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_A, (WPARAM)NM_A, (LPARAM)0);
}
else if (str == TEXT("Sales Management"))
{<!-- -->
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_B, (WPARAM)NM_B, (LPARAM)0);
}
else if (str == TEXT("Inventory Information"))
{<!-- -->
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_C, (WPARAM)NM_C, (LPARAM)0);
}
else if (str == TEXT("Inventory added"))
{<!-- -->
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_D, (WPARAM)NM_D, (LPARAM)0);
}
else if (str == TEXT("Inventory Delete"))
{<!-- -->
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), NM_E, (WPARAM)NM_E, (LPARAM)0);
}

7.2 Customized information processing

Process the corresponding message in the OnMyChange function of the CMainFrame framework class

LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam)
{<!-- -->
switch(wParam)
{<!-- -->
case NM_A:
MessageBox(_T("NM_A"));
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;
}

7.3 Interface mounting

If it is the NM_A signal, the CUserDlg window is mounted, and the subsequent interfaces are mounted in the same way.

CCreateContext Context;
switch(wParam)
{<!-- -->
case NM_A:
{<!-- -->
//CUserDlg class needs to include the header file #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), & amp;Context);
CUserDlg *pNewView = (CUserDlg *)m_spliter.GetPane(0, 1);
m_spliter.RecalcLayout();
pNewView->OnInitialUpdate();
m_spliter.SetActivePane(0, 1);
}
break;
case NM_B:
//…………

The program runs as follows: