📄 treeview.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 + -