MFC – 5 文件操作、序列化机制、对话框


文件操作

序列化基本类型

以二进制流形式读写硬盘文件,但这种方式效率高。

  • CFile 文件操作类,完成硬盘文件读写操作。
  • CArchive 归档类,完成内存数据操作。

CFile:

  1. CFile::Open
  2. CFile::Write / Read
  3. CFile::Close
  4. CFile::SeekToBegin / SeekToEnd / Seek
void fun()
{
    CFile file;
    file.Open("C:/path/to/file", CFile::modeReadWrite | CFile::modeCreate);
    char str[] = "hello file";
    file.Write(str, strlen(str));
    file.SeekToBegin();
    char buf[256] = { 0 };
    long nLen = file.Read(buf, 255);
    std::cout << buf << " : " << nLen << std::endl;
}

 

序列化机制使用

在内存中使用 /0 标识字符串的结束;在序列化的文件中,在字符串的前面用一个字节加上长度

MFC - 5 文件操作、序列化机制、对话框

图中的特殊符号就保存了字符串的长度

void store()
{
    CFile file;
    file.Open("C:/file", CFile::modeReadWrite);
    CArchive ar(&file, CArchive::store);

    ar << 1L << 88.5 << "string";

    ar.Close();
    file.Close();
}

void load()
{
    CFile file;
    file.Open("C:/file", CFile::modeReadWrite);
    CArchive ar(&file, CArchive::load);
    
    long a; float b; CString c;
    ar >> a >> b >> c;
    std::cout << a << b << c << std::endl;
    
    ar.Close();
    file.Close();
}

序列化过程:

  1. ar 对象维护一个缓冲区
  2. 将各个数据依次序列化到ar维护的缓冲区中,并将 m_lpBufCur 指针移动响应字节
  3. 如果ar维护的缓冲区不足,则将ar维护的缓冲区的数据写入硬盘文件,并重置 m_lpBufCur 为开始指向
  4. 当关闭ar对象时,将ar对象维护的缓冲区数据写入硬盘文件,释放ar维护的缓冲区

反序列化过程:

  1. ar 对象维护一个缓冲区
  2. 当反序列化第一个数据时,将文件数据全部读取到ar维护的缓冲区中,并将第一个数据反序列化到第一个变量,并将 m_lpBufCur 移动相应字节数
  3. 依次反序列化每个数据到变量中
  4. 当关闭ar对象时,释放ar维护的缓冲区

 

序列化类对象

序列化对象就是将对象的各个成员变量序列化,但与直接序列化各个字段不同,还会保存类名、类大小、类版本,然后保存字段。

要求:

  1. 必须派生自 CObject
  2. 类内必须添加声明宏 DECLARE_SERIAL(theClass)
  3. 类外必须添加实现宏 IMPLEMENT_SERIAL(theClass, baseClass, 1)
  4. 类必须重写虚函数 Serialize

 

class CMyDoc : public CDocument
{
    DECLARE_SERIAL(CMyDoc)  // 包含了 DECLARE_DYNCREATE(CMyDoc) 用于反序列化时动态生成对象
public:
    CMyDoc(int age = 0, float score = 0.0, CString name = "") : m_age(age), m_score(score), m_name(name) {}
    int m_age;
    float m_score;
    CString m_name;

    virtual void Serialize(CArchive& ar);
};
IMPLEMENT_SERIAL(CMyDoc, CDocument, 1)  // 包含了 IMPLEMENT_DYNCREATE(CMyDoc, CDocument)
void CMyDoc::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        ar << m_age << m_score << m_name;
    }
    else
    {
        ar >> m_age >> m_score >> m_name;
    }
}


void store()
{
    CFile file;
    file.Open("C:/file", CFile::modeReadWrite);
    CArchive ar(&file, CArchive::store);

    CMyDoc data(1, 5.5, "zhangsan");
    ar << &data;  // 序列化对象就是将对象的各个成员变量序列化

    ar.Close();
    file.Close();
}

void load()
{
    CFile file;
    file.Open("C:/file", CFile::modeReadWrite);
    CArchive ar(&file, CArchive::load);
    
    CMyDoc* pData = NULL;
    ar >> pData;

    ar.Close();
    file.Close();

    std::cout << pData->m_age << pData->m_score << pData->m_name << std::endl;
}

 

 


 

对话框

  • 模式对话框(假,使用 EnableWindow 伪造)
  • 无模式对话框

无模式对话框架构使用 CDialog  CWinApp

  1. 添加 Dialog 资源
  2. 定义一个自己的对话框类,管理对话框资源,派生自 CDialogCDialogEx 均可
// 这份代码将对话框做为主窗口,点击“确定”按钮后窗口消失但进程依然存在,因为父类中虚函数使用了 EndWindow 隐藏窗口
#include <afxwin.h>
#include "resource1.h"

class CMyDlg : public CDialog
{
    DECLARE_MESSAGE_MAP()
public:
    void OnCancel();
};
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    ON_COMMAND(IDCANCEL, OnCancel)
END_MESSAGE_MAP()
void CMyDlg::OnCancel()
{
    this->DestroyWindow();
}

class CMyWinApp : public CWinApp
{
public:
    virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
    CMyDlg* pdlg = new CMyDlg;
    pdlg->Create(IDD_DIALOG1);
    m_pMainWnd = pdlg;
    pdlg->ShowWindow(SW_SHOW);
    pdlg->UpdateWindow();
    return TRUE;
}

CMyWinApp theApp;

执行过程:

  1. 获得应用程序类对象theApp的地址
  2. 利用theApp地址调用InitApplication,初始化当前应用程序的数据
  3. 利用theApp地址调用InitInstance函数,在函数中创建无模式对话框并显示
  4. 利用theApp地址调用CWinApp的Run函数进行消息循环
  5. 如果没有消息,利用theApp地址调用 OnIdle 虚函数实现空闲处理
    当对话框销毁(必须利用DestroyWindow),消息循环才可退出。
    推出前利用theApp地址调用 ExitInstance 虚函数实现退出前的善后处理工作。

 

模式对话框

#include <afxwin.h>
#include "resource1.h"

class CMyDlg : public CDialog
{
    DECLARE_MESSAGE_MAP()
public:
    CMyDlg() : CDialog(IDD_DIALOG1) {}
    void OnCancel();
};
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    ON_COMMAND(IDCANCEL, OnCancel)
END_MESSAGE_MAP()
void CMyDlg::OnCancel()
{
    this->DestroyWindow();
}

class CMyWinApp : public CWinApp
{
public:
    virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
    CMyDlg* pdlg = new CMyDlg;
    this->m_pMainWnd = pdlg;
    //pdlg->Create(IDD_DIALOG1);
    //pdlg->ShowWindow(SW_SHOW);
    //pdlg->UpdateWindow();
    pdlg->DoModal();
    return FALSE;  // 不再执行MFC库中安排的Run函数
}

CMyWinApp theApp;
  1.  启动后进入入口函数 WinMain
  2. 获取应用程序类对象theApp的地址
  3. 利用theApp地址调用InitApplication,初始化当前应用程序的数据
  4. 利用theApp地址调用InitInstance函数,在函数中调用DoModal,DoModal 内部
    1. 将父窗口设置为不可用
    2. 创建无模式对话框
    3. 进入消息循环(自带的)
    4. 退出消息循环(父类的OnOK/OnCancel导致循环退出)
    5. 将父窗口设置为可用状态
    6. 销毁无模式对话框
  5. 不再执行CWinApp的Run函数进行消息循环
  6. 程序结束

 

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/278965.html

(0)
上一篇 2022年8月4日
下一篇 2022年8月5日

相关推荐

发表回复

登录后才能评论