⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 familytreedlg.cpp

📁 家族信息管理系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -