Tuần tự hóa là quá trình ghi hoặc đọc một đối tượng đến hoặc từ phương tiện lưu trữ liên tục, chẳng hạn như tệp đĩa. Tuần tự hóa là lý tưởng cho các tình huống mong muốn duy trì trạng thái của dữ liệu có cấu trúc (chẳng hạn như các lớp hoặc cấu trúc C++) trong hoặc sau khi thực hiện chương trình.
Khi thực hiện xử lý tệp, các giá trị thường thuộc kiểu nguyên thủy (char, short, int, float hoặc double). Theo cách tương tự, chúng ta có thể lưu nhiều giá trị riêng lẻ, từng giá trị một. Kỹ thuật này không bao gồm một đối tượng được tạo từ (như một biến của) một lớp.
Thư viện MFC có mức hỗ trợ cao cho tuần tự hóa. Nó bắt đầu với lớp CObject là tổ tiên của hầu hết các lớp MFC, lớp này được trang bị hàm thành viên Serialize().
Bước 1 – Xóa dòng TODO và thiết kế hộp thoại của bạn như trong ảnh chụp nhanh sau đây.
Bước 2 – Thêm các biến giá trị cho tất cả các điều khiển chỉnh sửa. Đối với Emp ID và Age được đề cập, loại giá trị là một số nguyên như trong ảnh chụp nhanh sau đây.
Bước 3 – Thêm trình xử lý sự kiện cho cả hai nút.
Bước 4 – Bây giờ chúng ta hãy thêm một lớp Nhân viên đơn giản mà chúng ta cần tuần tự hóa. Đây là khai báo của lớp Nhân viên trong tệp tiêu đề.
class CEmployee : public CObject {
public:
int empID;
CString empName;
int age;
CEmployee(void);
~CEmployee(void);
private:
public:
void Serialize(CArchive& ar);
DECLARE_SERIAL(CEmployee);
};
Bước 5 – Đây là định nghĩa của lớp Nhân viên trong tệp nguồn (*.cpp).
IMPLEMENT_SERIAL(CEmployee, CObject, 0)
CEmployee::CEmployee(void) {
}
CEmployee::~CEmployee(void) {
}
void CEmployee::Serialize(CArchive& ar) {
CObject::Serialize(ar);
if (ar.IsStoring())
ar << empID << empName << age;
else
ar >> empID >> empName >> age;
}
Bước 6 – Đây là triển khai trình xử lý sự kiện nút Lưu.
void CMFCSerializationDlg::OnBnClickedButtonSave() {
// TODO: Add your control notification handler code here
UpdateData(TRUE);
CEmployee employee;
CFile file;
file.Open(L"EmployeeInfo.hse", CFile::modeCreate | CFile::modeWrite);
CArchive ar(&file, CArchive::store);
employee.empID = m_id;
employee.empName = m_strName;
employee.age = m_age;
employee.Serialize(ar);
ar.Close();
}
Bước 7 – Đây là triển khai trình xử lý sự kiện nút Mở.
void CMFCSerializationDlg::OnBnClickedButtonOpen() {
// TODO: Add your control notification handler code here
UpdateData(TRUE);
CFile file;
file.Open(L"EmployeeInfo.hse", CFile::modeRead);
CArchive ar(&file, CArchive::load);
CEmployee employee;
employee.Serialize(ar);
m_id = employee.empID;
m_strName = employee.empName;
m_age = employee.age;
ar.Close();
file.Close();
UpdateData(FALSE);
}
Bước 8 – Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ thấy đầu ra sau.
Bước 9 – Nhập thông tin vào tất cả các trường và nhấp vào Lưu và đóng chương trình này.
Bước 10 – Nó sẽ lưu dữ liệu. Chạy lại ứng dụng và nhấp vào mở. Nó sẽ tải thông tin Nhân viên.
MFC – Đa luồng
Thư viện Microsoft Foundation Class (MFC) cung cấp hỗ trợ cho các ứng dụng đa luồng. Một luồng là một đường dẫn thực hiện trong một quy trình. Khi bạn khởi động Notepad, hệ điều hành sẽ tạo một quy trình và bắt đầu thực thi luồng chính của quy trình đó. Khi chủ đề này kết thúc, thì quá trình cũng vậy.
Bạn có thể tạo các chủ đề bổ sung trong ứng dụng của mình nếu muốn. Tất cả các luồng trong các ứng dụng MFC được đại diện bởi các đối tượng CWinThread. Trong hầu hết các trường hợp, bạn thậm chí không cần phải tạo các đối tượng này một cách rõ ràng; thay vào đó, hãy gọi hàm trợ giúp khung AfxBeginThread, hàm này sẽ tạo đối tượng CWinThread cho bạn.
Chúng ta hãy xem xét một ví dụ đơn giản bằng cách tạo một ứng dụng dựa trên hộp thoại MFC mới.
Bước 1 – Thay đổi Caption và ID của Static control thành Click on Start Thread button và IDC_STATIC_TEXT tương ứng.
Bước 2 – Kéo hai nút và thêm trình xử lý sự kiện nhấp cho các nút này.
Bước 3 – Thêm biến điều khiển cho điều khiển văn bản tĩnh.Bước 4 – Bây giờ, hãy thêm ba biến toàn cục sau vào đầu tệp CMFCMultithreadingDlg.cpp.
int currValue;
int maxValue;
BOOL stopNow;
Bước 5 – Thêm thông báo WM_TIMER trong lớp CMFCMultithreadingDlg.
Đây là cách triển khai OnTimer()
void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
// TODO: Add your message handler code here and/or call default
CString sStatusMsg;
sStatusMsg.Format(L"Running: %d", currValue);
m_ctrlStatus.SetWindowText(sStatusMsg);
CDialogEx::OnTimer(nIDEvent);
}
Bước 6 – Bây giờ, hãy thêm một hàm mẫu để sử dụng trong AfxBeginThread trong lớp CMFCMultithreadingDlg.
UINT MyThreadProc(LPVOID Param) {
while (!stopNow && (currValue < maxValue)) {
currValue++;
Sleep(50); // would do some work here
}
return TRUE;
}
Bước 7 – Đây là triển khai trình xử lý sự kiện cho nút Bắt đầu luồng, nút này sẽ bắt đầu luồng.
void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
// TODO: Add your control notification handler code here
currValue = 0;
maxValue = 5000;
stopNow = 0;
m_ctrlStatus.SetWindowText(L"Starting...");
SetTimer(1234, 333, 0); // 3 times per second
AfxBeginThread(MyThreadProc, 0); // <<== START THE THREAD
}
Bước 8 – Đây là cách triển khai trình xử lý sự kiện cho nút Dừng luồng, nút này sẽ dừng luồng.
void CMFCMultithreadingDlg::OnBnClickedButtonStop() {
// TODO: Add your control notification handler code here
stopNow = TRUE;
KillTimer(1234);
m_ctrlStatus.SetWindowText(L"Stopped");
}
Bước 9 – Đây là tệp nguồn hoàn chỉnh.
// MFCMultithreadingDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MFCMultithreading.h"
#include "MFCMultithreadingDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCMultithreadingDlg dialog
int currValue;
int maxValue;
BOOL stopNow;
CMFCMultithreadingDlg::CMFCMultithreadingDlg(CWnd* pParent /* = NULL*/)
: CDialogEx(IDD_MFCMULTITHREADING_DIALOG, pParent) {
m_hIcon = AfxGetApp() -> LoadIcon(IDR_MAINFRAME);
}
void CMFCMultithreadingDlg::DoDataExchange(CDataExchange* pDX) {
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_TEXT, m_ctrlStatus);
}
BEGIN_MESSAGE_MAP(CMFCMultithreadingDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_START,
&CMFCMultithreadingDlg::OnBnClickedButtonStart)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_STOP,
&CMFCMultithreadingDlg::OnBnClickedButtonStop)
END_MESSAGE_MAP()
// CMFCMultithreadingDlg message handlers
BOOL CMFCMultithreadingDlg::OnInitDialog() {
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMFCMultithreadingDlg::OnPaint() {
if (IsIconic()) {
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND,
reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}else {
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMFCMultithreadingDlg::OnQueryDragIcon() {
return static_cast<HCURSOR>(m_hIcon);
}
UINT /*CThreadDlg::*/MyThreadProc(LPVOID Param) //Sample function for using in
AfxBeginThread {
while (!stopNow && (currValue < maxValue)) {
currValue++;
Sleep(50); // would do some work here
}
return TRUE;
}
void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
// TODO: Add your control notification handler code here
currValue = 0;
maxValue = 5000;
stopNow = 0;
m_ctrlStatus.SetWindowText(L"Starting...");
SetTimer(1234, 333, 0); // 3 times per second
AfxBeginThread(MyThreadProc, 0); // <<== START THE THREAD
}
void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
// TODO: Add your message handler code here and/or call default
CString sStatusMsg;
sStatusMsg.Format(L"Running: %d", currValue);
m_ctrlStatus.SetWindowText(sStatusMsg);
CDialogEx::OnTimer(nIDEvent);
}
void CMFCMultithreadingDlg::OnBnClickedButtonStop() {
// TODO: Add your control notification handler code here
stopNow = TRUE;
KillTimer(1234);
m_ctrlStatus.SetWindowText(L"Stopped");
}
Bước 10 – Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ thấy đầu ra sau.
Bước 11 – Bây giờ hãy nhấp vào nút Bắt đầu chủ đề
Bước 12 – Nhấp vào nút Stop Thread. Nó sẽ dừng chuỗi.