The EX31B example is an "add-change-delete" application that's different from the Access model. The user must explicitly add, update, and delete records. Even if you prefer the Access-style behavior, you can learn a lot about the CRecordView class by going through the steps in the EX31B example.
Here are the steps for building the EX31B example:
When you're finished adding variable names for each edit box, you'll see a screen like the one shown here.
Menu Command | Command ID | Command Handler | Update Command UI Handler |
Add Record | ID_RECORD_ADD | OnRecordAdd | |
Clear Fields | ID_RECORD_CLEARFIELDS | OnRecordClearfields | |
Delete Record | ID_RECORD_DELETE | OnRecordDelete | OnUpdateRecordDelete |
Update Record | ID_RECORD_UPDATE | OnRecordUpdate | OnUpdateRecordUpdate |
BOOL CEx31bView::OnMove(UINT nIDMoveCommand) { switch (nIDMoveCommand) { case ID_RECORD_PREV: m_pSet->MovePrev(); if (!m_pSet->IsBOF()) break; case ID_RECORD_FIRST: m_pSet->MoveFirst(); break; case ID_RECORD_NEXT: m_pSet->MoveNext(); if (!m_pSet->IsEOF()) break; if (!m_pSet->CanScroll()) { // Clear screen since we're sitting on EOF m_pSet->SetFieldNull(NULL); break; } case ID_RECORD_LAST: m_pSet->MoveLast(); break; default: // unexpected case value ASSERT(FALSE); } // Show results of Move operation UpdateData(FALSE); return TRUE; }
Also, add the declaration for this overridden function to the ex31bView.h header file.
If you have a sorted recordset (or if your ODBC driver doesn't put added records in the recordset), you should call CRecordset::Requery to completely regenerate the recordset. In that case, there's no convenient way to position the cursor on the newly added record, and that's a basic problem with SQL.
Add the following boldface code:
void CEx31bView::OnRecordAdd() { m_pSet->AddNew(); UpdateData(TRUE); if (m_pSet->CanUpdate()) { m_pSet->Update(); } if (!m_pSet->IsEOF()) { m_pSet->MoveLast(); } m_pSet->Requery(); // for sorted sets UpdateData(FALSE); } void CEx31bView::OnRecordClearfields() { m_pSet->SetFieldNull(NULL); UpdateData(FALSE); } void CEx31bView::OnRecordDelete() { CRecordsetStatus status; try { m_pSet->Delete(); } catch(CDBException* e) { AfxMessageBox(e->m_strError); e->Delete(); m_pSet->MoveFirst(); // lost our place! UpdateData(FALSE); return; } m_pSet->GetStatus(status); if (status.m_lCurrentRecord == 0) { // We deleted last of 2 records m_pSet->MoveFirst(); } else { m_pSet->MoveNext(); } UpdateData(FALSE); } void CEx31bView::OnUpdateRecordDelete(CCmdUI* pCmdUI) { pCmdUI->Enable(!m_pSet->IsEOF()); } void CEx31bView::OnRecordUpdate() { m_pSet->Edit(); UpdateData(TRUE); if (m_pSet->CanUpdate()) { m_pSet->Update(); } // should requery if key field changed } void CEx31bView::OnUpdateRecordUpdate(CCmdUI* pCmdUI) { pCmdUI->Enable(!m_pSet->IsEOF()); }