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

📄 treeview.cpp

📁 API经典入门
💻 CPP
字号:
// treeview.cpp : implementation of the CTreeView class
//

#include "stdafx.h"
#include "tree.h"

#include "treeset.h"
#include "unionset.h"
#include "treedoc.h"
#include "treeview.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTreeView

IMPLEMENT_DYNCREATE(CTreeView, CRecordView)

BEGIN_MESSAGE_MAP(CTreeView, CRecordView)
	//{{AFX_MSG_MAP(CTreeView)
	ON_WM_LBUTTONDBLCLK()
	ON_LBN_DBLCLK(IDC_Children, OnDblclkChildren)
	ON_LBN_DBLCLK(IDC_Siblings, OnDblclkSiblings)
	ON_CBN_DBLCLK(IDC_Spouses, OnDblclkSpouses)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CRecordView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRecordView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTreeView construction/destruction

CTreeView::CTreeView()
	: CRecordView(CTreeView::IDD)
{
	//{{AFX_DATA_INIT(CTreeView)
	m_pSet = NULL;
	m_strFather = "";
	m_strMGFather = "";
	m_strMGMother = "";
	m_strMother = "";
	m_strPGFather = "";
	m_strPGMother = "";
	//}}AFX_DATA_INIT
	// TODO: add construction code here
}

CTreeView::~CTreeView()
{
}

void CTreeView::DoDataExchange(CDataExchange* pDX)
{
	CRecordView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTreeView)
	DDX_Control(pDX, IDC_Spouses, m_ctlSpouses);
	DDX_Control(pDX, IDC_Siblings, m_ctlSiblings);
	DDX_Control(pDX, IDC_Children, m_ctlChildren);
	DDX_FieldText(pDX, IDC_FirstName, m_pSet->m_FIRST, m_pSet);
	DDX_FieldText(pDX, IDC_LastName, m_pSet->m_LAST, m_pSet);
	DDX_FieldText(pDX, IDC_MiddleName, m_pSet->m_MIDDLE, m_pSet);
	DDX_Text(pDX, IDC_Father, m_strFather);
	DDX_Text(pDX, IDC_MGFather, m_strMGFather);
	DDX_Text(pDX, IDC_MGMother, m_strMGMother);
	DDX_Text(pDX, IDC_Mother, m_strMother);
	DDX_Text(pDX, IDC_PGFather, m_strPGFather);
	DDX_Text(pDX, IDC_PGMother, m_strPGMother);
	//}}AFX_DATA_MAP
}

void CTreeView::OnInitialUpdate()
{
	m_pSet = &GetDocument()->m_treeSet;
	CRecordView::OnInitialUpdate();

}

/////////////////////////////////////////////////////////////////////////////
// CTreeView printing

BOOL CTreeView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CTreeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CTreeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CTreeView diagnostics

#ifdef _DEBUG
void CTreeView::AssertValid() const
{
	CRecordView::AssertValid();
}

void CTreeView::Dump(CDumpContext& dc) const
{
	CRecordView::Dump(dc);
}

CTreeDoc* CTreeView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTreeDoc)));
	return (CTreeDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTreeView database support

CRecordset* CTreeView::OnGetRecordset()
{
	return m_pSet;
}

BOOL CTreeView::OnMove(UINT nIDMoveCommand)
{
	UpdateData(FALSE);
	if( CRecordView::OnMove(nIDMoveCommand) )
	{
		UpdateRelatives();
		return TRUE;
	}
	else
		return FALSE;
}

void CTreeView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
	CRecordView::OnUpdate(pSender, lHint, pHint);
	
	UpdateData(FALSE);
	UpdateRelatives();
	//ASSERT(pSender != this);

	// invalidate the entire pane, erase background too
	//Invalidate(TRUE);
}

void CTreeView::UpdateRelatives()
{
	if (!m_pSet->IsOpen())
	{
		TRACE0("Record set is not open in UpdateRelatives().\n");
		return;
	}

	ResetStrings();
		
	// Declare a new Person record set object but
	// use the same database object.
	CTreeSet TS(m_pSet->m_pDatabase);

	BeginWaitCursor();
	TS.m_strFilter = "ID = ?";
	if ( TS.Open() )
	{
		// Get Parent Names
		GetMomDad(&TS, m_pSet->m_ID, m_strMother, m_strFather);
		
		// Get Maternal Grandparent Names
		if ( !m_pSet->IsFieldNull(&m_pSet->m_MOTHER) )
			GetMomDad(&TS, m_pSet->m_MOTHER, 
					m_strMGMother, m_strMGFather);

		// Get Paternal Grandparent Names		
		if ( !m_pSet->IsFieldNull(&m_pSet->m_FATHER) )
			GetMomDad(&TS, m_pSet->m_FATHER, 
					m_strPGMother, m_strPGFather);

		TS.Close();
	}

	// Get Spouses' Names
	FillSpouses();

	// Get Siblings' Names
	FillSiblings();
	
	// Get Children's Names
	FillChildren();
		
	EndWaitCursor();
	
	UpdateData(FALSE);
}

void CTreeView::ResetStrings()
{
	CString Unknown = "?????";
	
	m_strFather = Unknown;
	m_strMother = Unknown;
	m_strPGFather = Unknown;
	m_strPGMother = Unknown;
	m_strMGFather = Unknown;
	m_strMGMother = Unknown;
}
	
void CTreeView::GetMomDad( CTreeSet* pSet, double fSubjectID,
			CString& strMom, CString& strDad)
{
	BOOL bMomExists = FALSE;
	double fMom = 0;

	if ( !(pSet->IsOpen()) )
	{
		TRACE0("Record set passed to GetMomDad() is not open!\n");
		return;
	}

	pSet->m_fIDParam = fSubjectID;
	pSet->Requery();
	if ( pSet->IsBOF() && pSet->IsEOF() )
	{
		TRACE0("fSubjectID passed to GetMomDad() is invalid!\n");
		return;
	}

	// if the mother field is not NULL save mother data
	if ( !pSet->IsFieldNull(&pSet->m_MOTHER) )
	{
		bMomExists = TRUE;
		fMom = pSet->m_MOTHER;
	}

	// if the father field is not NULL retrieve the father's name
	if ( !pSet->IsFieldNull(&pSet->m_FATHER) )
	{
		pSet->m_fIDParam = pSet->m_FATHER;
		pSet->Requery();
		if ( pSet->IsBOF() && pSet->IsEOF() )
			TRACE0("Father ID invalid!\n");
		else
			strDad = pSet->FullName();
	}
	
	// Now go back and retrieve the mother's name if possible
	if (bMomExists)
	{
		pSet->m_fIDParam = fMom;
		pSet->Requery();
		if ( pSet->IsBOF() && pSet->IsEOF() )
			TRACE0("Mother ID is invalid!\n");
		else
			strMom = pSet->FullName();
	}
					
}
				
void CTreeView::FillSpouses()
{
	double fTempID;
	int nTemp;
	CString S;

	if ( !m_pSet->IsOpen() )
	{
		TRACE0("Record set is not open in FillSpouses()!");
		return;
	}
	
	// Declare record set objects but
	// use an existing database object.
	CTreeSet TS(m_pSet->m_pDatabase);
	CUnionSet US(m_pSet->m_pDatabase);

	// clear the Spouses combo box
	m_ctlSpouses.ResetContent();
	
	// prepare TS for ID searching
	TS.m_strFilter = "ID = ?";
	if ( !TS.Open() )
	{
		TRACE0("Tree set failed to open in FillSpouses()!");
		return;
	}
	
	if (m_pSet->m_IS_MALE)
		US.m_strFilter = "HUSBAND = ?";
	else
		US.m_strFilter = "WIFE = ?";

	US.m_fIDParam = m_pSet->m_ID;
	if ( US.Open() )
	{
		if ( !(US.IsBOF() && US.IsEOF()) )
		{
			US.MoveFirst();
			while ( !US.IsEOF() )
			{
				if (m_pSet->m_IS_MALE)
					fTempID = US.m_WIFE;
				else
					fTempID = US.m_HUSBAND; 
						
				TS.m_fIDParam = fTempID;
				TS.Requery();
				if ( !(TS.IsBOF() && US.IsEOF()) )
				{
					S = TS.FullName();
					nTemp = m_ctlSpouses.AddString(S);
					m_ctlSpouses.SetItemData(nTemp, (DWORD)fTempID);
				}
				else
					TRACE1("DB Corruption: ID [%f] not in PERSON Table", fTempID);
			    US.MoveNext();
			}
			// select the first string in the box
			m_ctlSpouses.SetCurSel(0);
		}
		US.Close();
	}
	
	TS.Close();
}

void CTreeView::FillChildren()
{
	int nTemp;
	CString S;

	if ( !m_pSet->IsOpen() )
	{
		TRACE0("Record set is not open in FillChildren()!\n");
		return;
	}
		
	// Declare a new Person record set object but
	// use the same database object.
	CTreeSet TS(m_pSet->m_pDatabase);

	// Clear the Children List Box
	m_ctlChildren.ResetContent();

	if (m_pSet->m_IS_MALE)
		TS.m_strFilter = "FATHER = ?";
	else
		TS.m_strFilter = "MOTHER = ?";
	
	TS.m_fIDParam = m_pSet->m_ID;
	if ( TS.Open() )
	{
		if ( !(TS.IsBOF() && TS.IsEOF()) )
		{
			// fill child list box with elements of record set
			TS.MoveFirst();
			while ( !TS.IsEOF() )
			{
				S = TS.FullName();
				nTemp = m_ctlChildren.AddString(S);
				m_ctlChildren.SetItemData(nTemp, (DWORD)TS.m_ID);
				TS.MoveNext();
			}
		}
		
		TS.Close();
	}
	else
		TRACE0("Tree set failed to open in FillChildren()!\n");
	
}

void CTreeView::FillSiblings()
{
	int nTemp;

	if ( !m_pSet->IsOpen() )
	{
		TRACE0("Record set is not open in FillSiblings()!\n");
		return;
	}

	// Declare a new Person record set object but
	// use the same database object.
	CTreeSet TS(m_pSet->m_pDatabase);

	// Clear the Siblings List Box
	m_ctlSiblings.ResetContent();
	
	TS.m_strFilter = "FATHER = ?";
	TS.m_fIDParam = m_pSet->m_FATHER;
	
	if ( TS.Open() )
	{
		if ( !(TS.IsEOF() && TS.IsBOF()) )
		{
			// fill sibling list with elements of record set
			TS.MoveFirst();
			while ( !TS.IsEOF() )
			{
				if (TS.m_ID != m_pSet->m_ID)
				{
					nTemp = m_ctlSiblings.AddString(TS.FullName());
					m_ctlSiblings.SetItemData(nTemp, (DWORD)TS.m_ID);
				}
				TS.MoveNext();
			}
		}
		
		TS.Close();
	}	
	else
		TRACE0("Tree set failed to open in FillSiblings()!\n");
		
	// note that the above code will only load up your siblings
	// due to your father.  Half-siblings on your mother's side
	// will not be included!

}

/////////////////////////////////////////////////////////////////////////////
// CTreeView message handlers

void CTreeView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	CTreeDoc* pDoc = GetDocument();

	CWnd* pCtl = GetDlgItem(IDC_FatherBox);
	CRect CtlRect;
	
	pCtl->GetWindowRect(&CtlRect);
	ScreenToClient(&CtlRect);

	// Check to see if the point is in the Father box.
	if ( CtlRect.PtInRect(point) )
	{
		// if there is no father ID, then there is nothing to do.
		if (pDoc->m_treeSet.IsFieldNull(&pDoc->m_treeSet.m_FATHER))
			return;
	
		if ( !pDoc->MoveTo(pDoc->m_treeSet.m_FATHER) )
			TRACE("DB Corruption: Father ID : %i NOT FOUND\n",
					pDoc->m_treeSet.m_FATHER);
					
		return;
	}
	
	pCtl = GetDlgItem(IDC_MotherBox);
	pCtl->GetWindowRect(&CtlRect);
	ScreenToClient(&CtlRect);
	
	// Check to see if the point is in the Mother box.
	if ( CtlRect.PtInRect(point) )
	{ 
		// if there is no mother ID, then there is nothing to do.
		if (pDoc->m_treeSet.IsFieldNull(&pDoc->m_treeSet.m_MOTHER))
			return;
	
		if ( !pDoc->MoveTo(pDoc->m_treeSet.m_MOTHER) )
			TRACE("DB Corruption: Mother ID : %i NOT FOUND\n",
					pDoc->m_treeSet.m_MOTHER);
					
		return;
	}

	CRecordView::OnLButtonDblClk(nFlags, point);
	
	pCtl = GetDlgItem(IDC_NameBox);
	pCtl->GetWindowRect(&CtlRect);
	ScreenToClient(&CtlRect);
	
	// Check to see if the point is in the Name box.
	if ( CtlRect.PtInRect(point) )
		pDoc->EditCurrentPerson();

	// Alternatively we could send an WM_COMMAND message
	// to the main frame with the associated notification
	// message ID_RECORD_EDIT.  Recall the messaging
	// discussions earlier in the book.  This command will
	// be routed through to the document.  If you're thinking
	// why not cut out the middle man and send a message 
	// directly to the document, remember that the document
	// is not a window class it is derived from CCmdTarget.

}


void CTreeView::OnDblclkChildren()
{
	CTreeDoc* pDoc = GetDocument();
	
	double fID = (double)m_ctlChildren.GetItemData(m_ctlChildren.GetCurSel());
	if ( pDoc->MoveTo(fID) )
		UpdateRelatives();
}

void CTreeView::OnDblclkSiblings()
{
	CTreeDoc* pDoc = GetDocument();
	
	double fID = (double)m_ctlSiblings.GetItemData(m_ctlSiblings.GetCurSel());
	if ( pDoc->MoveTo(fID) )
		UpdateRelatives();
}

void CTreeView::OnDblclkSpouses()
{
	CTreeDoc* pDoc = GetDocument();
	
	double fID = (double)m_ctlSpouses.GetItemData(m_ctlSpouses.GetCurSel());
	if ( pDoc->MoveTo(fID) )
		UpdateRelatives();
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -