当前位置:文档之家› MFC实验报告

MFC实验报告



C++
期末程序设计实验报告



学院:自动化

班级:05507

学号:051622

姓名:操军

班内序号:02

(本来想做一个学生管理系统,但是后来做着做着就 发现自己做的一点都不像学生管理系统,应该像一个校友录系统,不过不管怎样学到知识就可以了,于是决定凑合着交上去吧。)

管理系统的设计及其制作


一. 整体设计 :


1. 使用MFC,充分利用MFC封装的各种控件函数;

2. 模块划分如图


分三个类,用三个 用MFC封装的函
对象数组记录 数实现
使用fstream流










3.思路简介:用类和对象实现可以充分利用封装,继承,多态的方法。由于要求比较简单,在本程序中基本没有用到多态的方法。但大量用到了封装和继承。即每个对话框继承了CDialog的多种特性,每个对话框的功能封装到一起,多个对话框各司其职(对话框之间只有数据传递,每个对话框只实现自己的功能),由于主对话框一直存在,所以将重要数据(3个对象数组)作为主对话框的变量。为了实现数据安全,考虑不用全局变量。另外,实现界面美化也是重要的部分,通过类向导,利用WM_PAINT WM_CTLCOLOR WM_ERASEBKGND 等消息实现对话框的美化。



二. 操作说明:





















开始






1. 主对话框

列表视图一个,按钮多个,静态控件若干,复选框一个。
列表试图不显示所有数据,仅显示最重要的数据。对于其它数据可以通过点击"详细资料"按钮弹出"详细资料对话框"得到。
排序,分类查看查找结果都在列表框中显示。
该对话框上可以实现添加,删除,编辑,查看,分类查看,精确查找,模糊查找,统计,保存,退出功能。
左上角能够显示当前系统所显示的时间。
右上方提示栏可以提示某些操作后的当前状态。
2. 添加,修改功能


点击"添加"按钮,显示上图


点击"编辑"按钮,显示上图

"添加"弹出对话框中为空,"修改"弹出的修改对话框显示待编辑对象的数据。
必须填写名称和性质才可以填写其它信息和实现"确定"功能。
填写前需要在相应的一栏前的复选框中打勾。
对于"部门"这一个选项,客户可以自己填写其他单位,不一定要在下拉框中的选项中选取。
对于"电话1""电

话2""电话3",只有客户信息"单位"时才可填写。
"重填"按钮表示清空所有显示的内容。
如果选择VIP则继续填写弹出VIP编辑窗,以表现我们对VIP的重视


注意:
添加后的结果将与列表试图的最后一行显示。
修改后的结果将显示在同一类别的最后一行(点击"修改"按钮前,必须选中待修改的项目,否则点击"修改"按钮不会有任何反应)。

3.删除功能
在列表试图中选中,按删除或者点击电脑上delete键,经过红色警示对话框确认后即可删除。
4.详细资料
弹出对话框,查看所有信息。顶端有翻页功能。


5.按姓名排序
可以实现姓名按音序排序。
可以选择升序或者降序。
排序结果显示在列表试图中。
如果在分类查看,或查找的状态下选择排序,则只在查看或查找的结果中排序。

6.分类查看

显示结果在主对话框列表中,当分类察看完毕后,如果选择添加,编辑,则自动回到"查看全部"状态

7.统计
统计"个人","VIP"和"单位"的数量,并用直方图显示
统计各部门的数量,如果有部门为空缺,则自动加到"未知部门"




8.精确查找

精确查找可以选择查找姓名或电话,结果显示在主对话框列表视图中。
可以显示,找到了几条结果。

9.模糊查找

模糊查找可以选择在姓名范围或全部信息范围。
只要目标数据中含有模糊查找的字符,就显示出来。比如说选择"所有资料范围",当输入
"123"时,搜索到的结果将显示包含数字"1","2","3"的所有选项。
结果显示在主对话框列表视图中。
当精确查找或模糊查找完毕后,如果选择添加,编辑,则自动回到"查看全部"状态---显示所有记录内容。

10.保存,登陆,注册






可以实现开通多个帐号,不需要密码。如果注册,则在登陆时用户名下拉框中显示已有的帐号。
如果登陆不存在用户名或注册已有用户名,则报错。
在注册时不输入,则放弃注册。
按保存按钮则保存。

11.退出
退出不自动保存,但有提示。

该红色警示对话框为了防止客户操作失误,丢失录入的数据而设计的。
在其它其它对话框操作中也涉及到该对话框。





三.主要实现方法:
(一)主要数据
1.没有设置全局变量。

2.设计了三个类,个人类CPerson,VIP类CVIPPerson,和单位类CWorkplace,其中CVIPPerson由CPerson派生。在主对话框类中设置了3对象数组,CPerson person[];CVIPPerson vipperson[];CWorkplace workplace[];来保存数据。另由p_num,v_num,w_num来记录对象个数,每当打开一个子窗口时,将有用的数据在DoModal()前传入子窗口,在窗口关闭时UpdateData(),在更新的数据传回。

3.在三种类中,有一个记录在列表

试图位置中的的数据,position。当不想在列表视图中显示这个数据时,令position为-1,以实现排序,分类查看,查找等功能时,屏蔽不想显示的内容。

(二)几个基本函数
1.Refresh()用于刷新当前的列表视图,先清除列表视图中的所有,再遍历3个对象数组。获取每个对象的position,然后利用InsertItem(),SetItemText()来重新显示列表视图。
由于,获得一个position,不能立刻InsertItem(),因为此时列表视图中不一定存在position这么多行,所以需要另行处理。
方法为循环i从0到p_num+v_num+w_num,每次遍历三个对象数组,找到成员变量position可以等于i的数,即可找出对象的所有数据,然后加到第i个位置。
当然,如果某对象的position==-1,也不会将其显示出来。

2.DeleteItem(int temp)函数

用于删除列表中第temp行(即position==temp)的数据。
方法为,首先通过遍历找到相应的类名和下标,删除之,该类所对应的对象数组下标往后的顺次前移,并使p_num,v_num,w_num中的一个减1(通过分类讨论)的。然后遍历三个类,发现position大于temp则position--,然后refresh();

3.取消的实现

在点击确定后,如果询问是否继续,单单使用系统的OnCancel是不能实现的,因为此时对话框已经关闭,而主对话框的DoModal()以后的代码会继续执行。
我的结局方法是,在子对话框中加入变量bool IsChange,在确定时为1,取消时设为0。
在主对话框DoModal()后首先分析IsOk,如果为0,则直接return;


(三)重要功能的算法实现:
1.添加
简单的添加工作,将新加的对象存储再相应对象数组的最后一个,position设置为最后一个。
2.删除
通过MFC封装函数 GetFirstSelectedItemPosition();GetNextSelectedItem();得到当前光标的位置,然后调用DeleteItem()函数,即可轻松删除。

3.修改
由于修改时需要考虑到VIP对话框的调用,取消工作是否真正能取消,所以代码较为复杂,但总体来说,就是先 删除,再添加。
其中如果修改时改变了类型,如将vip改为普通个人,则令需分类讨论。
总的流程是
(1)DoModal();
(2)传数据到主对话框
(3)讨论是否"取消",取消则return
(4)传出数据
(5)删除数据
(6)添加数据
(7)讨论是否由非VIP变成VIP,如果是,则打开VIP窗口
(8)refresh();

4.详细资料
利用属性框控件实现,其方法就是利用tab控件的GetCurSel()函数,分类讨论,然后对相应的其他控件进行隐身或显身。

5.排序
正序和逆序,按姓名排序。先把3个对象数组的全部对象的position为正的position设置为-2(position为-1的仍为-1)。然后遍历GetItemCount()次三个数组,每次找出一个最小的或者最大的(此时它的position必须为-2),

将其position改变。最后完毕后再refresh();
void CStudentDlg::OnArrange()
{
// TODO: Add your control notification handler code here
CHowtoarrange dlg5;
dlg5.DoModal();
int s;
int i,j;
int type=0;
CString maxstr="";
int subscript;//下标
s=m_CList.GetItemCount();
m_debug=maxstr;
UpdateData(false);
if (s==0||s==1)
{
return;
}

for(i=0;i{
if(person[i].position>=0)
{
person[i].position=-2;
}
}

for(i=0;i{
if(vipperson[i].position>=0)
{
vipperson[i].position=-2;
}
}

for(i=0;i{
if(workplace[i].position>=0)
{
workplace[i].position=-2;
}
}
//设为-2


for(i=0;i{
maxstr="";//临时记录目前找到的音序最大的姓名
for(j=0;j{
if(person[j].Name>=maxstr&&person[j].position==-2)
{
maxstr=person[j].Name;
type=1;
subscript=j;
CString d,e;
d=type+'0';
e=j+'0';
d+=e;
d+=maxstr=person[j].Name;
}//找到更大的则记录其姓名值,和下标

}

for(j=0;j{
if(vipperson[j].Name>=maxstr&&vipperson[j].position==-2)
{
maxstr=vipperson[j].Name;
type=2;
subscript=j;
CString d,e;
d=type+'0';
e=j+'0';
d+=e;
d+=maxstr=vipperson[j].Name;
}

}

for(j=0;j{
if(workplace[j].Name>=maxstr&&workplace[j].position==-2)
{
maxstr=workplace[j].Name;
type=3;
subscript=j;
CString d,e;
d=type+'0';
e=j+'0';
d+=e;
d+=maxstr=workplace[j].Name;
}

}

CString d;

switch(type)//不同种对象分类讨论
{

case 1:
person[subscript].position=i;
d=i+'0';
d+=maxstr;
// MessageBox(d);
break;
case 2:
vipperson[subscript].position=i;
d=i+'0';
d+=maxstr;
// MessageBox(d);
break;
case 3:
workplace[subscript].position=i;
d=i+'0';
d+=maxstr;
// MessageBox(d);
break;
}

}

if(dlg5.m_how==1)
{
for(i=0;i{
if (person[i].position!=-1)
{
person[i].position=s-1-person[i].position;
}
}

for(i=0;i{
if (vipperson[i].position!=-1)
{
vipperson[i].position=s-1-vipperson[i].position;
}
}

for(i=0;i{
if (workplace[i].position!=-1)
{
workplace[i].position=s-1-workplace[i].position;
}
}
refresh();
MessageBox("排序完毕!","温馨提示");
m_direction="状态:排序完毕--按姓名正序排序";
UpdateData(false);
}

else
{
refresh();
MessageBox("排序完毕!","温馨提示");
m_direction="状态:排序完毕--按姓名逆序排序";
UpdateData(false);
}
}
6.分类查看
只需改变position为-1或正,再refresh()即可

7.统计
统计各性质人数,只需显示p_num,v_num,w_num。
统计各部门人数,设置

2个数组CString Dep[],int attheDep[]分别记录部门名称,和该部门人数。初始值Dep[0]为"未知单位",另记录int Depnum记录存在部门的数量,初始值为1。遍历所有对象数组,嵌套遍历Dep[]数组,如果发现部门名称符合数组中某个名字(如果为空则视为"未知单位"),则atttheDep[i]++,否则(找不到符合的名称),Depnum++,Dep[]数组最后一项名称设为当前新发现部门名称,数量为1,且部门数量(Depnum)+1。

void CStudentDlg::OnStatistic()
{
// TODO: Add your control notification handler code here
int i,j;
CString Dep[10000];
int attheDep[10000]={0};
int Depnum=1;
int flag=0;
Dep[0]="未知部门";
attheDep[0]=0;

CStatisticDlg dlg;
dlg.x=p_num;
dlg.y=v_num;
dlg.z=w_num;
dlg.DoModal();

CStatisticDlg2 dlg2;

for (i=0;i{
if(person[i].Department=="")
{
flag=1;
attheDep[0]++;
}
for(j=0;j{
if (person[i].Department==Dep[j])
{
flag=1;
attheDep[j]++;
break;
}
}
if (flag==0)
{
Dep[Depnum]=person[i].Department;
attheDep[Depnum]++;
Depnum++;
}
flag=0;
}
for (i=0;i{
if(vipperson[i].Department=="")
{
flag=1;
attheDep[0]++;
}
for(j=0;j{
if (vipperson[i].Department==Dep[j])
{
flag=1;
attheDep[j]++;
break;
}
}
if (flag==0)
{
Dep[Depnum]=vipperson[i].Department;
attheDep[Depnum]++;
Depnum++;
}
flag=0;
}

for (i=0;i{
if(workplace[i].Department=="")
{
flag=1;
attheDep[0]++;
}
for(j=0;j{
if (workplace[i].Department==Dep[j])
{
flag=1;
attheDep[j]++;
break;
}
}
if (flag==0)
{
Dep[Depnum]=workplace[i].Department;
attheDep[Depnum]++;
Depnum++;
}
flag=0;
}

for (i=0;i{
https://www.doczj.com/doc/5816525155.html,[i]=Dep[i];
dlg2.num[i].Format("%d",attheDep[i]);
}
dlg2.sum=Depnum;
dlg2.DoModal();
}

8.精确查找
先将所有对象的position设为-1。初始化number=0,然后遍历所有对象数组,发现符合项则position=number,number++;最后refresh();

9.模糊查找
类似于精确查找。CString中有一个函int Find(CString),返回值为是否包含CString,是则返回开始位于字符的未知,否则为负。只要调用该函数,则可以找到所需项,其它算法基本于精确查找类似。

10.存盘,读取

1) 登陆:本程序用fstream流存取数组。读取时,在主对话框OnInitDlg()打开一个登陆对话框,如果错误则

MessageBox("不存在该帐户","警告",MB_ICONWARNING);
AfxGetMainWnd()->PostMessage(WM_QUIT);
即可以让主对话框也退出。
如果登陆成功,则用ifstream依次读进数据。
2) 注册

可以注册多个帐户每次注册建立一个新的帐户名,在新建文件中存储

0 0 0
因为该文件第一行代表三个对象数组的个数。
用ifstream::fail()判别是否该文件已经存在。
在单独的文件ID_LIST.txt中找到尾部,存取帐户名,这样可以在登陆的下拉框初始化时读取该文件,使下拉框中有所有已经注册过的帐号,方便登陆操作。
3) 存盘

先存取p_num,v_num,w_num
然后用ofstream,for循环存取所有数据。
为避免读取时不能识别空,所有在每个数据前加入"*",然后读取后每项内容利用CString中Delete(int)函数,可以删除"*"。

11.界面设置

1)自绘按钮
按钮不能像其他控件那样,欲重绘按钮,需从CButton类派生。在派生时,对其进行一系列的重绘,(由于能力有限,尚不能根据鼠标状态重绘多种状态的按钮)。并在资源中,把按钮改为Owner Draw,并利用类向导把按钮中加入一个CNewButton类的控件变量。即可实现按钮重绘。
2)背景,控件重绘
(1) 在CStudentApp中加入

SetDialogBkColor(RGB(109,232,40),RGB(252,26,50));代码即可改变所有对话框的字体和颜色,但不能改变为不同颜色。

(2) 在CLoginDlg中用类向导添加OnPaint()函数
然后添加代码如下,可以将背景改为IDB_BITMAP
CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here
CRect rect;
GetClientRect(&rect);//读取窗口的所在长方形
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);//创建兼容性指针
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BITMAP);
BITMAP bitMap;
bmpBackground.GetBitmap(&bitMap);
CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);//选择背景图片
dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,bitMap.bmWidth,bitMap.bmHeight,SRCCOPY);//将图片拉伸到合适大小

(3)在CInfromationDlg中设置控件颜色,用类向导建立OnCtlColor函数,再由OnPaint绘图
HBRUSH CInformationDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

// TODO: Change any attributes of the DC here
if(
pWnd->GetDlgCtrlID()==IDC_ISMOBILE||
pWnd->GetDlgCtrlID()==IDC_ISHOME||
pWnd->GetDlgCtrlID()==IDC_ISWORK||
pWnd->GetDlgCtrlID()==IDC_ISXLT||
pWnd->GetDlgCtrlID()==IDC_ISOTHER||
pWnd->GetDlgCtrlID()==IDC_ISPHONE1||
pWnd->GetDlgCtrlID()==IDC_ISPHONE2||
pWnd->GetDlgCtrlID()==IDC_ISPHONE3||
pWnd->GetDlgCtrlID()==IDC_ISEMAIL||
pWnd->GetDlgCtrlID()==IDC_ISMSN||
pWnd->GetDlgCtrlID()==IDC_ISQQ||
pWnd->GetDlgCtrlID()==IDC_ISADDRESS||
pWnd->GetDlgCtrlID()==IDC_ISDEPARTMENT||
pWnd->GetDlgCtrlID()==IDC_ISPERSON||
pWnd->GetDlgCtrlID()==IDC_ISWORKPLACE||
pWnd->GetDlgCtrlID()==IDC_ISVIP||
pWnd->GetDlgCtrlID()==IDC_STATIC1||
pWnd->GetDlgCtrlID()==IDC_STATIC2||
pWnd->GetDlgCtrlID()==IDC_NA)
{
pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkMode(

TRANSPARENT);
return m_brush;//设置该空间的颜色(蓝),和透明度(透明)
}
else
{
pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkMode(TRANSPARENT);
return hbr;//其他按默认设置
}
// TODO: Return a different brush if the default is not desired


}

(4)绘制图表,由于只绘一次,不需刷屏,可以不用与内存联系
void CStatisticDlg::OnPaint()
{
float interval;//根据需要设置每个单位1在图上占多少
int max;
CString type;
CString sum;
CSize szExtent;
if(x==0&&y==0&&z==0)
{
interval=(float)200;
}
else
{
if(x>=y&&x>=z)
{
max=x;
interval=200/x;
}
else if(y>=x&&y>=z)
{
max=y;
interval=200/y;
}
else if(z>=x&&z>=y)
{
max=z;
interval=200/z;
}
}

CRect rect;//绘制黑色背景
m_btnView.GetWindowRect(rect);
ScreenToClient(rect);
rect.top+=15;//顶端下移

CPaintDC dc(this);
CBrush brush;
brush.CreateSolidBrush(RGB(0,0,0));
dc.SelectObject(brush);
dc.Rectangle(rect);
brush.DeleteObject();
brush.CreateSolidBrush(RGB(255,0,0));
CPen pen;
pen.CreatePen(PS_SOLID,2,RGB(0,255,0));
dc.SelectObject(pen);

brush.DeleteObject();

dc.SelectObject(brush);
for (int i=1;i<=10;i++)
{
dc.MoveTo(rect.left,rect.bottom-i*20);
dc.LineTo(rect.right-1,rect.bottom-i*20);

}

CFont *font=GetFont();
LOGFONT lg;
lg.lfEscapement=10;

font->GetLogFont(&lg);
dc.SelectObject(font);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(RGB(251,21,3));
CString text;

for (i=0;i<=10;i++)
{
CSize szExtent = dc.GetTextExtent(text, text.GetLength());//调整数字位置


text.Format("%d",max*i/10);
if(max*i/10>max*(i-1)/10)
{
dc.TextOut(rect.left-szExtent.cx,rect.bottom-i*20-szExtent.cy/2,text);
}
}
pen.DeleteObject();

//以上为画横线
pen.CreatePen(PS_SOLID,1,RGB(0,255,0));


brush.CreateSolidBrush(RGB(255,0,0));
dc.SelectObject(brush);
dc.SelectObject(pen);
dc.Rectangle(rect.left+40,rect.bottom,rect.left+70,rect.bottom-interval*x);

dc.SelectObject(font);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(RGB(255,0,0));
sum.Format("%d",x);

szExtent = dc.GetTextExtent(sum, sum.GetLength());
dc.TextOut(rect.left+55-szExtent.cx/2,rect.bottom-interval*x-szExtent.cy-1,sum);


type.Format("%s","个人");
szExtent = dc.GetTextExtent(type, type.GetLength());
dc.TextOut(rect.left+55-szExtent.cx/2,rect.bottom+szExtent.cy,type);
brush.DeleteObject();
//作"个人"直方图

brush.CreateSolidBrush(RGB(255,0,255));
dc.SelectObject(brush);
dc.Rectangle(rect.left+140,rect.bottom,rect.left+170,rect.bottom-interval*y);

dc.SelectObject(font);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(RGB(255,0,255));
sum.Format("%d",y);

szExtent = dc.GetTextExtent(sum, sum.GetLength());
dc.TextOut(rect.left+155-szExtent.cx/2,rect.bottom-interval*y-szExtent.cy-1,sum);


type.Format("%s","VIP");
szExtent =

dc.GetTextExtent(type, type.GetLength());
dc.TextOut(rect.left+155-szExtent.cx/2,rect.bottom+szExtent.cy,type);
brush.DeleteObject();
//作vip直方图
brush.CreateSolidBrush(RGB(255,255,0));
dc.SelectObject(brush);
dc.Rectangle(rect.left+240,rect.bottom,rect.left+270,rect.bottom-interval*z);

dc.SelectObject(font);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(RGB(255,255,0));
sum.Format("%d",z);

szExtent = dc.GetTextExtent(sum, sum.GetLength());
dc.TextOut(rect.left+255-szExtent.cx/2,rect.bottom-interval*z-szExtent.cy-1,sum);

type.Format("%s","单位");
szExtent = dc.GetTextExtent(type, type.GetLength());
dc.TextOut(rect.left+255-szExtent.cx/2,rect.bottom+szExtent.cy,type);
brush.DeleteObject();
//作单位直方图
}

(5)绘制时钟
从类向导中添加OnTimer()函数,在初始化时设置SetTimer(int,int,int)第2个int为触发OnTimer()函数的周期(1秒)。
在每次OnTimer()中,先CTime::GetCurrentTime(),然后调用OnPaint()函数,在OnPaint函数中,将得到的当前时间转化为CString并用CFont类转化字体,打印出来。
int x=110;
int y=25;
//X、Y改变时钟的显示位置
CPaintDC dc(this);
CDialog::OnPaint();
dc.SetTextColor(RGB(255,150,0));

CFont font;
LOGFONT lf;
lf.lfHeight=-30;
lf.lfWeight=0;
lf.lfEscapement=0;
lf.lfOrientation=0;
lf.lfWeight=FW_HEAVY;
lf.lfCharSet=GB2312_CHARSET;
lf.lfStrikeOut=0;
lf.lfUnderline=0;//设置字体

font.CreateFontIndirect(&lf);
dc.SelectObject(font);
CString time;
time=m_time.Format("%H:%M:%S");//转换为CString类
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(GetSysColor(COLOR_3DDKSHADOW));

dc.TextOut(x+2,y-2,time);

dc.TextOut(x+2,y+2,time);
dc.SetTextColor(GetSysColor(COLOR_3DHILIGHT));
dc.TextOut(x+1,y-2,time);
dc.TextOut(x-2,y+1,time);
dc.TextOut(x-2,y-2,time);

dc.SetTextColor(GetSysColor(COLOR_3DSHADOW));
dc.TextOut(x-1,y+1,time);
dc.TextOut(x+1,y-1,time);
dc.TextOut(x+1,y+1,time);
dc.SetTextColor(GetSysColor(COLOR_3DLIGHT));
dc.TextOut(x,y-1,time);
dc.TextOut(x-1,y,time);
dc.TextOut(x-1,y-1,time);//书写多次以造成3D效果

CDialog::OnPaint();
四.系统调试分析:
1.添加、修改对话框中的静态文本没有能够像主对话框中那样同界面融为一体。如下图:

对于这个不足之处,我查了好久都没有找到毛病之所在。所以现在就只能这样了。
2.MFC对话框界面在按"Enter"时会自动关闭。
前段时间才发现这个问题,当时也没有想到什么好办法解决(后来听说一个同学解决了这个问题,但是当时没有去请教这个问题)。
后来参看别人的程序时想出了这个利用警示对话框提醒用户的操作来弥补这个缺陷,当然这样做只能从表面上解决问题,而且只是针对重要的界面,并非所有界面都利用了这个警示对话框,要不

然它将成为一种累赘。

3.系统内部出现的错误。
比如说:当我在系统中添加很多顾客信息保存并退出后,再次登陆系统时发现刚才添加的所有客户的主要资料都变成了"VDG",而且并不是每一次添加保存并退出之后会出现这种情况。这个缺陷我可真的没有办法解决。

4.登陆系统时只用有个用户名就可以了,这样起不到保护信息的作用
本来想做一个既能注册又能起到保护用户信息的作用的系统,但是在登陆密码方面,我了解不多,现有水平只能做那种只有一个用户名和一个密码登陆框。而且在家里上网极其不方便,很多不懂得东西都无处找答案。所以放弃了密码的设置,希望到了学校能够解决这个问题。

五.对系统的设想:
1.为了使登陆界面更人性化,我想在对话框的三个按钮上实现"气泡"提示。也就是说,当鼠标放在按钮上时,会有个气泡状的显示框进行一些操作提示或者系统警告等重要内容。

2.对于主对话框中的按钮,我希望把它们设计成不同的形状,最好能根据该按钮的作用设计成相关联的形状,这样跟生动形象。
(利用Windows提供的区域Region操作函数,动态地创建函数,然后通过API函数SetWindowsRgn来 改变按钮的形状。)

3.增加一个计时功能。
由于在主界面操作时,界面会随着时间的更新而闪动一次,这样对人的视力不好,所以想设计一个计时器,当用户登陆系统时开始计时,方便用户看看自己在系统上工作了多长时间,便于警示他们要及时休息,注意身体。

六.实验参考资料 :
《C++大学基础教程》人民邮电出版社
《Visual C++ 6.0程序设计从入门到精通》 人民邮电出版社
《Visual C++6.0范例入门与提高》 清华大学出版社
《CSDN VC编程经验总结》 已编译的HTML帮助文件
《VC++ 编程指南》 已编译的HTML帮助文件
《深入浅出MFC 》 已编译的HTML帮助文件

相关主题
文本预览
相关文档 最新文档