home *** CD-ROM | disk | FTP | other *** search
/ Mastering MFC Development / MMD.ISO / labs / c13 / lab02 / ex01 / employeeview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-20  |  11.0 KB  |  441 lines

  1. // EmployeeView.cpp : implementation of the CEmployeeView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "Employee.h"
  6.  
  7. #include "EmployeePaySet.h"
  8. #include "EmployeePersonalSet.h"
  9. #include "EmployeeDoc.h"
  10. #include "EmployeeView.h"
  11.  
  12. void DDX_FieldText( CDataExchange * pDX, UINT nID,
  13.         TIMESTAMP_STRUCT & date, CRecordset * pSet )
  14. {
  15.     CString strDate;
  16.     HRESULT hr;
  17.     
  18.     // When saving, we need to build a TIMESTAMP_STRUCT from a CString
  19.     if ( pDX->m_bSaveAndValidate )
  20.     {
  21.         pDX->PrepareEditCtrl( nID );
  22.         pDX->m_pDlgWnd->GetDlgItem( nID )->
  23.             GetWindowText( strDate );
  24.  
  25. // BEGIN lab
  26.         _bstr_t bst = strDate.AllocSysString();
  27.         memset(&date, 0, sizeof(date));        // set it all to 0
  28.         try {
  29.             ImdyPtr pMDY = ImdyPtr(CLSID_mdy);
  30.             hr = pMDY->MDYfromBSTR (bst, (short *)&date.month, 
  31.                 (short *)&date.day, &date.year);
  32.         }
  33.         catch (_com_error &ex)
  34.         {
  35.             _bstr_t bstrSource(ex.Source());
  36.             _bstr_t bstrDescription(ex.Description());
  37.             char szTemp[1024];
  38.             CString csMsg = "Oops - hit an error!\n";
  39.             wsprintf(szTemp, "Code = %08lx\n", ex.Error());
  40.             csMsg += szTemp;
  41.             wsprintf(szTemp, "Code meaning = %s\n", ex.ErrorMessage());
  42.             csMsg += szTemp;
  43.             wsprintf(szTemp, "Source = %S\n", (wchar_t*)bstrSource);
  44.             csMsg += szTemp;
  45.             wsprintf(szTemp, "Description = %S\n", (wchar_t*)bstrDescription);
  46.             csMsg += szTemp;
  47.             AfxMessageBox (csMsg);
  48.             SysFreeString(bstrSource);
  49.             SysFreeString(bstrDescription);
  50.         }
  51.         
  52.         if (S_OK == hr)            // if OK, get out of here
  53.             return;
  54.         AfxMessageBox( "Use date format:\nm/d/yyyy",
  55.                         MB_OK | MB_ICONEXCLAMATION );
  56.         pDX->Fail( );    //Put focus back to field
  57. // END lab
  58.  
  59.     }
  60.     else
  61.     {
  62.         if ( 12 < date.month &&  31 < date.day )    //Uninitialized date
  63.             strDate = "";
  64.         else
  65.             strDate.Format( "%u/%u/%u",
  66.                 date.month, date.day, date.year );
  67.         pDX->m_pDlgWnd->GetDlgItem( nID )->
  68.             SetWindowText( strDate );
  69.     }
  70. }
  71.  
  72. void DDV_Date( CDataExchange * pDX, TIMESTAMP_STRUCT & date,
  73.               CRecordset * pSet )
  74. {
  75.     if ( ! pDX->m_bSaveAndValidate )
  76.         return;
  77.  
  78.     HRESULT hr;
  79.     
  80. // BEGIN lab
  81.     CString strError('x', 255);
  82.     BSTR bstrError = strError.AllocSysString();
  83.  
  84.     try {
  85.         ImdyPtr pMDY = ImdyPtr(CLSID_mdy);
  86.         hr = pMDY->ValidateMDY (&bstrError, date.month, date.day, 
  87.                                 date.year);
  88.     }
  89.  
  90.     catch (_com_error &ex)
  91.     {
  92.         _bstr_t bstrSource(ex.Source());
  93.         _bstr_t bstrDescription(ex.Description());
  94.         char szTemp[1024];
  95.         CString csMsg = "Oops - hit an error!\n";
  96.         wsprintf(szTemp, "Code = %08lx\n", ex.Error());
  97.         csMsg += szTemp;
  98.         wsprintf(szTemp, "Code meaning = %s\n", ex.ErrorMessage());
  99.         csMsg += szTemp;
  100.         wsprintf(szTemp, "Source = %S\n", (wchar_t*)bstrSource);
  101.         csMsg += szTemp;
  102.         wsprintf(szTemp, "Description = %S\n", (wchar_t*)bstrDescription);
  103.         csMsg += szTemp;
  104.         AfxMessageBox (csMsg);
  105.         SysFreeString(bstrSource);
  106.         SysFreeString(bstrDescription);
  107.     }
  108.  
  109.     if (S_OK == hr)
  110.     {
  111.         ::SysFreeString(bstrError);
  112.         return;
  113.     }
  114.     
  115.     _bstr_t bst(bstrError, false);
  116.     AfxMessageBox( (char *) bst, MB_OK | MB_ICONEXCLAMATION );
  117.     pDX->Fail( );
  118.     
  119.     ::SysFreeString(bstrError);
  120. // END lab
  121. }
  122.  
  123. #ifdef _DEBUG
  124. #define new DEBUG_NEW
  125. #undef THIS_FILE
  126. static char THIS_FILE[] = __FILE__;
  127. #endif
  128.  
  129. /////////////////////////////////////////////////////////////////////////////
  130. // CEmployeeView
  131.  
  132.  
  133. IMPLEMENT_DYNCREATE(CEmployeeView, CRecordView)
  134.  
  135. BEGIN_MESSAGE_MAP(CEmployeeView, CRecordView)
  136.     //{{AFX_MSG_MAP(CEmployeeView)
  137.     ON_COMMAND(ID_RECORD_ADD, OnRecordAdd)
  138.     ON_COMMAND(ID_RECORD_CLEAR, OnRecordClear)
  139.     ON_COMMAND(ID_RECORD_DELETE, OnRecordDelete)
  140.     ON_UPDATE_COMMAND_UI(ID_RECORD_ADD, OnUpdateRecordAdd)
  141.     ON_UPDATE_COMMAND_UI(ID_RECORD_DELETE, OnUpdateRecordDelete)
  142.     //}}AFX_MSG_MAP
  143. END_MESSAGE_MAP()
  144.  
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CEmployeeView construction/destruction
  147.  
  148. CEmployeeView::CEmployeeView()
  149.     : CRecordView(CEmployeeView::IDD)
  150. {
  151.     //{{AFX_DATA_INIT(CEmployeeView)
  152.     m_pSet = NULL;
  153.     m_pEmplInfoSet = NULL;
  154.     //}}AFX_DATA_INIT
  155.     // TODO: add construction code here
  156. }
  157.  
  158. CEmployeeView::~CEmployeeView()
  159. {
  160. }
  161.  
  162. void CEmployeeView::DoDataExchange(CDataExchange* pDX)
  163. {
  164.     CRecordView::DoDataExchange(pDX);
  165.     //{{AFX_DATA_MAP(CEmployeeView)
  166.     DDX_FieldText(pDX, IDC_FNAME, m_pSet->m_First_Name, m_pSet);
  167.     DDX_FieldText(pDX, IDC_LNAME, m_pSet->m_Last_Name, m_pSet);
  168.     DDX_FieldText(pDX, IDC_EMP_NO, m_pSet->m_Employee_Number, m_pSet);
  169.     DDX_FieldText(pDX, IDC_DEPT, m_pSet->m_Department__, m_pSet);
  170.     DDX_FieldText(pDX, IDC_PAY_TYPE, m_pSet->m_Employee_Pay_Type, m_pSet);
  171.     DDX_FieldText(pDX, IDC_HOUR_RATE, m_pSet->m_Hourly_Rate, m_pSet);
  172.     //}}AFX_DATA_MAP
  173.     
  174.     //Ensure pointer is valid
  175.     if ( NULL != m_pEmplInfoSet )
  176.     {
  177.         DDX_FieldText(pDX, IDC_BIRTH, m_pEmplInfoSet->m_Birthdate, m_pEmplInfoSet);
  178.         DDV_Date( pDX, m_pEmplInfoSet->m_Birthdate, m_pEmplInfoSet );
  179.         DDX_FieldText(pDX, IDC_MARITAL_STATUS, m_pEmplInfoSet->m_Sex___Marital_Status, m_pEmplInfoSet);
  180.         DDX_FieldText(pDX, IDC_HEIGHT, m_pEmplInfoSet->m_Height, m_pEmplInfoSet);
  181.         DDX_FieldText(pDX, IDC_WEIGHT, m_pEmplInfoSet->m_Weight, m_pEmplInfoSet);
  182.     }
  183. }
  184.  
  185. BOOL CEmployeeView::PreCreateWindow(CREATESTRUCT& cs)
  186. {
  187.     // TODO: Modify the Window class or styles here by modifying
  188.     //  the CREATESTRUCT cs
  189.  
  190.     return CRecordView::PreCreateWindow(cs);
  191. }
  192.  
  193. void CEmployeeView::OnInitialUpdate()
  194. {
  195.     m_pSet = GetDocument( )->GetEmployeePaySet( );
  196.     m_pEmplInfoSet = GetDocument( )->GetEmployeeInfoSet( );
  197.  
  198.     GetParentFrame( )->RecalcLayout( );
  199.     ResizeParentToFit( FALSE );
  200.  
  201.     try
  202.     {
  203.         //Open the primary table
  204.         m_pSet->Open( );    
  205.         m_pEmplInfoSet->m_EmployeeNumberParam 
  206.             = m_pSet->m_Employee_Number;    //Set join param
  207.         //Open foreign table
  208.         m_pEmplInfoSet->Open( );    
  209.     }
  210.     catch( CException * pEx )
  211.     {
  212.         pEx->ReportError( );
  213.         pEx->Delete( );
  214.         return;
  215.     }
  216.  
  217.     UpdateData( FALSE );
  218.     SetAddMode( FALSE );
  219.  
  220.     CRecordView::OnInitialUpdate( );
  221. }
  222.  
  223. /////////////////////////////////////////////////////////////////////////////
  224. // CEmployeeView diagnostics
  225.  
  226. #ifdef _DEBUG
  227. void CEmployeeView::AssertValid() const
  228. {
  229.     CRecordView::AssertValid();
  230. }
  231.  
  232. void CEmployeeView::Dump(CDumpContext& dc) const
  233. {
  234.     CRecordView::Dump(dc);
  235. }
  236.  
  237. CEmployeeDoc* CEmployeeView::GetDocument() // non-debug version is inline
  238. {
  239.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEmployeeDoc)));
  240.     return (CEmployeeDoc*)m_pDocument;
  241. }
  242. #endif //_DEBUG
  243.  
  244. /////////////////////////////////////////////////////////////////////////////
  245. // CEmployeeView database support
  246. CRecordset* CEmployeeView::OnGetRecordset()
  247. {
  248.     return m_pSet;
  249. }
  250.  
  251. /////////////////////////////////////////////////////////////////////////////
  252. // CEmployeeView message handlers
  253.  
  254. BOOL CEmployeeView::OnMove(UINT nIDMoveCommand) 
  255. {
  256.     if ( IsAddMode( ) )
  257.         AddRecordCancel( );
  258.     if ( ! UpdateData( TRUE ) )
  259.         return FALSE;    //Bad data: We don't want to move
  260.     m_pSet->SetFieldDirty( NULL );    //Otherwise DB update won't occur
  261.     
  262.     BOOL bMove = CRecordView::OnMove(nIDMoveCommand);    //Primary table updated
  263.  
  264.     if ( bMove )    //If successful update the foreign info
  265.     {
  266.         m_pEmplInfoSet->Edit( );                //Turn on edit mode
  267.         m_pEmplInfoSet->SetFieldDirty( NULL );    //Mark the fields dirty
  268.         m_pEmplInfoSet->Update( );
  269.         m_pEmplInfoSet->m_EmployeeNumberParam = 
  270.             m_pSet->m_Employee_Number;
  271.         m_pEmplInfoSet->Requery( );        //Find foreign record
  272.         UpdateData( FALSE );            //Display foreign record
  273.     }
  274.     return bMove;
  275. }
  276.  
  277. void CEmployeeView::OnRecordAdd() 
  278. {
  279.     CDatabase * pDB = m_pSet->m_pDatabase;
  280.     BOOL bTrans = pDB->CanTransact( );
  281.     if ( UpdateData( TRUE ) )    //Scrape the screen data into memory
  282.         try
  283.         {
  284.             m_pEmplInfoSet->m_Employee_Number = 
  285.                 m_pSet->m_Employee_Number;    //Update the foreign table emp num
  286.             m_pSet->Update( );
  287.             m_pEmplInfoSet->Update( );
  288.             if ( bTrans )
  289.             {
  290.                 BOOL bCommitOk = pDB->CommitTrans( );
  291.                 if ( ! bCommitOk ||
  292.                         SQL_CB_PRESERVE != pDB->GetCursorCommitBehavior( ) ) //See TN068
  293.                 {
  294.                     m_pSet->Close( );
  295.                     m_pEmplInfoSet->Close( );
  296.                     m_pSet->Open( );
  297.                     m_pEmplInfoSet->Open( );
  298.                 }
  299.             }
  300.             SetAddMode( FALSE );
  301.             OnRecordClear( );    //Set up to add the next record
  302.         }    //End try
  303.     catch ( CDBException * pEx )
  304.     {
  305.         pEx->ReportError( );
  306.         pEx->Delete( );
  307.         if ( bTrans )
  308.         {
  309.             pDB->Rollback( );
  310.             
  311.             m_pSet->Close( );    //Assume worst case
  312.             m_pEmplInfoSet->Close( );
  313.             
  314.             pDB->BeginTrans( );    //Start trans, again
  315.             m_pSet->Open( );
  316.             m_pEmplInfoSet->Open( );
  317.             
  318.             m_pSet->AddNew( );
  319.             m_pEmplInfoSet->AddNew( );
  320.         }    //End if bTrans
  321.     }    //End catch
  322. }
  323.  
  324. void CEmployeeView::OnRecordClear( ) 
  325. {
  326.     CDatabase * pDB = m_pSet->m_pDatabase;
  327.     //Cannot transact across multiple databases
  328.     ASSERT ( m_pEmplInfoSet->m_pDatabase == pDB );
  329.     
  330.     if ( IsAddMode( ) )
  331.     {
  332.         m_pSet->CancelUpdate( );
  333.         m_pEmplInfoSet->CancelUpdate( );
  334.     }
  335.     else if ( pDB->CanTransact( ) )
  336.     {
  337.         if ( SQL_CB_PRESERVE == pDB->GetCursorCommitBehavior( ) ) //See TN068
  338.             pDB->BeginTrans( );
  339.         else    //Cannot have an open recordset to start transaction
  340.         {
  341.             m_pSet->Close( );
  342.             m_pEmplInfoSet->Close( );
  343.             pDB->BeginTrans( );
  344.             m_pSet->Open( );
  345.             m_pEmplInfoSet->Open( );
  346.         }
  347.     }    //End can transact
  348.     m_pSet->AddNew( );
  349.     m_pEmplInfoSet->AddNew( );
  350.     SetAddMode( );
  351.     UpdateData( FALSE );
  352. }
  353.  
  354. void CEmployeeView::OnRecordDelete() 
  355. {
  356.     CDatabase * pDB = m_pSet->m_pDatabase;
  357.     BOOL bTrans = 
  358.         m_pSet->CanTransact( );
  359.     if ( bTrans  )
  360.         pDB->BeginTrans( );
  361.     try
  362.     {
  363.         m_pEmplInfoSet->Delete( );
  364.         m_pSet->Delete( );
  365.         if ( bTrans )
  366.             pDB->CommitTrans( );
  367.     }
  368.     catch( CDBException * pEx )
  369.     {
  370.         pEx->ReportError( );
  371.         pEx->Delete( );
  372.         if ( bTrans )
  373.             pDB->Rollback( );
  374.     }    //End catch
  375.  
  376.     m_pSet->Close( );    //Assume minimal ODBC support
  377.     m_pEmplInfoSet->Close( );
  378.     m_pSet->Open( );
  379.     m_pEmplInfoSet->Open( );
  380.  
  381.     m_pSet->Requery( );    //Get a record
  382.     m_pEmplInfoSet->m_EmployeeNumberParam = m_pSet->m_Employee_Number;
  383.     m_pEmplInfoSet->Requery( );    //Get related data
  384.     UpdateData( FALSE );    //Show the data
  385. }
  386.  
  387. void CEmployeeView::OnUpdateRecordAdd(CCmdUI* pCmdUI) 
  388. {
  389.     pCmdUI->Enable( IsAddMode( ) ); 
  390. }
  391.  
  392. void CEmployeeView::OnUpdateRecordDelete(CCmdUI* pCmdUI) 
  393. {
  394.     pCmdUI->Enable( ! IsAddMode( ) );    
  395. }
  396.  
  397. void CEmployeeView::SetAddMode( BOOL bAddMode)
  398. {
  399.     m_bAddMode = bAddMode;
  400.     CEdit * pField = ( CEdit * ) GetDlgItem( IDC_EMP_NO );
  401.     pField->SetReadOnly( ! bAddMode );
  402.     if ( bAddMode )
  403.     {
  404.         pField = ( CEdit * ) GetDlgItem( IDC_FNAME );
  405.         pField->SetFocus( );
  406.     }
  407. }
  408.  
  409. BOOL CEmployeeView::IsAddMode()
  410. {
  411.     return m_bAddMode;
  412. }
  413.  
  414. void CEmployeeView::AddRecordCancel()
  415. {
  416.     if ( ! IsAddMode( ) )
  417.         return;
  418.     SetAddMode( FALSE );
  419.     m_pSet->CancelUpdate( );
  420.     m_pEmplInfoSet->CancelUpdate( );
  421.  
  422.     CDatabase * pDB = m_pSet->m_pDatabase;
  423.     if ( pDB->CanTransact( ) )
  424.     {
  425.         pDB->Rollback( );
  426.         if ( SQL_CB_DELETE == pDB->GetCursorRollbackBehavior( ) )
  427.         {
  428.             m_pSet->Close( );
  429.             m_pEmplInfoSet->Close( );
  430.             m_pSet->Open( );
  431.             m_pEmplInfoSet->Open( );
  432.         }
  433.         m_pSet->Requery( );
  434.         m_pEmplInfoSet->m_EmployeeNumberParam =
  435.             m_pSet->m_Employee_Number;
  436.         m_pEmplInfoSet->Requery( );
  437.     }
  438.     UpdateData( FALSE );
  439. }
  440.  
  441.