home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / database / daoctl / daocndlg.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  13KB  |  540 lines

  1. // DAOCnDlg.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "DAOCont.h"
  15. #include "DAOCnDlg.h"
  16.  
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. // variant handling
  24. #ifndef _UNICODE
  25.     #define V_BSTRT(b)  (LPSTR)V_BSTR(b)
  26. #else
  27.     #define V_BSTRT(b)  V_BSTR(b)
  28. #endif
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CAboutDlg dialog used for App About
  32.  
  33. class CAboutDlg : public CDialog
  34. {
  35. public:
  36.     CAboutDlg();
  37.  
  38. // Dialog Data
  39.     //{{AFX_DATA(CAboutDlg)
  40.     enum { IDD = IDD_ABOUTBOX };
  41.     //}}AFX_DATA
  42.  
  43.     // ClassWizard generated virtual function overrides
  44.     //{{AFX_VIRTUAL(CAboutDlg)
  45.     protected:
  46.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  47.     //}}AFX_VIRTUAL
  48.  
  49. // Implementation
  50. protected:
  51.     //{{AFX_MSG(CAboutDlg)
  52.     //}}AFX_MSG
  53.     DECLARE_MESSAGE_MAP()
  54. };
  55.  
  56. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  57. {
  58.     //{{AFX_DATA_INIT(CAboutDlg)
  59.     //}}AFX_DATA_INIT
  60. }
  61.  
  62. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  63. {
  64.     CDialog::DoDataExchange(pDX);
  65.     //{{AFX_DATA_MAP(CAboutDlg)
  66.     //}}AFX_DATA_MAP
  67. }
  68.  
  69. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  70.     //{{AFX_MSG_MAP(CAboutDlg)
  71.         // No message handlers
  72.     //}}AFX_MSG_MAP
  73. END_MESSAGE_MAP()
  74.  
  75. /////////////////////////////////////////////////////////////////////////////
  76. // CDAOContDlg dialog
  77.  
  78. CDAOContDlg::CDAOContDlg(CWnd* pParent /*=NULL*/)
  79.     : CDialog(CDAOContDlg::IDD, pParent)
  80. {
  81.     //{{AFX_DATA_INIT(CDAOContDlg)
  82.     m_bAllowEdits = FALSE;
  83.     //}}AFX_DATA_INIT
  84.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  85.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  86.  
  87.     m_pDB = NULL;
  88.     m_pRS = NULL;
  89.     m_bAllowEdits = TRUE;
  90. }
  91.  
  92. CDAOContDlg::~CDAOContDlg()
  93. {
  94.     if (m_pRS)
  95.         if (m_pRS->IsOpen())
  96.             m_pRS->Close();
  97.     delete m_pRS;
  98.  
  99.     if (m_pDB)
  100.         if (m_pDB->IsOpen())
  101.             m_pDB->Close();
  102.  
  103.     delete m_pDB;
  104. }
  105.  
  106. void CDAOContDlg::DoDataExchange(CDataExchange* pDX)
  107. {
  108.     CDialog::DoDataExchange(pDX);
  109.     //{{AFX_DATA_MAP(CDAOContDlg)
  110.     DDX_Control(pDX, IDC_RECNUM, m_ctlRecNum);
  111.     DDX_Control(pDX, IDC_SPIN1, m_ctlSpin);
  112.     DDX_Control(pDX, IDC_TREE1, m_ctlTree);
  113.     DDX_Control(pDX, IDC_ACCESSPICTCTRL1, m_ctlPicture);
  114.     DDX_Check(pDX, IDC_ALLOW_EDITS, m_bAllowEdits);
  115.     //}}AFX_DATA_MAP
  116.     for (int i=0; i<4; i++)
  117.         DDX_Control(pDX, IDC_COLNAME1 + i, m_ctlColName[i]);
  118.     for (i=0; i<4; i++)
  119.         DDX_Control(pDX, IDC_DAOEDITCTRL1 + i, m_ctlEdit[i]);
  120. }
  121.  
  122. BEGIN_MESSAGE_MAP(CDAOContDlg, CDialog)
  123.     //{{AFX_MSG_MAP(CDAOContDlg)
  124.     ON_WM_SYSCOMMAND()
  125.     ON_WM_PAINT()
  126.     ON_WM_QUERYDRAGICON()
  127.     ON_BN_CLICKED(IDC_CONNECT_DAO, OnConnectDao)
  128.     ON_BN_CLICKED(IDC_CONNECT_ODBC, OnConnectOdbc)
  129.     ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnDblclkTree1)
  130.     ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN1, OnDeltaposSpin1)
  131.     //}}AFX_MSG_MAP
  132. END_MESSAGE_MAP()
  133.  
  134. /////////////////////////////////////////////////////////////////////////////
  135. // CDAOContDlg message handlers
  136.  
  137. BOOL CDAOContDlg::OnInitDialog()
  138. {
  139.     CDialog::OnInitDialog();
  140.  
  141.     // Add "About..." menu item to system menu.
  142.  
  143.     // IDM_ABOUTBOX must be in the system command range.
  144.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  145.     ASSERT(IDM_ABOUTBOX < 0xF000);
  146.  
  147.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  148.     CString strAboutMenu;
  149.     strAboutMenu.LoadString(IDS_ABOUTBOX);
  150.     if (!strAboutMenu.IsEmpty())
  151.     {
  152.         pSysMenu->AppendMenu(MF_SEPARATOR);
  153.         pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  154.     }
  155.  
  156.     // Set the icon for this dialog.  The framework does this automatically
  157.     //  when the application's main window is not a dialog
  158.     SetIcon(m_hIcon, TRUE);         // Set big icon
  159.     SetIcon(m_hIcon, FALSE);        // Set small icon
  160.  
  161.     // Create the Image List
  162.     m_ctlImage.Create(IDB_TREEIMAGE,16,0,RGB(255,0,255));
  163.     m_ctlImage.SetBkColor(GetSysColor(COLOR_WINDOW));
  164.  
  165.     /// Attach image list to Tree
  166.     m_ctlTree.SetImageList(&m_ctlImage);
  167.  
  168.     m_pDB = new CDaoDatabase;
  169.     m_pRS = new CDaoRecordset(m_pDB);
  170.  
  171.     m_ctlTree.ModifyStyle(0,TVS_HASLINES | TVS_HASBUTTONS,0);
  172.     m_ctlTree.GetRootItem().AddTail(_T("No Database loaded!"));
  173.  
  174.     m_ctlSpin.SetRange(0,2);
  175.     m_ctlSpin.SetPos(1);
  176.     m_bUpdating = FALSE;
  177.  
  178.     Clear();
  179.  
  180.     return TRUE;  // return TRUE  unless you set the focus to a control
  181. }
  182.  
  183. void CDAOContDlg::OnSysCommand(UINT nID, LPARAM lParam)
  184. {
  185.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  186.     {
  187.         CAboutDlg dlgAbout;
  188.         dlgAbout.DoModal();
  189.     }
  190.     else
  191.     {
  192.         CDialog::OnSysCommand(nID, lParam);
  193.     }
  194. }
  195.  
  196. // If you add a minimize button to your dialog, you will need the code below
  197. //  to draw the icon.  For MFC applications using the document/view model,
  198. //  this is automatically done for you by the framework.
  199.  
  200. void CDAOContDlg::OnPaint()
  201. {
  202.     if (IsIconic())
  203.     {
  204.         CPaintDC dc(this); // device context for painting
  205.  
  206.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  207.  
  208.         // Center icon in client rectangle
  209.         int cxIcon = GetSystemMetrics(SM_CXICON);
  210.         int cyIcon = GetSystemMetrics(SM_CYICON);
  211.         CRect rect;
  212.         GetClientRect(&rect);
  213.         int x = (rect.Width() - cxIcon + 1) / 2;
  214.         int y = (rect.Height() - cyIcon + 1) / 2;
  215.  
  216.         // Draw the icon
  217.         dc.DrawIcon(x, y, m_hIcon);
  218.     }
  219.     else
  220.     {
  221.         CDialog::OnPaint();
  222.     }
  223. }
  224.  
  225. // The system calls this to obtain the m_cursor to display while the user drags
  226. //  the minimized window.
  227. HCURSOR CDAOContDlg::OnQueryDragIcon()
  228. {
  229.     return (HCURSOR) m_hIcon;
  230. }
  231.  
  232. void CDAOContDlg::OnConnectDao()
  233. {
  234.     m_bODBC = FALSE;
  235.  
  236.     CFileDialog dlgFile(
  237.         TRUE,
  238.         _T(".mdb"),
  239.         NULL,
  240.         OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  241.         _T("Access Files (*.mdb)|*.mdb|All Files (*.*)|*.*||"));
  242.     if (dlgFile.DoModal() != IDOK)
  243.         return;
  244.  
  245.     m_ctlTree.DeleteAllItems();
  246.     m_ctlTree.GetRootItem().AddTail(_T("No Database loaded!"));
  247.  
  248.     CWaitCursor wait;
  249.     UpdateWindow();
  250.  
  251.     if (m_pDB->IsOpen())
  252.         m_pDB->Close();
  253.  
  254.     try
  255.     {
  256.         m_pDB->Open(dlgFile.GetFileName());
  257.     }
  258.     catch (CDaoException* e)
  259.     {
  260.         AfxMessageBox(e->m_pErrorInfo->m_strDescription);
  261.         e->Delete();
  262.     }
  263.     if (m_pDB->IsOpen())
  264.         PopulateTree();
  265. }
  266.  
  267.  
  268. void CDAOContDlg::OnConnectOdbc()
  269. {
  270.     m_bODBC = TRUE;
  271.  
  272.     m_ctlTree.DeleteAllItems();
  273.     m_ctlTree.GetRootItem().AddTail(_T("No Database loaded!"));
  274.  
  275.     if (m_pDB->IsOpen())
  276.         m_pDB->Close();
  277.  
  278.     CWaitCursor wait;
  279.     UpdateWindow();
  280.  
  281.     try
  282.     {
  283.         m_pDB->Open(_T(""),FALSE,FALSE,_T("ODBC;"));
  284.     }
  285.     catch (CDaoException* e)
  286.     {
  287.         AfxMessageBox(e->m_pErrorInfo->m_strDescription);
  288.         e->Delete();
  289.     }
  290.     if (m_pDB->IsOpen())
  291.         PopulateTree();
  292. }
  293.  
  294. void CDAOContDlg::PopulateTree()
  295. {
  296.     m_ctlTree.DeleteAllItems();
  297.  
  298.     ASSERT(m_pDB);
  299.     ASSERT(m_pDB->IsOpen());
  300.  
  301.     // Insert root node by call to tree object this time
  302.     m_cursDB = m_ctlTree.GetRootItem().AddTail(m_pDB->GetName(),IID_DATABASE);
  303.  
  304.     // From now on call via iterators
  305.     m_cursTDS = m_cursDB.AddTail(_T("Tables"),IID_TABLES);
  306.  
  307.     CDaoTableDefInfo tabInfo;
  308.     CDaoFieldInfo fieldInfo;
  309.     int nTableDefCount = m_pDB->GetTableDefCount();
  310.     for (int i = 0; i < nTableDefCount; i++)
  311.     {
  312.         m_pDB->GetTableDefInfo(i,tabInfo);
  313.         if (tabInfo.m_lAttributes & dbSystemObject)
  314.             continue;
  315.         AddItem(IID_TABLE,tabInfo.m_strName);
  316.     }
  317.  
  318.     m_cursDB.Expand();
  319. }
  320.  
  321. void CDAOContDlg::AddItem(WORD nItemType, LPCTSTR lpszName)
  322. {
  323.     switch (nItemType)
  324.     {
  325.         case IID_TABLE:
  326.         {
  327.             m_cursTD = m_cursTDS.AddTail(lpszName,IID_TABLE);
  328.             CDaoTableDef td(m_pDB);
  329.             try
  330.             {
  331.                 td.Open(lpszName);
  332.                 CDaoFieldInfo fieldInfo;
  333.                 int nFieldCount = td.GetFieldCount();
  334.                 for (int j=0; j < nFieldCount; j++)
  335.                 {
  336.                     td.GetFieldInfo(j,fieldInfo);
  337.                     int nImageID;
  338.                     switch (fieldInfo.m_nType){
  339.                         case dbLongBinary:
  340.                             nImageID = IID_PICTURE; break;
  341.                         case dbText:
  342.                         case dbMemo:
  343.                             nImageID = IID_GOODFIELD; break;
  344.                         default:
  345.                             nImageID = IID_BADFIELD;
  346.                     }
  347.                     m_cursTD.AddTail(fieldInfo.m_strName, nImageID);
  348.                 }
  349.             }
  350.             catch(CDaoException* e)
  351.             {
  352.                 e->Delete();
  353.             }
  354.             td.Close();
  355.             break;
  356.         }
  357.     }
  358. }
  359.  
  360. void CDAOContDlg::OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult)
  361. {
  362.     CTreeCursor cursSel = m_ctlTree.GetSelectedItem();
  363.     UINT nImageID = cursSel.GetImageID();
  364.  
  365.     CString strTableName;
  366.     strTableName = cursSel.GetParent().GetText();
  367.     switch (nImageID)
  368.     {
  369.         case IID_GOODFIELD:
  370.             SetRecordset(strTableName);
  371.             m_ctlEdit[m_nEditIndex].SetFieldName(cursSel.GetText());
  372.             m_ctlColName[m_nEditIndex].SetWindowText(cursSel.GetText());
  373.             m_nEditIndex = (m_nEditIndex + 1) % 4;
  374.             UpdateFields();
  375.             break;
  376.         case IID_PICTURE:
  377.             SetRecordset(strTableName);
  378.             m_strPictCol = cursSel.GetText();
  379.             UpdateFields();
  380.             break;
  381.         case IID_BADFIELD:
  382.             AfxMessageBox(_T("Field type not supported"));
  383.             break;
  384.     }
  385.     *pResult = 0;
  386. }
  387.  
  388. void CDAOContDlg::SetRecordset(LPCTSTR strTableName)
  389. {
  390.     if (strTableName == m_strTableName)
  391.         return;
  392.  
  393.     Clear();
  394.  
  395.     try
  396.     {
  397.         CString strQuery = _T("Select * from ");
  398.         strQuery += strTableName;
  399.         m_pRS->Open(dbOpenDynaset,strQuery);
  400.         m_pRS->m_bCheckCacheForDirtyFields = FALSE;
  401.     }
  402.     catch(CDaoException* e)
  403.     {
  404.         AfxMessageBox(e->m_pErrorInfo->m_strDescription);
  405.         e->Delete();
  406.     }
  407.  
  408.     m_strTableName = strTableName;
  409. }
  410.  
  411. void CDAOContDlg::Clear()
  412. {
  413.     if (m_pRS->IsOpen())
  414.         m_pRS->Close();
  415.     for (int i=0; i<4; i++){
  416.         m_ctlEdit[i].SetText(_T(""));
  417.         m_ctlEdit[i].SetFieldName(_T(""));
  418.         m_ctlColName[i].SetWindowText(_T(""));
  419.     }
  420.     m_strPictCol = _T("");
  421.     m_ctlPicture.SetData(NULL);
  422.     m_nEditIndex = 0;
  423.     m_strTableName = _T("");
  424.     m_ctlRecNum.SetWindowText(_T(""));
  425.     m_nRecNum = 1;
  426. }
  427.  
  428. void CDAOContDlg::UpdateFields()
  429. {
  430.     m_bUpdating = TRUE; // Don't want data binding notifications during updates
  431.     CString strRecNum;
  432.     strRecNum.Format(_T("(%d)"),m_nRecNum);
  433.     m_ctlRecNum.SetWindowText(strRecNum);
  434.     for (int i=0; i<4; i++)
  435.     {
  436.         CString strFieldName = _T("[") + m_ctlEdit[i].GetFieldName() + _T("]");
  437.         if (strFieldName != _T("[]"))
  438.         {
  439.             COleVariant var = m_pRS->GetFieldValue(strFieldName);
  440.             m_ctlEdit[i].SetText(CString(V_BSTRT(&var)));
  441.         }
  442.     }
  443.     if (m_strPictCol != _T(""))
  444.     {
  445.             CString strFieldName = _T("[") + m_strPictCol + _T("]");
  446.             COleVariant var = m_pRS->GetFieldValue(strFieldName);
  447.             try
  448.             {
  449.                 m_ctlPicture.SetData(&var);
  450.             }
  451.             catch (COleException* e)
  452.             {
  453.                 // This is used to catch exceptions thrown
  454.                 // by the picture control when it can't display
  455.                 // the data we gave it for some reason
  456.                 e->Delete();
  457.             }
  458.     }
  459.     m_bUpdating = FALSE;
  460. }
  461.  
  462.  
  463. void CDAOContDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
  464. {
  465.     // Force the current control to receive a WM_KILLFOCUS
  466.     CWnd* wndFocus = GetFocus();
  467.     m_ctlSpin.SetFocus();
  468.     wndFocus->SetFocus();
  469.  
  470.     NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  471.     if (m_pRS->IsOpen())
  472.     {
  473.         if (pNMUpDown->iDelta == 1)
  474.         {
  475.             if (!m_pRS->IsEOF())
  476.             {
  477.                 m_pRS->MoveNext();
  478.                 m_nRecNum++;
  479.             }
  480.             if (m_pRS->IsEOF())
  481.             {
  482.                 m_pRS->MovePrev();
  483.                 m_nRecNum--;
  484.             }
  485.         }
  486.         if (pNMUpDown->iDelta == -1)
  487.         {
  488.             if (!m_pRS->IsBOF())
  489.             {
  490.                 m_pRS->MovePrev();
  491.                 m_nRecNum--;
  492.             }
  493.             if (m_pRS->IsBOF())
  494.             {
  495.                 m_pRS->MoveNext();
  496.                 m_nRecNum++;
  497.             }
  498.         }
  499.         UpdateFields();
  500.     }
  501.     m_ctlSpin.SetPos(1);
  502.     *pResult = 0;
  503. }
  504.  
  505. BEGIN_EVENTSINK_MAP(CDAOContDlg, CDialog)
  506.     //{{AFX_EVENTSINK_MAP(CDAOContDlg)
  507.     //}}AFX_EVENTSINK_MAP
  508.     ON_PROPNOTIFY_RANGE(CDAOContDlg, IDC_DAOEDITCTRL1, IDC_DAOEDITCTRL4, DISPID_TEXT, OnRequestEdit, OnChanged)
  509. //  ON_PROPNOTIFY_RANGE(theClass, idFirst, idLast, dispid, pfnRequest, pfnChanged)
  510. END_EVENTSINK_MAP()
  511.  
  512. BOOL CDAOContDlg::OnRequestEdit(UINT nID, BOOL* pBool)
  513. {
  514.     UpdateData(TRUE);
  515.     if (m_bUpdating)
  516.         *pBool = TRUE;
  517.     else
  518.         *pBool = m_bAllowEdits;
  519.  
  520.     return TRUE;
  521. }
  522.  
  523. BOOL CDAOContDlg::OnChanged(UINT nID)
  524. {
  525.     // Filter out changes due to refreshing the control
  526.     if (m_bUpdating)
  527.         return TRUE;
  528.  
  529.     if (m_pRS->IsOpen())
  530.     {
  531.         UINT nCtl = nID - IDC_DAOEDITCTRL1;
  532.         CString strFieldName = _T("[") + m_ctlEdit[nCtl].GetFieldName() + _T("]");
  533.         m_pRS->Edit();
  534.         COleVariant var(m_ctlEdit[nCtl].GetText(), VT_BSTRT);
  535.         m_pRS->SetFieldValue(strFieldName, var);
  536.         m_pRS->Update();
  537.     }
  538.     return TRUE;
  539. }
  540.