ADORDDLG.CPP
//-------------------------------------------------------------------- 
// Microsoft ADO Samples 
// 
// (c) 1996 Microsoft Corporation.  All Rights Reserved. 
// 
// @doc ADORead Sample 
// 
// @moduleADOrddlg.cpp 
// 
// @devnote None 
//-------------------------------------------------------------------- 
 
// ADOReadDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "ADORead.h" 
#include "ADORdDlg.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
const LPCTSTR x_lpcszSource = _T("OLE_DB_NWind_Jet;"); 
const LPCTSTR x_lpcszUser = _T("Admin"); 
 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
class CAboutDlg : public CDialog 
{ 
public: 
CAboutDlg(); 
 
// Dialog Data 
//{{AFX_DATA(CAboutDlg) 
enum { IDD = IDD_ABOUTBOX }; 
//}}AFX_DATA 
 
// Implementation 
protected: 
virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV support 
//{{AFX_MSG(CAboutDlg) 
//}}AFX_MSG 
DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
//{{AFX_DATA_INIT(CAboutDlg) 
//}}AFX_DATA_INIT 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
CDialog::DoDataExchange(pDX); 
//{{AFX_DATA_MAP(CAboutDlg) 
//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
//{{AFX_MSG_MAP(CAboutDlg) 
// No message handlers 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CADOReadDlg dialog 
 
CADOReadDlg::CADOReadDlg(CWnd* pParent /*=NULL*/) 
: CDialog(CADOReadDlg::IDD, pParent) 
{ 
//{{AFX_DATA_INIT(CADOReadDlg) 
m_lCacheSize = 100; 
m_strTableQuery = _T("SELECT EmployeeId, LastName, FirstName FROM Employees"); 
m_lNumRows = 10; 
m_bDynamic = TRUE; 
m_bKeyset = TRUE; 
m_bStatic = TRUE; 
m_bForwardOnly = TRUE; 
m_strSource = x_lpcszSource; //.. D:\\samples\\Employee.mdb 
m_strProvider = _T("msdasql"); 
m_strUser = x_lpcszUser; 
m_lConnectMode  = adModeRead; 
m_lConnectOption  = adPromptAlways; 
//m_bReadOnly = FALSE; 
//}}AFX_DATA_INIT 
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
m_comboBoxOption.Create(CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP| WS_CHILD | WS_VISIBLE,  
CRect(261,7,94,12), this, IDC_ConnectOption); 
m_piConnection = NULL; 
} 
   
CADOReadDlg::~CADOReadDlg() 
{ 
if ( m_piConnection != NULL ) 
m_piConnection->Release();  
m_piConnection = NULL; 
} 
                  
void CADOReadDlg::DoDataExchange(CDataExchange* pDX) 
{ 
CDialog::DoDataExchange(pDX); 
//{{AFX_DATA_MAP(CADOReadDlg) 
DDX_Control(pDX, IDC_ConnectMode, m_comboBoxMode); 
DDX_Control(pDX, IDC_ConnectOption, m_comboBoxOption); 
DDX_Text(pDX, IDC_CACHESIZE, m_lCacheSize); 
DDV_MinMaxLong(pDX, m_lCacheSize, 0, 1200); 
DDX_Text(pDX, IDC_TABLEQUERYEDIT, m_strTableQuery); 
DDX_Text(pDX, IDC_NUMROWS, m_lNumRows); 
DDV_MinMaxLong(pDX, m_lNumRows, 1, 32000); 
DDX_Check(pDX, IDC_Dynamic, m_bDynamic); 
DDX_Check(pDX, IDC_Keyset, m_bKeyset); 
DDX_Check(pDX, IDC_StaticCursor, m_bStatic); 
DDX_Check(pDX, IDC_FORWARDONLY, m_bForwardOnly); 
DDX_Text(pDX, IDC_Source, m_strSource); 
DDV_MaxChars(pDX, m_strSource, 256); 
DDX_Text(pDX, IDC_PROVIDER, m_strProvider); 
DDV_MaxChars(pDX, m_strProvider, 256); 
DDX_Text(pDX, IDC_User, m_strUser); 
DDV_MaxChars(pDX, m_strUser, 256); 
//}}AFX_DATA_MAP 
 
//Do the manual checks 
 
//Check the database name parameter 
if(pDX->m_bSaveAndValidate) 
{ 
pDX->PrepareEditCtrl(IDC_Source); 
if (m_strSource.IsEmpty())  
{ 
MessageBox(_T("Missing Jet database name."), _T("ADO Test App Error"), MB_ICONEXCLAMATION ); 
pDX->Fail(); 
} 
} 
 
 
//Check the Table/Query parameter 
if(pDX->m_bSaveAndValidate) 
{ 
pDX->PrepareEditCtrl(IDC_TABLEQUERYEDIT); 
if (m_strTableQuery.IsEmpty())  
{ 
MessageBox(_T("Missing table,query or SQL."), _T("ADO Test App Error"), MB_ICONEXCLAMATION ); 
pDX->Fail(); 
} 
} 
} 
 
BEGIN_MESSAGE_MAP(CADOReadDlg, CDialog) 
//{{AFX_MSG_MAP(CADOReadDlg) 
ON_WM_SYSCOMMAND() 
ON_WM_PAINT() 
ON_WM_QUERYDRAGICON() 
ON_BN_CLICKED(IDC_DATABASEBUTTON, OnDatabase) 
ON_BN_CLICKED(ID_EXECUTE, OnExecute) 
ON_CBN_SELCHANGE(IDC_ConnectMode, OnSelchangeConnectMode) 
ON_CBN_SELCHANGE(IDC_ConnectOption, OnSelchangeConnectOption) 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CADOReadDlg message handlers 
 
BOOL CADOReadDlg::OnInitDialog() 
{ 
CDialog::OnInitDialog(); 
 
// Add "About..." menu item to system menu. 
 
// IDM_ABOUTBOX must be in the system command range. 
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
ASSERT(IDM_ABOUTBOX < 0xF000); 
 
CMenu* pSysMenu = GetSystemMenu(FALSE); 
CString strAboutMenu; 
strAboutMenu.LoadString(IDS_ABOUTBOX); 
if (!strAboutMenu.IsEmpty()) 
{ 
pSysMenu->AppendMenu(MF_SEPARATOR); 
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
} 
 
 
//Set default selections 
SetDlgItemText(IDC_CACHESIZE, _T("100")); 
SetDlgItemText(IDC_NUMROWS, _T("10")); 
 
return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CADOReadDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
{ 
CAboutDlg dlgAbout; 
dlgAbout.DoModal(); 
} 
else 
{ 
CDialog::OnSysCommand(nID, lParam); 
} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CADOReadDlg::OnPaint()  
{ 
if (IsIconic()) 
{ 
CPaintDC dc(this); // device context for painting 
 
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
// Center icon in client rectangle 
int cxIcon = GetSystemMetrics(SM_CXICON); 
int cyIcon = GetSystemMetrics(SM_CYICON); 
CRect rect; 
GetClientRect(&rect); 
int x = (rect.Width() - cxIcon + 1) / 2; 
int y = (rect.Height() - cyIcon + 1) / 2; 
 
// Draw the icon 
dc.DrawIcon(x, y, m_hIcon); 
} 
else 
{ 
CDialog::OnPaint(); 
} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CADOReadDlg::OnQueryDragIcon() 
{ 
return (HCURSOR) m_hIcon; 
} 
 
void CADOReadDlg::OnDatabase()  
{ 
CFileDialog*pcBrowse;//Need a file open dialog 
 
pcBrowse = (CFileDialog*)new CFileDialog(TRUE,_T("mdb"),NULL,NULL,_T("Jet Database Files | *.mdb ||"), NULL); 
 
pcBrowse->DoModal(); 
 
(GetDlgItem(IDC_Source))->SetWindowText(pcBrowse->GetPathName()); 
 
delete pcBrowse; 
} 
 
 
 
void CADOReadDlg::Execute( 
CursorTypeEnumcursorType, 
intiControlID, 
intiUnitsID 
)  
{ 
ADORecordset*piRecordSet; 
DWORDdwStart, dwEnd; 
DWORDdwDuration; 
LONGlIndex; 
COleVariantdbVar; 
COleVariantvNull; 
HRESULThr; 
BSTRbstrTableQuery; 
VARIANT_BOOLvbEOF; 
 
dwStart = timeGetTime(); 
 
//Open recordset  
hr = CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_INPROC_SERVER, IID_IADORecordset, (LPVOID *)&piRecordSet); 
if (FAILED(hr))goto ErrorExit; 
 
//Check that recordset was created 
if (piRecordSet != NULL) 
{ 
bstrTableQuery = m_strTableQuery.AllocSysString(); 
hr = piRecordSet->put_Source(bstrTableQuery);// convert to bstr  
if (FAILED(hr))goto ErrorExit; 
 
hr = piRecordSet->putref_ActiveConnection(m_piConnection); 
if (FAILED(hr))goto ErrorExit; 
 
//Set the cache size to value supplied by user. 
hr = piRecordSet->put_CacheSize(m_lCacheSize); 
if (FAILED(hr))goto ErrorExit; 
 
vNull.vt = VT_ERROR; 
vNull.scode = DISP_E_PARAMNOTFOUND; 
hr = piRecordSet->Open(vNull, vNull, cursorType, adLockOptimistic, adCmdUnknown); 
if (FAILED(hr))goto ErrorExit; 
 
//Watch for end of record set 
piRecordSet->get_EOF(&vbEOF); 
if (FAILED(hr))goto ErrorExit; 
 
for (lIndex = 0L; !vbEOF && lIndex < m_lNumRows; lIndex++) 
{ 
//Get the first returned column 
hr = piRecordSet->get_Collect(COleVariant(0L, VT_I4), &dbVar); 
if (FAILED(hr))goto ErrorExit; 
 
AddFieldToList(lIndex, &dbVar); 
hr = piRecordSet->MoveNext(); 
if (FAILED(hr))goto ErrorExit; 
piRecordSet->get_EOF(&vbEOF); 
if (FAILED(hr))goto ErrorExit; 
//dbVar.Clear();// release memory 
} 
 
//Report the estimated execute time (in milliseconds) 
dwEnd = timeGetTime(); 
dwDuration = dwEnd - dwStart; 
DisplayQueryTime(iControlID, iUnitsID, dwDuration); 
} 
else 
{ 
(GetDlgItem(IDC_DynamicTIME))->SetWindowText(_T("ERROR")); 
} 
 
piRecordSet->Release(); 
SysFreeString(bstrTableQuery); 
return ; 
 
 ErrorExit: 
TCHAR szBuf[256]; 
wsprintf(szBuf, _T("Error: %d \n"), hr); 
AfxMessageBox(szBuf); 
 
piRecordSet->Release(); 
SysFreeString(bstrTableQuery); 
return ; 
} 
 
 
//When the Execute button is pressed, run through the selected methods and perform each 
//reporting an approximate execution time and listing the first field returned (only if 
//it's a string or numeric) 
 
void CADOReadDlg::OnExecute()  
{ 
CListBox*pList = ((CListBox *)(GetDlgItem(IDC_ROWSLIST))); 
HRESULThr; 
BSTRbstrSource; 
BSTRbstrUser; 
BSTRbstrProvider; 
CStringstrSource, strUser,strPassword, strProvider; 
static BOOLEANfIsFirstTime = TRUE; 
 
//Update the parameters 
if (!UpdateData(TRUE)) 
{ 
return; 
} 
 
// This could take a while,  
CWaitCursor wait; 
 
//Clear the list 
pList->ResetContent(); 
 
// Following is a series of database table retrieves using variations 
// on the Recordset object. This isn't a great programming structure, 
// but it shows each method clearly. 
 
//Execute each the requested read methods, recording a time for each 
//Open the database 
if ( m_piConnection == NULL ) 
{ 
hr = CoInitialize(NULL); 
if (FAILED(hr))goto ErrorExit; 
hr = CoCreateInstance(CLSID_CADOConnection, NULL, CLSCTX_INPROC_SERVER, IID_IADOConnection, (LPVOID *)&m_piConnection); 
if (FAILED(hr))goto ErrorExit; 
} 
 
(GetDlgItem(IDC_Source))->GetWindowText(strSource);   
(GetDlgItem(IDC_User))->GetWindowText(strUser);    
(GetDlgItem(IDC_Password))->GetWindowText(strPassword); 
(GetDlgItem(IDC_PROVIDER))->GetWindowText(strProvider); 
 
if ( fIsFirstTime || m_strSource != strSource  || m_strUser != strUser||  
m_strPassword != strPassword || m_strProvider != strProvider ) 
{ 
fIsFirstTime = FALSE; 
m_strSource = strSource ; 
m_strUser = strUser;  
m_strPassword = strPassword ; 
m_strProvider = strProvider; 
 
bstrSource = m_strSource.AllocSysString(); 
bstrUser = m_strUser.AllocSysString(); 
bstrProvider = m_strProvider.AllocSysString(); 
if ( bstrProvider == NULL || bstrSource == NULL || bstrUser == NULL)goto ErrorExit;  
 
if (FAILED(hr = m_piConnection->put_Provider(bstrProvider))) 
goto ErrorExit; 
 
hr = m_piConnection->Open( bstrSource, bstrUser, NULL );  //toaddpassword 
 if (FAILED(hr))goto ErrorExit; 
 
SysFreeString(bstrProvider); 
SysFreeString(bstrSource); 
SysFreeString(bstrUser); 
} 
 
//Open recordset on as a Dynamic 
if(m_bDynamic) 
{ 
pList->AddString(_T("Dynamic Cursor")); 
pList->AddString(_T("==========================")); 
Execute( adOpenDynamic, IDC_DynamicTIME, IDC_UNITDynamic ); 
} 
//Open recordset on as a Keyset 
if(m_bKeyset) 
{ 
pList->AddString(_T("Keyset Cursor")); 
pList->AddString(_T("==========================")); 
Execute( adOpenKeyset, IDC_KeysetTIME, IDC_UNITDYNA ); 
} 
//Open recordset on as a Static 
if(m_bStatic) 
{ 
pList->AddString(_T("Static Cursor")); 
pList->AddString(_T("==========================")); 
Execute( adOpenStatic, IDC_StaticTIME, IDC_UNITSNAP ); 
} 
//Open recordset on as ForwardOnly 
if(m_bForwardOnly) 
{ 
pList->AddString(_T("ForwardOnly Cursor")); 
pList->AddString(_T("==========================")); 
Execute( adOpenForwardOnly, IDC_FORWARDONLYTIME, IDC_UNITFORWARDONLY ); 
}  
 
return ; 
 
 ErrorExit: 
TCHAR szBuf[256]; 
wsprintf(szBuf, _T("Error: %d \n"), hr); 
AfxMessageBox(szBuf); 
 
SysFreeString(bstrProvider); 
SysFreeString(bstrSource); 
SysFreeString(bstrUser); 
return ; 
 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Other functions 
 
void CADOReadDlg::DisplayQueryTime(int iControlID, int iUnitsID, DWORD dwDuration) 
{ 
CString strDisp; 
CString strUnits(_T("ms")); 
doublefDuration = dwDuration; 
 
//Did it go into minutes? 
if(fDuration >= 60000.0) 
{ 
fDuration = fDuration/60000.0; 
strUnits = _T("M"); 
} 
//Did it go to seconds? 
else if(fDuration >= 1000.0) 
{ 
fDuration = fDuration/1000.0; 
strUnits = _T("S"); 
} 
 
strDisp.Format(_T("%.2f"), fDuration); 
 
(GetDlgItem(iUnitsID))->SetWindowText(strUnits); 
(GetDlgItem(iControlID))->SetWindowText(strDisp); 
 
} 
 
void CADOReadDlg::AddFieldToList(LONG lRecordNum, COleVariant *pdbVar) 
{ 
CStringstrDisp; 
CStringstrScratch; 
CListBox*pList = ((CListBox *)(GetDlgItem(IDC_ROWSLIST))); 
 
//Add record number 
strDisp.Format(_T("%d - "), lRecordNum); 
 
//NOTE: This only works for strings/numerics 
 
switch(pdbVar->vt) 
{ 
case VT_BSTR: 
{ 
strDisp += (LPCTSTR)pdbVar->bstrVal; 
break; 
} 
 
case VT_I4: 
{ 
strScratch.Format(_T("%d"), pdbVar->lVal); 
strDisp += strScratch; 
break; 
} 
 
case VT_UI1: 
{ 
strScratch.Format(_T("%u"), pdbVar->bVal); 
strDisp += strScratch; 
break; 
} 
 
case VT_I2: 
{ 
strScratch.Format(_T("%d"), pdbVar->iVal); 
strDisp += strScratch; 
break; 
} 
 
case VT_R4: 
{ 
strScratch.Format(_T("%f"), pdbVar->fltVal); 
strDisp += strScratch; 
break; 
} 
 
case VT_R8 : 
{ 
strScratch.Format(_T("%f"), pdbVar->dblVal); 
strDisp += strScratch; 
break; 
} 
 
default: // 
{ 
strDisp += _T("Field type not supported by sample code"); 
} 
 
} 
pList->AddString(strDisp); 
 
} 
 
ConnectPromptEnum rgConnectPrompts[] = {adPromptAlways, 
adPromptComplete, 
adPromptCompleteRequired, 
adPromptNever}; 
 
void CADOReadDlg::OnSelchangeConnectOption()  
{ 
m_lConnectOption = rgConnectPrompts[m_comboBoxOption.GetCurSel()]; 
} 
 
ConnectModeEnum rgConnectModes[] = {adModeRead,  
adModeWrite,  
adModeReadWrite,  
adModeShareDenyRead, 
adModeShareDenyWrite, 
adModeShareExclusive, 
adModeShareDenyNone}; 
 
void CADOReadDlg::OnSelchangeConnectMode()  
{ 
 
m_lConnectMode = rgConnectModes[m_comboBoxMode.GetCurSel()]; 
}