ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-08-04 22:04:33  阅读:165  来源: 互联网

标签:CFile MFC 对话框 ar pdlg file 序列化


文件操作

序列化基本类型

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

  • 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 标识字符串的结束;在序列化的文件中,在字符串的前面用一个字节加上长度

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

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. 程序结束

 

标签:CFile,MFC,对话框,ar,pdlg,file,序列化
来源: https://www.cnblogs.com/zhh567/p/16550719.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有