home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / DAOVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  17.5 KB  |  743 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_DB_SEG
  14. #pragma code_seg(AFX_DB_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25.  
  26. IMPLEMENT_DYNAMIC(CDaoRecordView, CFormView)
  27.  
  28. BEGIN_MESSAGE_MAP(CDaoRecordView, CFormView)
  29.     //{{AFX_MSG_MAP(CDaoRecordView)
  30.         // NOTE - the ClassWizard will add and remove mapping macros here.
  31.     //}}AFX_MSG_MAP
  32.     ON_COMMAND_EX(ID_RECORD_FIRST, OnMove)
  33.     ON_UPDATE_COMMAND_UI(ID_RECORD_FIRST, OnUpdateRecordFirst)
  34.     ON_COMMAND_EX(ID_RECORD_PREV, OnMove)
  35.     ON_UPDATE_COMMAND_UI(ID_RECORD_PREV, OnUpdateRecordPrev)
  36.     ON_COMMAND_EX(ID_RECORD_NEXT, OnMove)
  37.     ON_UPDATE_COMMAND_UI(ID_RECORD_NEXT, OnUpdateRecordNext)
  38.     ON_COMMAND_EX(ID_RECORD_LAST, OnMove)
  39.     ON_UPDATE_COMMAND_UI(ID_RECORD_LAST, OnUpdateRecordLast)
  40. END_MESSAGE_MAP()
  41.  
  42. CDaoRecordView::CDaoRecordView(LPCTSTR lpszTemplateName)
  43.     : CFormView(lpszTemplateName)
  44. {
  45.     m_nStatus = 0;
  46.  
  47.     // Setup dummy bookmarks
  48.     m_varBookmarkCurrent = 1L;
  49.     m_varBookmarkFirst = m_varBookmarkLast = 0L;
  50. }
  51.  
  52. CDaoRecordView::CDaoRecordView(UINT nIDTemplate)
  53.     : CFormView(nIDTemplate)
  54. {
  55.     m_nStatus = 0;
  56.  
  57.     // Setup dummy bookmarks
  58.     m_varBookmarkCurrent = 1L;
  59.     m_varBookmarkFirst = m_varBookmarkLast = 0L;
  60. }
  61.  
  62. CDaoRecordView::~CDaoRecordView()
  63. {
  64. }
  65.  
  66. void CDaoRecordView::OnInitialUpdate()
  67. {
  68.     ASSERT_VALID(this);
  69.  
  70.     CDaoRecordset* pRecordset = OnGetRecordset();
  71.     // recordset must be allocated already
  72.     ASSERT(pRecordset != NULL);
  73.  
  74.     if (!pRecordset->IsOpen())
  75.     {
  76.         CWaitCursor wait;
  77.         pRecordset->Open();
  78.     }
  79.  
  80.     if (!pRecordset->IsEOF())
  81.     {
  82.         // Determine recordset properties for move button enabling
  83.         if (pRecordset->CanBookmark())
  84.         {
  85.             // Get the bookmark of the first record
  86.             m_varBookmarkCurrent = pRecordset->GetBookmark();
  87.             m_varBookmarkFirst = m_varBookmarkCurrent;
  88.         }
  89.  
  90.         // Enable forward scrolling buttons
  91.         m_nStatus |= AFX_DAOVIEW_SCROLL_NEXT;
  92.  
  93.         // Enable backward scrolling buttons if possible
  94.         if (pRecordset->CanScroll())
  95.         {
  96.             m_nStatus |= AFX_DAOVIEW_SCROLL_LAST;
  97.             m_nStatus |= AFX_DAOVIEW_SCROLL_BACKWARD;
  98.         }
  99.         else
  100.         {
  101.             m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  102.             m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  103.         }
  104.     }
  105.     else
  106.     {
  107.         // Disable scrolling
  108.         m_nStatus &= ~AFX_DAOVIEW_SCROLL_NEXT;
  109.         m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  110.         m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  111.     }
  112.  
  113.     CFormView::OnInitialUpdate();
  114. }
  115.  
  116. BOOL CDaoRecordView::OnMove(UINT nIDMoveCommand)
  117. {
  118.     ASSERT_VALID(this);
  119.  
  120.     CDaoRecordset* pSet = OnGetRecordset();
  121.     if (pSet->CanUpdate())
  122.     {
  123.         pSet->Edit();
  124.         if (!UpdateData())
  125.             return TRUE;
  126.  
  127.         if (pSet->IsFieldDirty(NULL))
  128.             pSet->Update();
  129.         else
  130.             pSet->CancelUpdate();
  131.     }
  132.  
  133.     BOOL bBookmarkable = pSet->CanBookmark();
  134.     BOOL bScrollable = pSet->CanScroll();
  135.  
  136.     switch (nIDMoveCommand)
  137.     {
  138.         case ID_RECORD_PREV:
  139.             pSet->MovePrev();
  140.  
  141.             if (!pSet->IsBOF())
  142.             {
  143.                 if (bBookmarkable)
  144.                     m_varBookmarkCurrent = pSet->GetBookmark();
  145.  
  146.                 // Enable forward scrolling
  147.                 m_nStatus |= AFX_DAOVIEW_SCROLL_NEXT;
  148.  
  149.                 if (bScrollable)
  150.                 {
  151.                     m_nStatus |= AFX_DAOVIEW_SCROLL_LAST;
  152.  
  153.                     if (IsOnFirstRecord())
  154.                         // Disable backward scrolling
  155.                         m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  156.                     else
  157.                         m_nStatus |= AFX_DAOVIEW_SCROLL_BACKWARD;
  158.                 }
  159.                 else
  160.                 {
  161.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  162.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  163.                 }
  164.  
  165.  
  166.                 break;
  167.             }
  168.             // Fall through to reset to first record
  169.  
  170.         case ID_RECORD_FIRST:
  171.             pSet->MoveFirst();
  172.  
  173.             // backward scrolling never allowed after movefirst
  174.             m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  175.  
  176.             if (pSet->IsEOF())
  177.             {
  178.                 // Empty recordset, disable forward too
  179.                 m_nStatus &= ~AFX_DAOVIEW_SCROLL_NEXT;
  180.                 m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  181.             }
  182.             else
  183.             {
  184.                 if (bBookmarkable)
  185.                 {
  186.                     m_varBookmarkCurrent = pSet->GetBookmark();
  187.                     m_varBookmarkFirst = m_varBookmarkCurrent;
  188.                 }
  189.  
  190.                 // Enable forward scrolling
  191.                 m_nStatus |= AFX_DAOVIEW_SCROLL_NEXT;
  192.  
  193.                 if (bScrollable)
  194.                     m_nStatus |= AFX_DAOVIEW_SCROLL_LAST;
  195.                 else
  196.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  197.             }
  198.  
  199.             break;
  200.  
  201.         case ID_RECORD_NEXT:
  202.             pSet->MoveNext();
  203.  
  204.             if (!pSet->IsEOF())
  205.             {
  206.                 if (bBookmarkable)
  207.                     m_varBookmarkCurrent = pSet->GetBookmark();
  208.  
  209.                 if (IsOnLastRecord())
  210.                 {
  211.                     // Disable forward scrolling
  212.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_NEXT;
  213.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  214.                 }
  215.                 else
  216.                 {
  217.                     m_nStatus |= AFX_DAOVIEW_SCROLL_NEXT;
  218.                     m_nStatus |= AFX_DAOVIEW_SCROLL_LAST;
  219.                 }
  220.  
  221.                 if (bScrollable)
  222.                     m_nStatus |= AFX_DAOVIEW_SCROLL_BACKWARD;
  223.                 else
  224.                 {
  225.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  226.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  227.                 }
  228.  
  229.                 break;
  230.             }
  231.  
  232.             // Can't fall through to move last
  233.             if (!bScrollable)
  234.             {
  235.                 // At the end of forward only recordset
  236.                 m_nStatus &= ~AFX_DAOVIEW_SCROLL_NEXT;
  237.                 m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  238.                 m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  239.                 break;
  240.             }
  241.  
  242.             // Fall through to reset to last record
  243.  
  244.         case ID_RECORD_LAST:
  245.             pSet->MoveLast();
  246.  
  247.             // forward scrolling never allowed after movelast
  248.             m_nStatus &= ~AFX_DAOVIEW_SCROLL_NEXT;
  249.             m_nStatus &= ~AFX_DAOVIEW_SCROLL_LAST;
  250.  
  251.             if (pSet->IsBOF())
  252.             {
  253.                 // Empty recordset, disable backward too
  254.                 m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  255.             }
  256.             else
  257.             {
  258.                 if (bBookmarkable)
  259.                 {
  260.                     m_varBookmarkCurrent = pSet->GetBookmark();
  261.                     m_varBookmarkLast = m_varBookmarkCurrent;
  262.                 }
  263.  
  264.                 // Enable backward scrolling
  265.                 if (bBookmarkable)
  266.                     m_nStatus |= AFX_DAOVIEW_SCROLL_BACKWARD;
  267.                 else
  268.                     m_nStatus &= ~AFX_DAOVIEW_SCROLL_BACKWARD;
  269.             }
  270.  
  271.             break;
  272.  
  273.         default:
  274.             // Unexpected case value
  275.             ASSERT(FALSE);
  276.     }
  277.  
  278.     // Show results of move operation
  279.     UpdateData(FALSE);
  280.     return TRUE;
  281. }
  282.  
  283. BOOL CDaoRecordView::IsOnFirstRecord()
  284. {
  285.     ASSERT_VALID(this);
  286.     return (m_varBookmarkCurrent == m_varBookmarkFirst);
  287. }
  288.  
  289. BOOL CDaoRecordView::IsOnLastRecord()
  290. {
  291.     ASSERT_VALID(this);
  292.     return (m_varBookmarkCurrent == m_varBookmarkLast);
  293. }
  294.  
  295. /////////////////////////////////////////////////////////////////////////////
  296. // DDX Cover functions for use with fields of a recordset
  297.  
  298. /////////////////////////////////////////////////////////////////////////////
  299. // Simple field formatting to text item
  300.  
  301. BOOL AFXAPI AfxFieldText(CDataExchange* pDX, int nIDC, void* pv,
  302.     CDaoRecordset* pRecordset)
  303. {
  304.     ASSERT_VALID(pRecordset);
  305.  
  306.     HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  307.     TCHAR szT[2];
  308.     if (pDX->m_bSaveAndValidate)
  309.     {
  310.         ::GetWindowText(hWndCtrl, szT, _countof(szT));
  311.         if (szT[0] == '\0')
  312.         {
  313.             // If edit buffer not NULL prior to update, set it dirty
  314.             // to catch case of setting field value from PSEUDO NULL to NULL.
  315.             if (!pRecordset->IsFieldNull(pv))
  316.                 pRecordset->SetFieldDirty(pv, TRUE);
  317.             pRecordset->SetFieldNull(pv);
  318.             return TRUE;
  319.         }
  320.         else
  321.         {
  322.             // If edit buffer NULL prior to update, set it dirty
  323.             // to catch case of setting field value to PSEUDO NULL.
  324.             if (pRecordset->IsFieldNull(pv))
  325.                 pRecordset->SetFieldDirty(pv, TRUE);
  326.             pRecordset->SetFieldNull(pv, FALSE);
  327.         }
  328.     }
  329.     else
  330.     {
  331.         if (!pRecordset->IsOpen() || pRecordset->IsFieldNull(pv))
  332.         {
  333.             szT[0] = '\0';
  334.             AfxSetWindowText(hWndCtrl, szT);
  335.             return TRUE;
  336.         }
  337.     }
  338.     return FALSE;
  339. }
  340.  
  341. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, BOOL& value,
  342.     CDaoRecordset* pRecordset)
  343. {
  344.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  345.         DDX_Text(pDX, nIDC, value);
  346. }
  347.  
  348. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, BYTE& value,
  349.     CDaoRecordset* pRecordset)
  350. {
  351.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  352.         DDX_Text(pDX, nIDC, value);
  353. }
  354.  
  355. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, short& value,
  356.     CDaoRecordset* pRecordset)
  357. {
  358.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  359.         DDX_Text(pDX, nIDC, value);
  360. }
  361.  
  362. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, long& value,
  363.     CDaoRecordset* pRecordset)
  364. {
  365.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  366.         DDX_Text(pDX, nIDC, value);
  367. }
  368.  
  369. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, DWORD& value,
  370.     CDaoRecordset* pRecordset)
  371. {
  372.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  373.         DDX_Text(pDX, nIDC, value);
  374. }
  375.  
  376. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, COleCurrency& value,
  377.     CDaoRecordset* pRecordset)
  378. {
  379.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  380.         DDX_Text(pDX, nIDC, value);
  381. }
  382.  
  383. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, float& value,
  384.     CDaoRecordset* pRecordset)
  385. {
  386.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  387.         DDX_Text(pDX, nIDC, value);
  388. }
  389.  
  390. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, double& value,
  391.     CDaoRecordset* pRecordset)
  392. {
  393.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  394.         DDX_Text(pDX, nIDC, value);
  395. }
  396.  
  397. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, COleDateTime& value,
  398.     CDaoRecordset* pRecordset)
  399. {
  400.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  401.         DDX_Text(pDX, nIDC, value);
  402. }
  403.  
  404. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, CString& value,
  405.     CDaoRecordset* pRecordset)
  406. {
  407.     if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  408.         DDX_Text(pDX, nIDC, value);
  409. }
  410.  
  411. void AFXAPI DDX_FieldLBString(CDataExchange* pDX, int nIDC, CString& value,
  412.     CDaoRecordset* pRecordset)
  413. {
  414.     ASSERT_VALID(pRecordset);
  415.  
  416.     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  417.     if (pDX->m_bSaveAndValidate)
  418.     {
  419.         int nIndex = (int)::SendMessage(hWndCtrl, LB_GETCURSEL, 0, 0L);
  420.         if (nIndex != -1)
  421.         {
  422.             int nLen = (int)::SendMessage(hWndCtrl, LB_GETTEXTLEN, nIndex, 0L);
  423.             ::SendMessage(hWndCtrl, LB_GETTEXT, nIndex,
  424.                     (LPARAM)(LPSTR)value.GetBuffer(nLen));
  425.             if (nLen == 0)
  426.             {
  427.                 if (pRecordset->IsFieldNullable(&value))
  428.                     pRecordset->SetFieldNull(&value, TRUE);
  429.             }
  430.             else
  431.             {
  432.                 pRecordset->SetFieldNull(&value, FALSE);
  433.             }
  434.             value.ReleaseBuffer();
  435.         }
  436.         else
  437.         {
  438.             // no selection
  439.             value.GetBufferSetLength(0);
  440.             if (pRecordset->IsFieldNullable(&value))
  441.                 pRecordset->SetFieldNull(&value);
  442.         }
  443.     }
  444.     else
  445.     {
  446.         if (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value))
  447.         {
  448.             SendMessage(hWndCtrl, LB_SETCURSEL, (WPARAM)-1, 0L);
  449.         }
  450.         else
  451.         {
  452.             // set current selection based on data string
  453.             if (::SendMessage(hWndCtrl, LB_SELECTSTRING, (WPARAM)-1,
  454.               (LPARAM)(LPCTSTR)value) == LB_ERR)
  455.             {
  456.                 // no selection match
  457.                 TRACE0("Warning: no listbox item selected.\n");
  458.             }
  459.         }
  460.     }
  461. }
  462.  
  463. void AFXAPI DDX_FieldLBStringExact(CDataExchange* pDX, int nIDC, CString& value,
  464.     CDaoRecordset* pRecordset)
  465. {
  466.     ASSERT_VALID(pRecordset);
  467.  
  468.     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  469.     if (pDX->m_bSaveAndValidate)
  470.     {
  471.         DDX_FieldLBString(pDX, nIDC, value, pRecordset);
  472.     }
  473.     else
  474.     {
  475.         if (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value))
  476.         {
  477.             SendMessage(hWndCtrl, LB_SETCURSEL, (WPARAM)-1, 0L);
  478.         }
  479.         else
  480.         {
  481.             // set current selection based on data string
  482.             int i = (int)::SendMessage(hWndCtrl, LB_FINDSTRINGEXACT, (WPARAM)-1,
  483.               (LPARAM)(LPCTSTR)value);
  484.             if (i < 0)
  485.             {
  486.                 // no selection match
  487.                 TRACE0("Warning: no listbox item selected.\n");
  488.             }
  489.             else
  490.             {
  491.                 // select it
  492.                 SendMessage(hWndCtrl, LB_SETCURSEL, i, 0L);
  493.             }
  494.         }
  495.     }
  496. }
  497.  
  498. void AFXAPI DDX_FieldCBString(CDataExchange* pDX, int nIDC, CString& value,
  499.     CDaoRecordset* pRecordset)
  500. {
  501.     ASSERT_VALID(pRecordset);
  502.  
  503.     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  504.     if (pDX->m_bSaveAndValidate)
  505.     {
  506.         // just get current edit item text (or drop list static)
  507.         int nLen = ::GetWindowTextLength(hWndCtrl);
  508.         if (nLen != -1)
  509.         {
  510.             // get known length
  511.             ::GetWindowText(hWndCtrl, value.GetBuffer(nLen), nLen+1);
  512.         }
  513.         else
  514.         {
  515.             // for drop lists GetWindowTextLength does not work - assume
  516.             //  preallocated length (or 256, whichever is larger)
  517.             nLen = value.GetAllocLength();
  518.             if (nLen < 256)
  519.                 nLen = 256;
  520.             ::GetWindowText(hWndCtrl, value.GetBuffer(nLen-1), nLen);
  521.         }
  522.         value.ReleaseBuffer();
  523.         if (value.GetLength() == 0)
  524.         {
  525.             if (pRecordset->IsFieldNullable(&value))
  526.                 pRecordset->SetFieldNull(&value, TRUE);
  527.         }
  528.         else
  529.         {
  530.             pRecordset->SetFieldNull(&value, FALSE);
  531.         }
  532.     }
  533.     else
  534.     {
  535.         if (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value))
  536.         {
  537.             SendMessage(hWndCtrl, CB_SETCURSEL, (WPARAM)-1, 0L);
  538.         }
  539.         else
  540.         {
  541.             // set current selection based on model string
  542.             if (::SendMessage(hWndCtrl, CB_SELECTSTRING, (WPARAM)-1,
  543.                 (LPARAM)(LPCTSTR)value) == CB_ERR)
  544.             {
  545.                 // just set the edit text (will be ignored if DROPDOWNLIST)
  546.                 AfxSetWindowText(hWndCtrl, value);
  547.             }
  548.         }
  549.     }
  550. }
  551.  
  552. void AFXAPI DDX_FieldCBStringExact(CDataExchange* pDX, int nIDC, CString& value,
  553.     CDaoRecordset* pRecordset)
  554. {
  555.     ASSERT_VALID(pRecordset);
  556.  
  557.     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  558.     if (pDX->m_bSaveAndValidate)
  559.     {
  560.         DDX_FieldCBString(pDX, nIDC, value, pRecordset);
  561.     }
  562.     else
  563.     {
  564.         if (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value))
  565.         {
  566.             SendMessage(hWndCtrl, CB_SETCURSEL, (WPARAM)-1, 0L);
  567.         }
  568.         else
  569.         {
  570.             // set current selection based on data string
  571.             int i = (int)::SendMessage(hWndCtrl, CB_FINDSTRINGEXACT, (WPARAM)-1,
  572.               (LPARAM)(LPCTSTR)value);
  573.             if (i < 0)
  574.             {
  575.                 // no selection match
  576.                 TRACE0("Warning: no combobox item selected.\n");
  577.             }
  578.             else
  579.             {
  580.                 // select it
  581.                 SendMessage(hWndCtrl, CB_SETCURSEL, i, 0L);
  582.             }
  583.         }
  584.     }
  585. }
  586.  
  587. void AFXAPI DDX_FieldLBIndex(CDataExchange* pDX, int nIDC, int& index,
  588.     CDaoRecordset* pRecordset)
  589. {
  590.     ASSERT_VALID(pRecordset);
  591.  
  592.     if (!pDX->m_bSaveAndValidate &&
  593.         (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&index)))
  594.     {
  595.         int nIndex = 0;
  596.         DDX_LBIndex(pDX, nIDC, nIndex);
  597.     }
  598.     else
  599.         DDX_LBIndex(pDX, nIDC, index);
  600. }
  601.  
  602. void AFXAPI DDX_FieldCBIndex(CDataExchange* pDX, int nIDC, int& index,
  603.     CDaoRecordset* pRecordset)
  604. {
  605.     ASSERT_VALID(pRecordset);
  606.  
  607.     if (!pDX->m_bSaveAndValidate &&
  608.         (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&index)))
  609.     {
  610.         int nIndex = 0;
  611.         DDX_CBIndex(pDX, nIDC, nIndex);
  612.     }
  613.     else
  614.         DDX_CBIndex(pDX, nIDC, index);
  615. }
  616.  
  617. void AFXAPI DDX_FieldScroll(CDataExchange* pDX, int nIDC, int& value,
  618.     CDaoRecordset* pRecordset)
  619. {
  620.     ASSERT_VALID(pRecordset);
  621.  
  622.     if (!pDX->m_bSaveAndValidate &&
  623.         (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value)))
  624.     {
  625.         int nValue = 0;
  626.         DDX_Scroll(pDX, nIDC, nValue);
  627.     }
  628.     else
  629.         DDX_Scroll(pDX, nIDC, value);
  630. }
  631.  
  632. /////////////////////////////////////////////////////////////////////////////
  633. // Data exchange for special controls
  634.  
  635. void AFXAPI DDX_FieldCheck(CDataExchange* pDX, int nIDC, int& value, CDaoRecordset* pRecordset)
  636. {
  637.     ASSERT_VALID(pRecordset);
  638.  
  639.     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  640.     if (pDX->m_bSaveAndValidate)
  641.     {
  642.         value = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L);
  643.         ASSERT(value >= 0 && value <= 2);
  644.         if (value == 2)
  645.         {
  646.             if (pRecordset->IsFieldNullable(&value))
  647.                 pRecordset->SetFieldNull(&value);
  648.             else
  649.             {
  650.                 TRACE0("Warning: can't set field NULL for checkbox value.\n");
  651.                 // Default to unchecked
  652.                 value = 0;
  653.             }
  654.         }
  655.     }
  656.     else
  657.     {
  658.         if (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value))
  659.         {
  660.             int style = ((int)::GetWindowLong(hWndCtrl, GWL_STYLE) & 0xf);
  661.             if ((style == BS_3STATE || style == BS_AUTO3STATE))
  662.                 value = 2;
  663.             else
  664.             {
  665.                 TRACE0("Warning: can't set checkbox value for NULL field.\n");
  666.                 // Default to unchecked
  667.                 value = 0;
  668.             }
  669.         }
  670.         if (value < 0 || value > 2)
  671.         {
  672.             value = 0;      // default to off
  673.             TRACE1("Warning: dialog data checkbox value (%d) out of range.\n",
  674.                 value);
  675.         }
  676.         ::SendMessage(hWndCtrl, BM_SETCHECK, (WPARAM)value, 0L);
  677.     }
  678. }
  679.  
  680. void AFXAPI DDX_FieldRadio(CDataExchange* pDX, int nIDC, int& value,
  681.     CDaoRecordset* pRecordset)
  682. {
  683.     ASSERT_VALID(pRecordset);
  684.  
  685.     if (!pDX->m_bSaveAndValidate &&
  686.         (!pRecordset->IsOpen() || pRecordset->IsFieldNull(&value)))
  687.         value = -1;
  688.     DDX_Radio(pDX, nIDC, value);
  689.     if (pDX->m_bSaveAndValidate)
  690.     {
  691.         if (value == -1 && !pRecordset->IsFieldNullable(&value))
  692.         {
  693.             AfxFailRadio(pDX);
  694.         }
  695.         else
  696.         {
  697.             pRecordset->SetFieldNull(&value, (value == -1));
  698.         }
  699.     }
  700. }
  701.  
  702. /////////////////////////////////////////////////////////////////////////////
  703.  
  704. #ifdef _DEBUG
  705. void CDaoRecordView::AssertValid() const
  706. {
  707.     CFormView::AssertValid();
  708. }
  709.  
  710. void CDaoRecordView::Dump(CDumpContext& dc) const
  711. {
  712.     ASSERT_VALID(this);
  713.  
  714.     CFormView::Dump(dc);
  715.  
  716.     dc << "m_nStatus =" << m_nStatus;
  717.     dc << "m_varBookmarkCurrent =" << m_varBookmarkCurrent;
  718.     dc << "m_varBookmarkFirst =" << m_varBookmarkFirst;
  719.     dc << "m_varBookmarkLast =" << m_varBookmarkLast;
  720.  
  721.     dc << "\n";
  722. }
  723. #endif
  724.  
  725. //////////////////////////////////////////////////////////////////////////////
  726. // Inline function declarations expanded out-of-line
  727.  
  728. #ifndef _AFX_ENABLE_INLINES
  729.  
  730. static char _szAfxDaoInl[] = "afxdao.inl";
  731. #undef THIS_FILE
  732. #define THIS_FILE _szAfxDaoInl
  733. #define _AFXDAOVIEW_INLINE
  734. #include "afxdao.inl"
  735.  
  736. #endif
  737.  
  738. #ifdef AFX_INIT_SEG
  739. #pragma code_seg(AFX_INIT_SEG)
  740. #endif
  741.  
  742. /////////////////////////////////////////////////////////////////////////////
  743.