⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcg15.htm

📁 Visual C++与数据库的连接经典实例
💻 HTM
📖 第 1 页 / 共 5 页
字号:

<B>    SetArray();</B>

<B>    // Show results of move operation</B>

<B>    UpdateData(FALSE);</B>

<B>    return(TRUE);</B>

<B>}</B>

<B>void    CContinView::SetArray()</B>

<B>{</B>

<B>int        i;</B>

<B>int        nStepBack;</B>

<B>    nStepBack = 0;</B>

<B>    for (i = 0; i &lt; 10; i++)</B>

<B>    {// Save the current record and then get next one!</B>

<B>        m_EnglishName[i] = m_pSet-&gt;m_English_Name;</B>

<B>        m_ProductName[i] = m_pSet-&gt;m_Product_Name;</B>

<B>        m_UnitPrice[i] = m_pSet-&gt;m_Unit_Price;</B>

<B>        m_UnitsInStock[i] = m_pSet-&gt;m_Units_In_Stock;</B>

<B>        m_UnitsOnOrder[i] = m_pSet-&gt;m_Units_On_Order;</B>

<B>        if (!m_pSet-&gt;IsEOF())</B>

<B>        {</B>

<B>            TRY</B>

<B>            {// Use old-style exceptions for Visual C++ 1.5x</B>

<B>                m_pSet-&gt;MoveNext();</B>

<B>                --nStepBack;</B>

<B>            }</B>

<B>            CATCH(CDBException, e)</B>

<B>            {// Died. Should use message box to user!</B>

<B>                   TRACE(&quot;MoveNext() failed Ret = %d Error '%s', cause '%s'\n&quot;,</B>

<B>                       e-&gt;m_nRetCode,</B>

<B>                       (const char *)e-&gt;m_strError,</B>

<B>                       (const char *)e-&gt;m_strStateNativeOrigin);</B>

<B>            }</B>

<B>            END_CATCH</B>

<B>        }</B>

<B>        else</B>

<B>        {</B>

<B>            m_pSet-&gt;SetFieldNull(NULL);</B>

<B>        }</B>

<B>    }</B>

<B>//    Restore the record pointer! Take nStepBack giant steps back!</B>

<B>    TRY</B>

<B>    {// Use old-style exceptions for Visual C++ 1.5x</B>

<B>        m_pSet-&gt;Move(nStepBack);</B>

<B>    }</B>

<B>    CATCH(CDBException, e)</B>

<B>    {// Died. Should use message box to user!</B>

<B>           TRACE(&quot;Move(nStepBack) failed Ret = %d Error '%s', cause '%s'\n&quot;,</B>

<B>               e-&gt;m_nRetCode,</B>

<B>            (const char *)e-&gt;m_strError,</B>

<B>               (const char *)e-&gt;m_strStateNativeOrigin);</B>

<B>    }</B>

<B>    END_CATCH</B>

<B>    m_ArraySet = TRUE;</B>

<B>}</B>

void CContinView::DoDataExchange(CDataExchange* pDX)

{

<B>    if (!m_ArraySet)</B>

<B>        SetArray();</B>

    CRecordView::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CContinView)

    //}}AFX_DATA_MAP

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME1,   m_EnglishName[0]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME1,   m_ProductName[0]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE1,     m_UnitPrice[0]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK1,  m_UnitsInStock[0]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER1,  m_UnitsOnOrder[0]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME2,   m_EnglishName[1]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME2,   m_ProductName[1]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE2,     m_UnitPrice[1]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK2,  m_UnitsInStock[1]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER2,  m_UnitsOnOrder[1]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME3,   m_EnglishName[2]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME3,   m_ProductName[2]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE3,     m_UnitPrice[2]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK3,  m_UnitsInStock[2]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER3,  m_UnitsOnOrder[2]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME4,   m_EnglishName[3]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME4,   m_ProductName[3]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE4,     m_UnitPrice[3]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK4,  m_UnitsInStock[3]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER4,  m_UnitsOnOrder[3]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME5,   m_EnglishName[4]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME5,   m_ProductName[4]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE5,     m_UnitPrice[4]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK5,  m_UnitsInStock[4]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER5,  m_UnitsOnOrder[4]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME6,   m_EnglishName[5]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME6,   m_ProductName[5]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE6,     m_UnitPrice[5]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK6,  m_UnitsInStock[5]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER6,  m_UnitsOnOrder[5]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME7,   m_EnglishName[6]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME7,   m_ProductName[6]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE7,     m_UnitPrice[6]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK7,  m_UnitsInStock[6]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER7,  m_UnitsOnOrder[6]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME8,   m_EnglishName[7]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME8,   m_ProductName[7]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE8,     m_UnitPrice[7]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK8,  m_UnitsInStock[7]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER8,  m_UnitsOnOrder[7]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME9,   m_EnglishName[8]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME9,   m_ProductName[8]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE9,     m_UnitPrice[8]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK9,  m_UnitsInStock[8]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER9,  m_UnitsOnOrder[8]);</B>

<B>    DDX_Text(pDX,   IDC_ENGLISH_NAME10,  m_EnglishName[9]);</B>

<B>    DDX_Text(pDX,   IDC_PRODUCT_NAME10,  m_ProductName[9]);</B>

<B>    DDX_Text(pDX,     IDC_UNIT_PRICE10,    m_UnitPrice[9]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_IN_STOCK10, m_UnitsInStock[9]);</B>

<B>    DDX_Text(pDX, IDC_UNITS_ON_ORDER10, m_UnitsOnOrder[9]);</B>

}

void CContinView::OnInitialUpdate()

{

    m_pSet = &amp;GetDocument()-&gt;m_continSet;

    CRecordView::OnInitialUpdate();

}

/////////////////////////////////////////////////////////////////////////////

// CContinView printing

BOOL CContinView::OnPreparePrinting(CPrintInfo* pInfo)

{

    // Default preparation

    return DoPreparePrinting(pInfo);

}

void CContinView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

    // TODO: Add extra initialization before printing

}

void CContinView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

    // TODO: Add cleanup after printing

}

/////////////////////////////////////////////////////////////////////////////

// CContinView diagnostics

#ifdef _DEBUG

void CContinView::AssertValid() const

{

    CRecordView::AssertValid();

}

void CContinView::Dump(CDumpContext&amp; dc) const

{

    CRecordView::Dump(dc);

}

CContinDoc* CContinView::GetDocument() // Non-debug version is inline

{

    ASSERT(m_pDocument-&gt;IsKindOf(RUNTIME_CLASS(CContinDoc)));

    return (CContinDoc*)m_pDocument;

}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////

// CContinView database support

CRecordset* CContinView::OnGetRecordset()

{

    return m_pSet;

}

/////////////////////////////////////////////////////////////////////////////

// CContinView message handlers</FONT></PRE>

<BLOCKQUOTE>

<BLOCKQUOTE>

<HR ALIGN=CENTER>

<BR>

<NOTE><B>CAUTION</B>

<BR>

<BR>If you want to use more than one record at a time from the CRecordView class object (which has a CRecordset object contained in it), you must override the default OnMove() CRecordView member function. This function normally isn't overridden, so there is no documentation from Microsoft on how the OnMove() member function actually works.

<BR>

<BR>You can easily overcome this shortcoming in documentation by simply taking a peek at the MFC source code for the OnMove() member function, which is found in the source file DBVIEW.CPP (on the Visual C++ 4 distribution CD in the MSDEV\MFC\SRC folder).</NOTE>

<BR>

<HR ALIGN=CENTER>

</BLOCKQUOTE></BLOCKQUOTE>

<P>To fully emulate Access's continuous subform, you need to add a vertical scroll bar to position the data control's record pointer. Because AppWizard-generated applications have record navigation buttons in their toolbars, it's usually not necessary to have a scroll bar as well. When your database access is part of a dialog box (dialog boxes don't have AppWizard-generated toolbars), you might want to code a scroll bar to let the user easily navigate through the database's records.

<BR>

<P>The problem you encounter when using scroll bars to position the record pointer is that scroll bars use numeric values, but recordsets don't have corresponding record number properties. As mentioned in Chapter 1, &quot;Positioning Visual C++ in the Desktop Database Market,&quot; neither Access 1.x nor Visual C++ offers the equivalent of xBase's RECNO() function to return a record number.

<BR>

<P>You can choose from several approaches in order to create the equivalent of record numbers for recordset objects:

<BR>

<UL>

<LI>Create an array of the data in the recordset object and use the array elements instead of the data in the recordset object to populate the emulated subform. The element number of the array substitutes for the record number. However, you need to update the array each time you edit or add a new record to the recordset object. Conventional 16-bit Visual C++ arrays are limited to 64K (for all practical purposes), so this approach works best with small tables. You can create an array larger than 64K, but you need to have the length of the array elements be a power of 2, which might waste substantial storage space.

<BR>

<BR>With Visual C++ 2.x (or any other version of Visual C++ that creates 32-bit programs, including Visual C++ 4.x), an array isn't limited to 64K, and elements in the array don't need to be a power of 2.

<BR>

<BR>

<LI>Create an array of bookmarks for the recordset. This is a faster process than creating an array of the recordset data, but you still have a 64K limit on the size of the array. An SQL_C_BOOKMARK object is an unsigned long int (4 bytes long), so you could have up to 16,385 bookmark objects in a 64K block of memory. You can easily define a huge array of SQL_C_BOOKMARK objects because sizeof(unsigned long int) is a power of 2.

<BR>

<BR>

<LI>Save the last value of the vertical scroll bar's position and use the MoveNext or MovePrevious methods to position the record pointer incrementally. Set the Min value of the scroll bar to 1 and the Max value to CRecordset::GetRecordCount(). (You must read all records in the recordset to ensure that CRecordset::GetRecordCount() returns the actual number of records in the recordset.) The range of scroll bars is limited to the range of integer variables (+32,767 to &#150;32,768). If you expect your recordset to contain more than 32,000 records, you need to use math to move the record pointer more than one record for each scroll bar Value increment or decrement.

<BR>

<BR>

</UL>

<P>This last approach usually is the simplest and is used in the emulated subform application. Listing 15.3 shows the code for the function that overrides the CRecordView::OnMove() member function. This function started as a direct cut-and-paste of the original CRecordView::OnMove() code that is shown in Listing 15.2.

<BR>

<P>Listing 15.2 has some comments that explain the steps that OnMove() performs when moving from one record to another. These comments appear in bold.

<BR>

<P>

<FONT COLOR="#000080"><B>Listing 15.2. CRecordView::OnMove() original handler.</B></FONT>

<BR>

<PRE>

<FONT COLOR="#000080">// This is a part of the Microsoft Foundation Classes C++ library.

// Copyright  1993 Microsoft Corporation

// All rights reserved.

//

// This source code is intended only as a supplement to the

// Microsoft Foundation Classes Reference and Microsoft

// QuickHelp and/or WinHelp documentation provided with the library.

// See these sources for detailed information regarding the

// Microsoft Foundation Classes product.

#include &quot;stdafx.h&quot;

#ifdef AFX_DB_SEG

#pragma code_seg(AFX_DB_SEG)

#endif

#ifdef _DEBUG

#undef THIS_FILE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -