Inter - Worked Example
key : purple - original code / blue - new code
Step 1 :
Create a new project using the MFC AppWizard(exe) (this worked example is based on a program called inter). Select Multi Document Application at Step 1 of the Wizard. Set the base class as CListView at the the final step of the Wizard.
Step 2 :
Initialise the OLE/COM libraries. The following code should be added to the InitInstance() function of the App :
BOOL
CADOMFC1App::InitInstance()
{
// Add this function to initialize the OLE/COM libraries
AfxOleInit();
The StdAfx.h file should also be adapted as follows (the #import line should be split between three lines as shown below - if this is not done then an illeagal ecape sequence error will occur)
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <comdef.h>
#import "C:\program files\common files\system\ado\msado15.dll" \
no_namespace \
rename( "EOF", "adoEOF" )
Step 3 :
Declare a pointer to the ADO connection object in the Document. Declare a BOOL variable which will indicate whether this object is opened or closed :
//
Attributes
public:
BOOL
m_IsConnectionOpen;
_ConnectionPtr m_pConnection;
note: (Initialise the BOOL variable to FALSE in the document's constructor)
Step 4 :
Open the database by adding code to the OnNewDocument() function in the Document. Ensure the file path is correct for the data source!
BOOL
CInterDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
HRESULT hr;
hr = m_pConnection.CreateInstance( __uuidof( Connection ) );
if (SUCCEEDED(hr))
{hr = m_pConnection->Open(
_bstr_t(L"Provider=Microsoft.Jet.OLEDB.3.51;Data Source=c:\\myfiles\\access\\names.mdb;"),
_bstr_t(L""),
_bstr_t(L""),
adModeUnknown);
if (SUCCEEDED(hr))
{m_IsConnectionOpen = TRUE;
}
}
return TRUE;
}
Step 5 :
Ensure the Access file is closed by doing so automatically in the Document. Use the ClassWizard to add the following function :
void
CInterDoc::OnCloseDocument()
{
// if when the document closes the connection is still open
// this function will close it automatically
if (m_IsConnectionOpen)
{m_IsConnectionOpen = FALSE;
m_pConnection->Close();}
CDocument::OnCloseDocument();
}
Step 6 :
Add the exception handling code to the OnNewDocument() function in the Document.
BOOL
CInterDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
HRESULT hr;
try
{hr = m_pConnection.CreateInstance( __uuidof( Connection ) );
if (SUCCEEDED(hr))
{hr = m_pConnection->Open(
_bstr_t(L"Provider=Microsoft.Jet.OLEDB.3.51;Data Source=c:\\myfiles\\access\\names.mdb;"),
_bstr_t(L""),
_bstr_t(L""),
adModeUnknown);
if (SUCCEEDED(hr))
{AfxMessageBox("THE SPECIFIED DATABASE HAS BEEN ACCESSED!!!");
m_IsConnectionOpen = TRUE;}
}
}
catch( _com_error &e )
{AfxMessageBox("FAILED - SEE DEBUG INFO!!!");
// Get info from _com_error
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
TRACE( "\nException thrown for classes generated by #import" );
TRACE( "\n\tCode = %081x", e.Error());
TRACE( "\n\tCode meaning = %s", e.ErrorMessage());
TRACE( "\n\tSource = %s", (LPCTSTR) bstrSource);
TRACE( "\n\tDescription = %s\n", (LPCTSTR) bstrDescription);}
catch(...)
{AfxMessageBox("FAILED - SEE DEBUG INFO!!!");
TRACE( "*** Unhandled Exception ***" );}
return TRUE;
}
Step 7 :
Import three files from the MSDN sample DAOVIEW into the project - these will handle the ListCtrl format. These may be downloaded here. The StdAfx.h file needs the following code added :
#include
<afxcview.h>
#include "ctrlext.h"
Step 8 :
Using ClassWizard add an OnCreate() function to the View :
int
CInterView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
lpCreateStruct->style |= LVS_REPORT;
if (CListView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
return 0;
}
Step 9 :
Insert some example data in the Views OnInitialUpdate() function :
void
CInterView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
CListCtrlEx& ctlList = (CListCtrlEx&) GetListCtrl();
ctlList.AddColumn(" First Test Column ", 0);
ctlList.AddColumn(" Second Test Column ", 1);
ctlList.AddColumn(" Third Test Column ", 3);
ctlList.AddItem(0, 0, "First Test Row");
ctlList.AddItem(1, 0, "Second Test Row")
}
Step 10 :
Using ClassWizard add a OnRButtonDown() function - the main data processing here. This is shown in the code below :
void
CInterView::OnRButtonDown(UINT nFlags, CPoint point)
{
_RecordsetPtr pRecordSet;
CInterDoc * pDoc;
pDoc = GetDocument();
// the SQL query is below
_bstr_t bstrQuery("SELECT * FROM names ORDER BY SecondName");
_variant_t vRecsAffected(0L);
try
{pRecordSet = pDoc->m_pConnection->Execute(bstrQuery, &vRecsAffected, adOptionUnspecified);
if (!pRecordSet->GetadoEOF())
{CListCtrlEx& ctlList = (CListCtrlEx&) GetListCtrl();
ctlList.DeleteAllItems();
while(ctlList.DeleteColumn(0));
ctlList.AddColumn("Second Name ",0);
ctlList.AddColumn("Title ",1);
ctlList.AddColumn("First Name ",2);
int i = 0;
_variant_t vSecondName;
_variant_t vTitle;
_variant_t vFirstName;
while (!pRecordSet->GetadoEOF())
{vSecondName = pRecordSet->GetCollect(L"SecondName");
ctlList.AddItem(i,0,(_bstr_t) vSecondName);
vTitle = pRecordSet->GetCollect(L"Title");
ctlList.AddItem(i,1,(_bstr_t) vTitle);
vFirstName = pRecordSet->GetCollect(L"FirstName");
ctlList.AddItem(i,2,(_bstr_t) vFirstName);
i++;
pRecordSet->MoveNext();}
}
pRecordSet->Close();}
catch( _com_error &e )
{AfxMessageBox("FAILED - SEE DEBUG INFO!!!");
// Get info from _com_error
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
TRACE( "\nException thrown for classes generated by #import" );
TRACE( "\n\tCode = %081x", e.Error());
TRACE( "\n\tCode meaning = %s", e.ErrorMessage());
TRACE( "\n\tSource = %s", (LPCTSTR) bstrSource);
TRACE( "\n\tDescription = %s\n", (LPCTSTR) bstrDescription);}
catch(...)
{AfxMessageBox("FAILED - SEE DEBUG INFO!!!");
TRACE( "*** Unhandled Exception ***" );}
CListView::OnRButtonDown(nFlags, point);
}
Click here for the basic exercise
Click here for the source code
Click here to return to menu