实验9文件操作文档格式.docx
- 文档编号:20269551
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:14
- 大小:173.19KB
实验9文件操作文档格式.docx
《实验9文件操作文档格式.docx》由会员分享,可在线阅读,更多相关《实验9文件操作文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
打开ResourceView双击Dialog中的IDD_Ex101_FORM项,可以编辑CEx101View使用的对话框资源。
按照下图的排列,增加下表中的控件。
控件含义
ID
类型
属性
年份
IDC_YEAR
EditBox
选中Styles—Number
改变年份Spin
IDC_SPIN_YEAR
Spin
默认
月份
IDC_MONTH
ComboBox
Data输入“一月”到“十二月”,Styles—Type去掉Sort
当月产值
IDC_MON_PRO
当月备注
IDC_MON_MEM
比上月增长率
IDC_RISERATE
StaticText
删除Caption
全年产值
IDC_YEAE_PRO
FormLabel
删除Caption,黑体14
在输入一月到十二月时,使用Ctrl+Enter换行。
窗口上的其他文字信息是StaticText控件,设定好位置后写上文字即可。
添加全年产值控件的方法是:
在编辑对话框的窗口上,按鼠标右键选择InsertActiveXControls,在弹出的对话框上添加MicrosoftForms2.0Label控件,选择其属性,可以设置较为美观的字体、颜色。
3、给CEx101Doc类添加成员变量。
给CEx101Doc类添加记录各月产值、备注、年份等的变量,可以使用鼠标右键弹出菜单中的AddMemberVariable项,添加部分变量并定位到源代码中变量定义处,继续添加下列代码:
public:
struct{
intnProduct;
//月份产量
charsNote[50];
//备注
}m_Month[12];
//记录各月信息
intm_nTotalProduct;
//年总产量
intm_nYear;
//年份
在CEx101Doc类的构造函数中对这些变量进行初始化:
CEx101Doc:
:
CEx101Doc()
{
m_nYear=2005;
m_nTotalProduct=0;
for(inti=0;
i<
12;
i++)
{
m_Month[i].nProduct=0;
m_Month[i].sNote[0]=NULL;
}
}
4、给CEX101View类添加成员变量。
利用类向导给CEX101View类添加以下成员变量。
控件ID
成员变量
说明
int
m_nYear
CComboBox
m_ctrlMonthList
选择月份组合框
m_nMonPro
CString
m_strMonMem
m_strRiseRate
增长率字符串
CLabelControl
m_YearPro
年总产值
注意:
CLabelControl类,是在类向导中为ActiveX控件IDC_YEAE_PRO增加变量时自动生成的,它实现了对这个控件的基本控制,在此没有改动它的代码。
另外在视图类中添加一个记录当前月份的整数变量。
Private:
intm_nCurrentMonth;
5、实现CEX101View类成员函数。
用类向导增加响应用户输入的成员函数。
因为采用CFormView基类,关闭文档窗口时来不及获取最近数据,所以这些输入控件都响应的是EN_CHANGE消息,数据一有变化就记录下来。
A、初始化CEX101View类构造函数。
CEx101View:
CEx101View()
:
CFormView(CEx101View:
IDD)
m_nYear=0;
m_nMonPro=0;
m_strMonMem=_T("
"
);
m_strRiseRate=_T("
m_nCurrentMonth=0;
//0代表1月
//}}AFX_DATA_INIT
B、初始化更新函数OnInitUpdate()完成初始化时的一些设置工作。
voidCEx101View:
OnInitialUpdate()
CFormView:
OnInitialUpdate();
ResizeParentToFit();
CEx101Doc*pDoc=GetDocument();
m_nYear=pDoc->
m_nYear;
//获取文档中的年份
m_ctrlMonthList.SetCurSel(0);
//选择一月
//当前月是一月
m_nMonPro=pDoc->
m_Month[0].nProduct;
//一月产值
m_strMonMem=pDoc->
m_Month[0].sNote;
//一月备注
m_strRiseRate="
第一月无此值"
;
CStringstr;
str.Format("
%d"
pDoc->
m_nTotalProduct);
m_YearPro.SetCaption(str);
//调用CLableControl设置标题函数显示年总产值
UpdateData(false);
C、添加当月备注函数OnChangeMonMem()。
使用类向导在CEx101View类中增加成员函数,用于响应输入当月备注控件IDC_MON_MEM的EN_CHANGE消息,其代码如下:
OnChangeMonMem()
CEx101Doc*pDoc=GetDocument();
UpdateData();
//获取最新输入数据
//和文档中的数据比较,看是否有变化
if(strcmp(pDoc->
m_Month[m_nCurrentMonth].sNote,m_strMonMem))
//记录新数据
strcpy(pDoc->
m_Month[m_nCurrentMonth].sNote,m_strMonMem);
pDoc->
SetModifiedFlag();
//设置文档改变标志
D、添加当月产值OnChangeMonPro()函数。
使用类向导在CEx101View类中增加成员函数,用于响应输入当月产值控件IDC_MON_PRO的EN_CHANGE消息,其代码如下:
OnChangeMonPro()
//获取输入的月份值
if(pDoc->
m_Month[m_nCurrentMonth].nProduct!
=m_nMonPro)
{//比较判断数据是否改变,并改变总产值
m_nTotalProduct+=m_nMonPro-pDoc->
m_Month[m_nCurrentMonth].nProduct;
CStringstr;
str.Format("
m_YearPro.SetCaption(str);
//显示总产值
m_Month[m_nCurrentMonth].nProduct=m_nMonPro;
//记录当月产值,并计算增长率
if(m_nCurrentMonth==0)
m_strRiseRate="
elseif(pDoc->
m_Month[m_nCurrentMonth-1].nProduct==0)
上月无产值"
else
m_strRiseRate.Format("
%.2f%%"
(pDoc->
m_Month[m_nCurrentMonth].nProduct-pDoc->
m_Month[m_nCurrentMonth-1].nProduct)/(float)(pDoc->
m_Month[m_nCurrentMonth-1].nProduct)*100);
UpdateData(false);
E、添加输入年份函数OnChangeYear()。
使用类向导增加CEx101View类的成员函数OnChangeYear(),响应输入年份控件IDC_YEAR的EN_CHANGE消息。
代码如下:
OnChangeYear()
//获取最新输入
m_nYear!
=m_nYear)
{//判断数据变化
m_nYear=m_nYear;
//记录到Doc中
//设置修改标志
F、使用IDC_SPIN_YEAR微调控件改变年份。
使用类向导增加CEx101View类的成员函数OnDeltaposSpinYear(),响应改变年份的微调控件的UDN_DELTAPOS消息。
OnDeltaposSpinYear(NMHDR*pNMHDR,LRESULT*pResult)
NM_UPDOWN*pNMUpDown=(NM_UPDOWN*)pNMHDR;
if((pNMUpDown->
iDelta>
0)&
&
(m_nYear>
0))
m_nYear--;
//减小年份并且不能小于0
elseif(pNMUpDown->
iDelta<
0)
m_nYear++;
//增加年份
else//非法输入
AfxMessageBox("
年份必须是非负数!
*pResult=0;
return;
GetDocument()->
//文档记录年份
UpdateData(FALSE);
*pResult=0;
G、添加月份选择处理函数OnSelchangeMonth()。
利用类向导在CEx101View类中添加成员函数,响应月份控件IDC_MONTH的CBN_SELCHANGE消息。
OnSelchangeMonth()
//获得当前选择月份并设置正确显示
m_nCurrentMonth=m_ctrlMonthList.GetCurSel();
//计算这个月增长率
if(m_nCurrentMonth==0)//是一月?
m_strRiseRate="
第一月无此值!
elseif(pDoc->
else//计算增长率
m_strRiseRate.Format("
(pDoc->
m_Month[m_nCurrentMonth-1].nProduct)/
(float)(pDoc->
//获得当月产值和备注
m_Month[m_nCurrentMonth].sNote;
6、实现CEx101Doc类的串行化函数。
CEx101Doc类的串行化函数是MFC自动生成的,添加所需的代码,实现框架传递过来的CArchive对象对数据的读写操作。
在这个函数中给出了CArchive的“<
<
”和“>
>
”操作符、Read()和Write()函数的用法。
这里操作的文件就是在创建工程时确定的hjm文件。
从这里就可以知道hjm文件的格式。
voidCEx101Doc:
Serialize(CArchive&
ar)
if(ar.IsStoring())//判断是否存储
//实现存储写的代码
ar<
//写入年份
m_nTotalProduct;
//写入年总产值
for(inti=0;
i++)//循环写入各月信息
{
ar<
m_Month[i].nProduct;
//这个月的产值
ar.Write(m_Month[i].sNote,50);
//这个月备注
}
else
//实现读出的代码
ar>
//读出年份
//读出总产值
intnTemp=0;
i++)//读出各月信息
ar>
if(m_Month[i].nProduct<
0)//纠正负值
m_Month[i].nProduct=-m_Month[i].nProduct;
nTemp+=m_Month[i].nProduct;
//临时统计各月总产值
ar.Read(m_Month[i].sNote,50);
//读出该月的备注信息
m_Month[i].sNote[49]=NULL;
//确保字符串结束符存在
//进行检查工作
if(nTemp!
=m_nTotalProduct)//各月累计和总产值不符
AfxMessageBox("
该报表文件中总产值与各月总和不符,\\n将总产值置为各月总和"
m_nTotalProduct=nTemp;
此时,程序可以编译、链接运行,已经可以对文档,即hjm文件进行新建、打开、保存等操作。
7、使用CStdioFile类。
使用串行化函数,可以完成对框架支持的文件的固定操作,但在需要实现一些特殊功能时,它就有些捉襟见肘了。
从上面实现的程序基础上继续来扩展功能:
用CStdioFile类实现从hjm数据文件中来生成txt文本文件。
1)添加菜单资源。
选择工作区资源视图,打开Menu项编辑IDR_YEARTYPE菜单。
打开“文件”菜单,在菜单项“另存为”和“打印”二者之间加入一个Separator菜单项,然后在加入“生成文本报表”菜单项;
ID为ID_CREATE_TEXT,Caption为“生成文本报表”。
2)生成文本报表函数,利用类向导在CEx101Doc类中增加响应ID_CREATE_TEXT的COMMAND消息的成员函数,即完成当前打开的年度产值报表hjm文件生成一个txt文件。
在这里使用使用CFile的派生类CStdioFile类来完成。
CStdioFile的流方式文本操作对此使用较为方便。
该函数还演示了对于文件名信息的一些操作技巧。
OnCreateText()
CStringfilename=GetPathName();
//获取该文档当前的hjm名
if(filename.IsEmpty())//如果空
filename=GetTitle()+"
.txt"
//从标题获得
filename=filename.Left(filename.GetLength()-3)+"
txt"
CStdioFilefile;
//用CStdioFile创建一个txt文件,注意使用的文件操作标志
if(file.Open(filename,CFile:
modeCreate|CFile:
modeWrite|CFile:
typeText)==0)
str="
创建文件"
+filename+"
失败!
AfxMessageBox(str);
//创建失败
//写文本文件内容
%d年产值报告\n\n"
m_nYear);
file.WriteString(str);
总产值:
%d元\n\n"
m_nTotalProduct);
月份:
产值:
单位(元)备注:
\n"
%4d%13d%s\n"
i+1,m_Month[i].nProduct,m_Month[i].sNote);
file.WriteString(str);
//文件写完了,再做一些辅助工作
file.SetLength(file.GetPosition());
file.Close();
str="
notepad"
+filename;
WinExec(str,SW_SHOW);
//用记事本打开
编译,链接并运行程序,打开“文件”文件菜单选择“生成文本报表”,观察运行效果。
思考和练习
1.什么是“串行化”?
VC++中是通过什么成员函数实现这一功能的?
2.CFile类的哪几个函数具备文件定位的功能?
3.怎样用CFile类和CFileDialog类配合使用来完成文件的读写操作?
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 文件 操作