📄 familytreedlg.cpp
字号:
if (bWorked && strcmp(item.pszText,name)==0){ //如果此项等于name,则保存其句柄
hItem=hParent;
return;
}
hCurrent=m_peTree.GetNextItem(hParent,TVGN_CHILD); //得到hParent项的第一个子项
FindInTree(hCurrent,hItem,name); //递归搜索s
hParent=m_peTree.GetNextItem(hParent, TVGN_NEXT); //查找hParent项的下一个兄弟项
}
}
void CFamilytreeDlg::OnFamilytreeAdd()
{
// TODO: Add your command handler code here
CAddInfoDlg dlg;
if(dlg.DoModal()==IDCANCEL) //弹出对话框
return;
UpdateData(FALSE);
Person addnode;
addnode=new PersonNode; //新申请一结点
if(addnode==0){
AfxMessageBox("内存不足!");
return;
}
addnode->child=0;
addnode->sibling=0;
addnode->parent=0;
//把有关结点信息加入到结点中去
strcpy(addnode->info.name,dlg.m_name);
strcpy(addnode->info.addr,dlg.m_addr);
addnode->info.birthday.year=dlg.m_birthday_year;
addnode->info.birthday.month=dlg.m_birthday_month;
addnode->info.birthday.day=dlg.m_birthday_day;
addnode->info.marry=dlg.m_marry;
addnode->info.live=dlg.m_live;
//若此人已过世,则还应有死亡日期
if(!dlg.m_live){
addnode->info.deathday.year=dlg.m_deathday_year;
addnode->info.deathday.month=dlg.m_deathday_month;
addnode->info.deathday.day=dlg.m_deathday_day;
}
Person oneself=0;
operFamilytree.Find(operFamilytree.GetRoot(),oneself,addnode->info.name); //查找家谱中有没有此人
if(oneself!=0){
AfxMessageBox("家谱中已有此人!");
delete addnode;
return;
}
Person parent=0;
char parentname[MAX_CHARNUM];
strcpy(parentname,dlg.m_parentname); //加入的结点不是根结点
operFamilytree.Find(operFamilytree.GetRoot(),parent,parentname); //在家谱中找addnode的父结点
if(parent==0){
AfxMessageBox("父亲结点没找到!");
delete addnode;
return;
}
//日期合法性检查
if(!operFamilytree.IsDateValid(addnode->info.birthday)){
AfxMessageBox("个人信息中的出生日期不合实际!");
delete addnode;
return;
}
//比较孩子结点与其父亲结点的出生日期
if(strcmp(parentname,"-1")!=0){ //加入的结点不是根结点
if(operFamilytree.CompareDate(addnode->info.birthday,parent->info.birthday)<0){
AfxMessageBox("所加入孩子的出生日期比其父亲的出生日期早,不合实际!");
delete addnode;
return;
}
else if(operFamilytree.CompareDate(addnode->info.birthday,parent->info.birthday)==0){
AfxMessageBox("所加入孩子的出生日期与其父亲的出生日期相等,不合实际!");
delete addnode;
return;
}
}
if(!addnode->info.live){ //查看死亡日期的合法性
if(!operFamilytree.IsDateValid(addnode->info.deathday)){
AfxMessageBox("个人信息中的死亡日期不合实际!");
delete addnode;
return;
}
if(operFamilytree.CompareDate(addnode->info.birthday,addnode->info.deathday)>0){
AfxMessageBox("此人出生日期不可能比其死亡日期早!");
delete addnode;
return;
}
}
operFamilytree.Add(parent,addnode); //找到,把addnode加入家谱中
HTREEITEM hParentItem=0,hRootItem;
hRootItem=m_peTree.GetRootItem(); //得到树的根结点
if(strcmp(parentname,"-1")!=0) //加入的结点不是根结点
FindInTree(hRootItem,hParentItem,parentname); //在树中找到要加入结点addnode的父结点parentname
AddToTree(hParentItem,addnode); //把此结点加入到树中
RefreshTree(); //刷新该树
IsFamilytreeModified=true; //置家谱修改标记为真
}
void CFamilytreeDlg::RefreshTree()
{
m_peTree.DeleteAllItems();
DisplayFamilytree(operFamilytree.GetRoot());
}
void CFamilytreeDlg::AddToTree(HTREEITEM hParentItem, Person addnode)
{
TVINSERTSTRUCT tvInsert;
tvInsert.hParent=hParentItem;
tvInsert.hInsertAfter=0;
tvInsert.item.mask=TVIF_TEXT;
tvInsert.item.cchTextMax=MAX_CHARNUM;
tvInsert.item.pszText=_T(addnode->info.name);
m_peTree.InsertItem(&tvInsert);
RefreshList();
}
void CFamilytreeDlg::OnFamilytreeDelete()
{
// TODO: Add your command handler code here
CDelInfoDlg dlg;
if(dlg.DoModal()==IDCANCEL)
return;
UpdateData(false);
Person oneself=0; //指向自己的指针
char name[MAX_CHARNUM];
strcpy(name,dlg.m_name); //自己的名字
operFamilytree.Find(operFamilytree.GetRoot(),oneself,name); //查找自己的名字在家谱中的位置
if(oneself==0){
AfxMessageBox("本家谱中找不到"+CString(name)+"!");
return;
}
int answer;
if(oneself->child==0)
answer=::MessageBox(this->m_hWnd,"你确实想删除"+CString(name)+"吗?","警告",MB_YESNO|MB_ICONWARNING);
else
answer=::MessageBox(this->m_hWnd,CString(name)+"还有孩子,如果你删除了他,其孩子也一并被删除。你确实想删除此人及其孩子吗?","警告",MB_YESNO|MB_ICONWARNING);
if(answer==IDNO)
return;
else{
operFamilytree.Delete(oneself);
RefreshTree();
RefreshList();
IsFamilytreeModified=true; //置家谱修改标记为真
}
}
void CFamilytreeDlg::OnFamilytreeModify()
{
// TODO: Add your command handler code here
CModifyInfoDlg dlg;
if(dlg.DoModal()==IDCANCEL)
return;
UpdateData(FALSE);
Person oneself=0;
char oldname[MAX_CHARNUM];
strcpy(oldname,dlg.m_oldname);
operFamilytree.Find(operFamilytree.GetRoot(),oneself,oldname);
if(oneself==0){
AfxMessageBox("本家谱中找不到"+CString(oldname)+"!");
return;
}
Person newValue=new PersonNode;
strcpy(newValue->info.name,dlg.m_newname); //判断家谱中是否已有用户给定的新名字
if(strcmp(newValue->info.name,"\0")==0) //用户不修改姓名
strcpy(newValue->info.name,oldname);
else{
Person p=0;
operFamilytree.Find(operFamilytree.GetRoot(),p,newValue->info.name); //查找家谱中有没有此人
if(p!=0){
AfxMessageBox("家谱中已有此人!");
delete newValue;
return;
}
}
strcpy(newValue->info.addr,dlg.m_newaddr);
newValue->info.marry=dlg.m_marry;
newValue->info.live=dlg.m_live;
newValue->info.birthday=oneself->info.birthday;
if(!newValue->info.live){ //如若过世,则应有死亡日期
newValue->info.deathday.day=dlg.m_deathday_day;
newValue->info.deathday.month=dlg.m_deathday_month;
newValue->info.deathday.year=dlg.m_deathday_year;
if(!operFamilytree.IsDateValid(newValue->info.deathday)){
AfxMessageBox("此人信息中死亡日期不合实际!");
delete newValue;
return;
}
}
operFamilytree.Modify(oneself,newValue);
RefreshTree();
RefreshList();
IsFamilytreeModified=true; //置家谱修改标记为真
delete newValue;
}
void CFamilytreeDlg::InitListCtrl() //初始化列表控件
{
char* colname[8]={"姓名","出生日期","婚否","地址","健在否","死亡日期","孩子数","排行"};
LVCOLUMN lvColumn;
lvColumn.mask=LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
lvColumn.fmt=LVCFMT_CENTER;
lvColumn.cchTextMax=MAX_CHARNUM;
lvColumn.cx=85;
for(int i=0;i<8;i++){
lvColumn.pszText=_T(colname[i]);
m_peList.InsertColumn(i,&lvColumn);
}
m_peList.SetBkColor(RGB(0,128,128));
m_peList.SetTextBkColor(RGB(0,128,128));
m_peList.SetTextColor(RGB(25,250,0));
m_peTree.SetBkColor(RGB(206,227,100));
}
void CFamilytreeDlg::OnSelchangedTreeFamilytree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
HTREEITEM hItem;
hItem=m_peTree.GetSelectedItem();
TVITEM item;
TCHAR szText[MAX_CHARNUM];
item.hItem = hItem;
item.mask = TVIF_TEXT | TVIF_HANDLE;
item.pszText = szText;
item.cchTextMax = MAX_CHARNUM;
BOOL bWorked =m_peTree.GetItem(&item);
if(!bWorked){
AfxMessageBox("程序出现错误,但无法定位于在何处!");
return;
}
Person oneself=0;
operFamilytree.Find(operFamilytree.GetRoot(),oneself,item.pszText);
if(oneself==0){
AfxMessageBox("程序出现不明错误!");
return;
}
RefreshList();
DisplayInListCtrl(oneself);
*pResult = 0;
}
void CFamilytreeDlg::DisplayInListCtrl(Person pNode)
{
LVITEM lvItem;
lvItem.mask=LVIF_TEXT;
lvItem.cchTextMax=MAX_CHARNUM;
//格式化结点信息,以便在列表控件中显示
char info[8][MAX_CHARNUM];
strcpy(info[0],pNode->info.name); //姓名
CString s;
s.Format("%d--%d--%d",pNode->info.birthday.year,pNode->info.birthday.month,
pNode->info.birthday.day);
strcpy(info[1],s); //出生日期
if(pNode->info.marry) //婚否
strcpy(info[2],"是");
else
strcpy(info[2],"否");
strcpy(info[3],pNode->info.addr); //地址
if(pNode->info.live){ //健在否
strcpy(info[4],"是");
strcpy(info[5],"无");
}
else{
strcpy(info[4],"否"); //死亡日期
s.Format("%d--%d--%d",pNode->info.deathday.year,pNode->info.deathday.month,
pNode->info.deathday.day);
strcpy(info[5],s);
}
s.Format("%d",operFamilytree.ChildNums(pNode));
strcpy(info[6],s); //孩子数
s.Format("%d",operFamilytree.InSiblingPos(pNode));
strcpy(info[7],s); //排行
int row=m_peList.GetItemCount();
lvItem.iSubItem=0;
lvItem.iItem=row;
lvItem.pszText=_T(info[0]);
m_peList.InsertItem(&lvItem);
int nColumnCount = m_peList.GetHeaderCtrl()->GetItemCount();
for(int i=1;i<nColumnCount;i++)
m_peList.SetItemText(row,i,info[i]);
}
void CFamilytreeDlg::Display(CString temp) //将字符串temp插入列表控件
{
LVITEM lvItem;
lvItem.mask=LVIF_TEXT;
lvItem.cchTextMax=MAX_CHARNUM;
char info[8][MAX_CHARNUM];
strcpy(info[0],temp);
int row=m_peList.GetItemCount();
lvItem.iSubItem=0;
lvItem.iItem=row;
lvItem.pszText=_T(info[0]);
m_peList.InsertItem(&lvItem);
int nColumnCount = m_peList.GetHeaderCtrl()->GetItemCount();
}
void CFamilytreeDlg::OnFamilytreeRelations()
{
// TODO: Add your command handler code here
CRelationsDlg dlg;
if(dlg.DoModal()==IDCANCEL)
return;
UpdateData(FALSE);
int pos1,pos2;
Person oneself=0;
char name1[MAX_CHARNUM],name2[MAX_CHARNUM];
strcpy(name1,dlg.m_firstname);
operFamilytree.Find(operFamilytree.GetRoot(),oneself,name1);
if(oneself)
pos1=operFamilytree.InGenerationPos(oneself);
else{
AfxMessageBox("本家谱中找不到"+CString(name1)+"!");
return;
}
Person p,q;
CString generation;
generation+=oneself->info.name;
generation+="在家谱中的位置: ";
for(q=oneself,p=q->parent;p!=0;p=p->parent){
generation+=q->info.name;
generation+= "->";
q=p;
}
generation+=q->info.name;
generation+="\n";
oneself=0;
strcpy(name2,dlg.m_secondname);
operFamilytree.Find(operFamilytree.GetRoot(),oneself,name2);
if(oneself)
pos2=operFamilytree.InGenerationPos(oneself);
else{
AfxMessageBox("本家谱中找不到"+CString(name2)+"!");
return;
}
generation+=oneself->info.name;
generation+="在家谱中的位置: ";
for(q=oneself,p=q->parent;p!=0;p=p->parent){
generation+=q->info.name;
generation+= " -> ";
q=p;
}
generation+=q->info.name;
generation+="\n\n";
CString cmpResult;
if(pos1>pos2)
cmpResult.Format("%s在第%d代,%s在第%d代,%s是%s的晚辈.",name1,pos1,name2
,pos2,name1,name2);
else if(pos1<pos2)
cmpResult.Format("%s在第%d代,%s在第%d代,%s是%s的长辈.",name1,pos1,name2
,pos2,name1,name2);
else
cmpResult.Format("%s与%s同在第%d代.",name1,name2,pos2);
generation+=cmpResult;
AfxMessageBox(generation);
}
void CFamilytreeDlg::OnFamilytreePersonalInfo()
{
// TODO: Add your command handler code here
CPersonalInfoDlg dlg;
if(dlg.DoModal()==IDCANCEL)
return;
Person oneself=0;
char name[MAX_CHARNUM];
strcpy(name,dlg.m_name);
operFamilytree.Find(operFamilytree.GetRoot(),oneself,name);
if(!oneself){
AfxMessageBox("没找到此人!");
return ;
}
AfxMessageBox(CString(name)+"的信息请见下部列表.");
RefreshList();
DisplayInListCtrl(oneself);
if(oneself->parent){
Display(" ");
Display(CString(name)+"的父亲:");
DisplayInListCtrl(oneself->parent);
}
if(oneself->child){
Display(" ");
Display(CString(name)+"的长子:");
DisplayInListCtrl(oneself->child);
}
}
void CFamilytreeDlg::OnFamilytreeIgenerationInfo()
{
// TODO: Add your command handler code here
CSearchGenerationDlg dlg;
if(dlg.DoModal()==IDCANCEL)
return;
UpdateData(FALSE);
Person pcur=operFamilytree.GetRoot();
int generation=dlg.m_generation;
if(generation<=0){
AfxMessageBox("输入的数必须大于0!");
return;
}
RefreshList();
int count=1;
bool flag=false;
DisplayGenerationInfo(operFamilytree.GetRoot(),flag,count,generation);
if(flag==false){
AfxMessageBox("你输入的数字超出了家谱中的最大代,家谱还没续到此代!");
return;
}
else
AfxMessageBox("该代所有成员的信息请见下部列表.");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -