📄 vcg14.htm
字号:
<P>PostalCode using the field PostalCode
<BR>
</BLOCKQUOTE></BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<HR ALIGN=CENTER>
<BR>
<NOTE><B>NOTE</B>
<BR>
<BR>Indexes can have one or more fields. In the example, each index has only one field. Some database applications have indexes that comprise multiple fields. For a multiple-field index, you would define your CDaoIndexFieldInfo object as an array and indicate the number of fields used in the CDaoIndexInfo::m_nFields member.</NOTE>
<BR>
<HR ALIGN=CENTER>
</BLOCKQUOTE></BLOCKQUOTE>
<P>To create an index, you must allocate a CDaoIndexInfo object and either a single CDaoIndexFieldInfo if your index will have only one field or an array of type CDaoIndexFieldInfo if your index will have more than one field. For example, your program uses this code:
<BR>
<PRE>
<FONT COLOR="#000080">// Finally, create the (optional) index fields. The example has
// four sets of indexes, each having only one field:
CDaoIndexInfo idx;
CDaoIndexFieldInfo fld; // Only one field per index in the example</FONT></PRE>
<P>After you've allocated your index and index field objects, you must fill them in. To create your primary key, use this code:
<BR>
<PRE>
<FONT COLOR="#000080">// Fill in your structure with revelant information, then build
// the index. CDaoTableDef::CreateIndex() calls Append
// automatically, unlike CDaoTableDef::CreateField(), which does not.
idx.m_strName = _T("PrimaryKey"); // Primary
idx.m_pFieldInfos = &fld; // Primary
idx.m_nFields = 1; // Primary
idx.m_bPrimary = TRUE; // Secondary
idx.m_bUnique = TRUE; // Secondary
idx.m_bClustered = FALSE; // Secondary
idx.m_bIgnoreNulls = FALSE; // Secondary
idx.m_bRequired = TRUE; // Secondary
idx.m_bForeign = FALSE; // Secondary
idx.m_lDistinctCount = 5; // All - returned, not set!
fld.m_strName = _T("AddressID"); // Key field
fld.m_bDescending = FALSE; // Ascending
TableDef.CreateIndex(idx); // Create primary index</FONT></PRE>
<P>The comments //Primary, //Secondary, and //All refer to which fields are returned when you call the CDaoTableDef::GetIndexInfo() or CDaoRecordset::GetIndexInfo() functions. You must fill in all fields (except for CDaoIndexInfo::m_lDistinctCount, which is only used to return information about an existing index).
<BR>
<BLOCKQUOTE>
<BLOCKQUOTE>
<HR ALIGN=CENTER>
<BR>
<NOTE><B>CAUTION</B>
<BR>
<BR>By design, a database can have one, and only one, primary key. The primary key is often used by the database engine to manage records in the table. A database table can have other, alternative keys if desired.</NOTE>
<BR>
<HR ALIGN=CENTER>
</BLOCKQUOTE></BLOCKQUOTE>
<P>To create the secondary keys, use this code:
<BR>
<PRE>
<FONT COLOR="#000080">idx.m_strName = _T("EmailAddress"); // Primary
idx.m_pFieldInfos = &fld; // Primary
idx.m_nFields = 1; // Primary
idx.m_bPrimary = FALSE; // Secondary
idx.m_bUnique = FALSE; // Secondary
idx.m_bClustered = FALSE; // Secondary
idx.m_bIgnoreNulls = FALSE; // Secondary
idx.m_bRequired = FALSE; // Secondary
idx.m_bForeign = FALSE; // Secondary
idx.m_lDistinctCount = 5; // All - returned, not set!
fld.m_strName = _T("EmailAddress"); // Key field
fld.m_bDescending = FALSE; // Ascending
TableDef.CreateIndex(idx); // Create secondary index
idx.m_strName = _T("LastName"); // Primary
idx.m_pFieldInfos = &fld; // Primary
idx.m_nFields = 1; // Primary
idx.m_bPrimary = FALSE; // Secondary
idx.m_bUnique = FALSE; // Secondary
idx.m_bClustered = FALSE; // Secondary
idx.m_bIgnoreNulls = FALSE; // Secondary
idx.m_bRequired = FALSE; // Secondary
idx.m_bForeign = FALSE; // Secondary
idx.m_lDistinctCount = 5; // All - returned, not set!
fld.m_strName = _T("LastName"); // Key field
fld.m_bDescending = FALSE; // Ascending
TableDef.CreateIndex(idx); // Create secondary index
idx.m_strName = _T("PostalCode"); // Primary
idx.m_pFieldInfos = &fld; // Primary
idx.m_nFields = 1; // Primary
idx.m_bPrimary = FALSE; // Secondary
idx.m_bUnique = FALSE; // Secondary
idx.m_bClustered = FALSE; // Secondary
idx.m_bIgnoreNulls = FALSE; // Secondary
idx.m_bRequired = FALSE; // Secondary
idx.m_bForeign = FALSE; // Secondary
idx.m_lDistinctCount = 5; // All - returned, not set!
fld.m_strName = _T("PostalCode"); // Key field
fld.m_bDescending = FALSE; // Ascending
TableDef.CreateIndex(idx); // Create secondary index
// Done creating the indexes...</FONT></PRE>
<P>There's no need to call Append(), because this is done automatically by MFC's DAO implementation. Of course, in the preceding code, you should make sure that your parameters are set to reflect your database's design.
<BR>
<BR>
<A NAME="E70E71"></A>
<H5 ALIGN=CENTER>
<CENTER>
<FONT SIZE=4 COLOR="#FF0000"><B>Adding Records to a DAO Database</B></FONT></CENTER></H5>
<BR>
<P>To add records to a DAO database, you follow procedures that are very similar to those used with ODBC. To keep this functionality separate from your database creation, you add record addition, deletion, and refresh in the view class instead of in the recordset class. You could place this functionality in either class, but the view class is a better place for record addition, deletion, and refresh.
<BR>
<P>To add this functionality, I've added three new selections to the Record menu: Add, Delete, and Refresh. I also used ClassWizard to add a handler for OnMove(). To make the user interface easier, I also added three buttons to the toolbar to perform these functions. Visual C++ 4 makes adding toolbar buttons easy. It takes more time to design and draw the button bitmaps than it does to actually implement them!
<BR>
<P>After adding the new menu selections, handlers are generated using ClassWizard for each one. As noted earlier, the handlers are added to the view class, keeping them separate from other code used in this sample program. Listing 14.2 shows the view class implementation. Additions and modifications appear in bold.
<BR>
<P>
<FONT COLOR="#000080"><B>Listing 14.2. The view implementation class file.</B></FONT>
<BR>
<PRE>
<FONT COLOR="#000080">// AddressesView.cpp : implementation of the CAddressesView class
//
#include "stdafx.h"
#include "Addresses.h"
#include "AddressesSet.h"
#include "AddressesDoc.h"
#include "AddressesView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAddressesView
IMPLEMENT_DYNCREATE(CAddressesView, CDaoRecordView)
BEGIN_MESSAGE_MAP(CAddressesView, CDaoRecordView)
//{{AFX_MSG_MAP(CAddressesView)
ON_COMMAND(ID_RECORD_ADD, OnRecordAdd)
ON_COMMAND(ID_RECORD_DELETE, OnRecordDelete)
ON_COMMAND(ID_RECORD_REFRESH, OnRecordRefresh)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CDaoRecordView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CDaoRecordView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CDaoRecordView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAddressesView construction/destruction
CAddressesView::CAddressesView()
: CDaoRecordView(CAddressesView::IDD)
{
//{{AFX_DATA_INIT(CAddressesView)
m_pSet = NULL;
//}}AFX_DATA_INIT
// TODO: add construction code here
<B> m_bAddMode = FALSE;</B>
}
CAddressesView::~CAddressesView()
{
}
void CAddressesView::DoDataExchange(CDataExchange* pDX)
{
CDaoRecordView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAddressesView)
DDX_FieldText(pDX, IDC_ADDRESS, m_pSet->m_Address, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_Address, 255);
DDX_FieldText(pDX, IDC_CITY, m_pSet->m_City, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_City, 50);
DDX_FieldText(pDX, IDC_EMAIL, m_pSet->m_EmailAddress, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_EmailAddress, 50);
DDX_FieldText(pDX, IDC_FAX, m_pSet->m_FaxNumber, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_FaxNumber, 30);
DDX_FieldText(pDX, IDC_FIRSTNAME, m_pSet->m_FirstName, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_FirstName, 50);
DDX_FieldText(pDX, IDC_HOMEPHONE, m_pSet->m_HomePhone, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_HomePhone, 30);
DDX_FieldText(pDX, IDC_LASTNAME, m_pSet->m_LastName, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_LastName, 50);
DDX_FieldText(pDX, IDC_NOTES, m_pSet->m_Notes, m_pSet);
DDX_FieldText(pDX, IDC_POSTALCODE, m_pSet->m_PostalCode, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_PostalCode, 20);
DDX_FieldText(pDX, IDC_STATE, m_pSet->m_StateOrProvince, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_StateOrProvince, 20);
DDX_FieldText(pDX, IDC_WORKPHONE, m_pSet->m_WorkPhone, m_pSet);
DDV_MaxChars(pDX, m_pSet->m_WorkPhone, 30);
//}}AFX_DATA_MAP
}
BOOL CAddressesView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CDaoRecordView::PreCreateWindow(cs);
}
void CAddressesView::OnInitialUpdate()
{
m_pSet = &GetDocument()->m_addressesSet;
CDaoRecordView::OnInitialUpdate();
}
/////////////////////////////////////////////////////////////////////////////
// CAddressesView printing
BOOL CAddressesView::OnPreparePrinting(CPrintInfo* pInfo)
{
// Default preparation
return DoPreparePrinting(pInfo);
}
void CAddressesView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: Add extra initialization before printing
}
void CAddressesView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: Add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CAddressesView diagnostics
#ifdef _DEBUG
void CAddressesView::AssertValid() const
{
CDaoRecordView::AssertValid();
}
void CAddressesView::Dump(CDumpContext& dc) const
{
CDaoRecordView::Dump(dc);
}
CAddressesDoc* CAddressesView::GetDocument() // Non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAddressesDoc)));
return (CAddressesDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CAddressesView database support
CDaoRecordset* CAddressesView::OnGetRecordset()
{
return m_pSet;
}
/////////////////////////////////////////////////////////////////////////////
// CAddressesView message handlers
BOOL CAddressesView::OnMove(UINT nIDMoveCommand)
{
// TODO: Add your specialized code here and/or call the base class
<B> // Retrieve the current record set:</B>
<B> CDaoRecordset* pRecordset = OnGetRecordset();</B>
<B> if (m_bAddMode)</B>
<B> {// Do special handling if you are adding records:</B>
<B> if (!UpdateData())</B>
<B> { // Could not get updated data from input dialog:</B>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -