Click here to Skip to main content
15,896,269 members
Articles / Desktop Programming / MFC

MFC DataGrid

Rate me:
Please Sign up or sign in to vote.
5.00/5 (17 votes)
24 Feb 20022 min read 255.5K   7.5K   88  
CDataGrid which was derived from CGridCtrl and used ADO for access to database.
// DataGrid.cpp: implementation of the CDataGrid class.
//
// CDataGrid - the Grid class for access to database
// Written by Kirill Panov <cpanov@yahoo.com>
// Copyright (c) 2000-2002. All Rights Reserved.
//
// This class derived from CGridCtrl by Chris Maunder <cmaunder@mail.com>
// http://www.codeproject.com/miscctrl/gridctrl.asp
// Copyright (c) 1998-2001. All Rights Reserved.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
//////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "Resource.h"

#include "DataGrid.h"
#include "ExString.h"

#ifdef IDD_DIAL_FIND
  #include "DialFind.h"
#endif IDD_DIAL_FIND

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNCREATE(CDataGrid,CGridCtrl)


BEGIN_MESSAGE_MAP(CDataGrid, CGridCtrl)
//{{AFX_MSG_MAP(CGridCtrl)
  ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()





CDataGrid::CDataGrid()
{
  m_strSQLFields=m_strSQLFrom=m_strSQLWhere=m_strSQLOrderBy=m_strKey=_T("");
  m_nSortField=-1;
  m_bWait=false;

  m_hCursorWait= AfxGetApp()->LoadStandardCursor(IDC_WAIT);
}

CDataGrid::~CDataGrid()
{

}


void CDataGrid::OnFixedRowClick(CCellID& cell)
{
  if (!IsValid(cell))
    return;
  Sort(cell.col);
}
void CDataGrid::Requery(  const CString& strKey
    ,const CString& strSQLFields
    ,const CString& strSQLFrom
    ,const CString& strSQLWhere
    ,int NumberSortField
    ,bool AscSortField)
{
  CString strSQLOrderBy;
  m_nSortField=NumberSortField;
  m_bAscSortField=AscSortField;
  if(NumberSortField!=-1)
  {
    strSQLOrderBy=m_field[NumberSortField].Field;
    if(!AscSortField)
      strSQLOrderBy+=_T(" DESC");
  }
  else
  {
    strSQLOrderBy=_T("");
  }
  Requery(strKey,strSQLFields,strSQLFrom,strSQLWhere,strSQLOrderBy);
}

void CDataGrid::Requery(  const CString& strKey
    ,const CString& strSQLFields
    ,const CString& strSQLFrom
    ,const CString& strSQLWhere
    ,const CString& strSQLOrderBy)
{
  ::SetCursor(m_hCursorWait);
  m_strSQLFields=strSQLFields;
  m_strSQLFrom=strSQLFrom;
  m_strSQLWhere=strSQLWhere;
  m_strSQLOrderBy=strSQLOrderBy;
  m_strKey=strKey;

  CString strSQL=_T("SELECT ")+m_strSQLFields+_T(" FROM ")+m_strSQLFrom;
  if(m_strSQLWhere.GetLength()>0)
    strSQL+=_T(" WHERE ")+m_strSQLWhere;

  if(m_strSQLOrderBy.GetLength()>0)
    strSQL+=_T(" ORDER BY ")+m_strSQLOrderBy;

  _variant_t TheValue;

  try
  {
    if(m_pSet==NULL)
    {
      m_pSet.CreateInstance(__uuidof(Recordset));
    }
    else
    {
      if(m_pSet->State == adStateOpen)
        m_pSet->Close();
    }
    m_pSet->Open(_variant_t(strSQL),m_pCon.GetInterfacePtr()
      ,adOpenKeyset
      ,adLockOptimistic
      ,adCmdText);
  }
  catch(_com_error *e)
  {
    CString Error = e->ErrorMessage();
    AfxMessageBox(e->ErrorMessage());
    return;
  }

}

void CDataGrid::Execute(_ConnectionPtr & Con
    ,const CString& strKey
    ,const CString& strSQLFields
    ,const CString& strSQLFrom
    ,const CString& strSQLWhere
    ,int NumberSortField
    ,bool AscSortField)
{
  m_bWait=true;
//  AfxMessageBox("m_bWait=true;");
  CString strSQLOrderBy;
  m_nSortField=NumberSortField;
  m_bAscSortField=AscSortField;
  if(NumberSortField!=-1)
  {
    strSQLOrderBy=m_field[NumberSortField].Field;
    if(!AscSortField)
      strSQLOrderBy+=_T(" DESC");
  }
  else
  {
    strSQLOrderBy=_T("");
  }
  Execute(Con,strKey,strSQLFields,strSQLFrom,strSQLWhere,strSQLOrderBy);
//  m_bWait=false;
//  AfxMessageBox("m_bWait=false;");

  if(NumberSortField!=-1)
  {
    SortItems(NumberSortField, AscSortField);
  }

  Invalidate();
}
void CDataGrid::Execute(_ConnectionPtr & Con
    ,const CString& strKey
    ,const CString& strSQLFields
    ,const CString& strSQLFrom
    ,const CString& strSQLWhere
    ,const CString& strSQLOrderBy)
{
  m_bWait=true;
  m_pCon=Con;
  Requery(strKey,strSQLFields,strSQLFrom,strSQLWhere,strSQLOrderBy);
  Refresh();
  m_bWait=false;
}

void CDataGrid::SetValue(GV_DISPINFO *pDispInfo)
{
  CString strRead;
  strRead.LoadString(IDS_GRID_READ);
  if (GVN_GETDISPINFO == pDispInfo->hdr.code)
  {

    if(pDispInfo->item.row!=0)
    {
      if(m_bWait) return;
      if(m_pSet->State == adStateOpen)
      {
        try
        {
          SetRecordsetPos(pDispInfo->item.row);
          CString name=m_field[pDispInfo->item.col].Field;

          _variant_t TheValue;
          TheValue = m_pSet->Fields->GetItem(_variant_t(name))->Value;

          pDispInfo->item.nFormat=m_field[pDispInfo->item.col].Align;
          if(TheValue.vt!=VT_NULL)
            pDispInfo->item.strText=(char*)_bstr_t(TheValue);
          else
            pDispInfo->item.strText="";
        }
        catch( _com_error &e )
        {
          #if defined PROGRAM_DEBUG
            CString mes1,mes2,mes3,mes4;
            mes1.Format("Error:%08lx.\n", e.Error());
            mes2.Format("ErrorMessage:%s.\n", e.ErrorMessage());
            mes3.Format("Source:%s.\n", (LPCTSTR) _bstr_t(e.Source()));
            mes4.Format("Description:%s.\n", (LPCTSTR) _bstr_t(e.Description()));
            MessageBox(mes1+mes2+mes3+mes4,strRead,MB_ICONERROR);
          #endif

          return;
        }
        catch(...)
        {
          #if defined PROGRAM_DEBUG
            MessageBox("Unhandled Exception",strRead,MB_ICONERROR);
          #endif
        }
      }
      else
      {
        pDispInfo->item.strText=_T("");
      }
    }
    else
    {
      pDispInfo->item.nFormat=DT_CENTER;
      pDispInfo->item.strText=m_field[pDispInfo->item.col].Caption;
    }

  }
  else if (GVN_ODCACHEHINT == pDispInfo->hdr.code)
  {
    GV_CACHEHINT *pCacheHint = (GV_CACHEHINT*)pDispInfo;
  }
}

void CDataGrid::Sort(int NumberField)
{
  CWaitCursor waiter;
  CString strOrderBy=m_field[NumberField].Field;
  if (NumberField == GetSortColumn())
  {
    if(GetSortAscending())
      strOrderBy=strOrderBy+_T(" DESC");
    SortItems(NumberField, !GetSortAscending());
  }
  else
  {
    SortItems(NumberField, TRUE);
  }
  Requery(m_strKey,m_strSQLFields,m_strSQLFrom,m_strSQLWhere,strOrderBy);
  Invalidate();
}

void CDataGrid::Delete()
{
  int nRow = IsSelectRow();
  if (nRow==-1)
    return;
  CString strDel,strErrorDesc;
  strDel.LoadString(IDS_GRID_DEL);
  CString strQuestion;

  strQuestion.LoadString(IDS_GRID_DEL_QUESTION);
  if (MessageBox (strQuestion, strDel,  MB_YESNO|MB_DEFBUTTON2 | MB_ICONQUESTION) == IDNO)
    return;

  try
  {
    m_pSet->Delete(adAffectCurrent);
//    m_pSet->Close();
    m_pSet->Update();
  }
  catch( _com_error &e )
  {

    CString mes1,mes2,mes3,mes4;

    mes1.Format("Error:%08lx.\n", e.Error());
    mes2.Format("ErrorMessage:%s.\n", e.ErrorMessage());
    mes3.Format("Source:%s.\n", (LPCTSTR) _bstr_t(e.Source()));
    mes4.Format("Description:%s.\n", (LPCTSTR) _bstr_t(e.Description()));
    MessageBox(mes1+mes2+mes3+mes4,strDel,MB_ICONERROR);
    return;
  }
  catch(...)
  {
    MessageBox("Unhandled Exception",strDel,MB_ICONERROR);
    return;
  }
  if(nRow==1)
  {
    if(1!=GetRowCount())
      SetRowFocus(nRow);
    else
      SetRowFocus(0);
  }
  else
    SetRowFocus(nRow-1);

  RequerySource(nRow);
}

void CDataGrid::SetRecordsetPos(int pos)
{
//m_pSet->MoveFirst();
//m_pSet->Move(pDispInfo->item.row+1);
  int move=pos-m_pSet->AbsolutePosition;
  try
  {
    m_pSet->Move(move);
  }
  catch (CMemoryException* e)
  {
    #if defined PROGRAM_DEBUG
      e->ReportError();
    #endif
    e->Delete();
  }

}

void CDataGrid::Refresh(int nRowFocus)
{
  try
  {
    SetVirtualMode(true);
    SetCallbackFunc( NULL , 0);
    SetFixedRowCount(1);
    SetFixedColumnCount(0);

    SetColumnCount(m_field.GetSize());
    SetRowCount(m_pSet->GetRecordCount() +1 );
    SetListMode();
    m_bSortOnClick=TRUE;
    AutoSize();
    for(int i=0;i<m_field.GetSize();i++)
      if (m_field[i].With>0)
        SetColumnWidth(i, m_field[i].With);
    GetDefaultCell(FALSE, FALSE)->SetBackClr(RGB(0xFF, 0xFF, 0xE0));
    SetRowFocus(nRowFocus);
  }
  catch (CMemoryException* e)
  {
    e->ReportError();
    e->Delete();
  }

}

void CDataGrid::AddNew()
{

  SetRowCount(m_pSet->GetRecordCount() +1 );
  SetRowFocus(GetRowCount()-1);
}

void CDataGrid::SetRowFocus(int nRow)
{
  if((GetRowCount()>nRow)&&(nRow>-1))
  {
    CCellID cell(nRow,1);
    SetFocusCell(cell);
    SetSelectedRange(nRow,GetFixedColumnCount(), nRow ,GetColumnCount()-1, TRUE);
    EnsureVisible(nRow,1);
  }
}
void CDataGrid::RequerySource(int nRow)
{
  Requery( m_strKey,m_strSQLFields,m_strSQLFrom,m_strSQLWhere,m_strSQLOrderBy);
  SetRowCount(m_pSet->GetRecordCount() +1 );
}



int CDataGrid::IsSelectRow()
{
  int nRow = GetFocusCell().row;
  if (nRow ==-1 )
  {
    CString strWarn,strWarnDesc;
    strWarnDesc.LoadString(IDS_GRID_NO_SEL_DESC);
    strWarn.LoadString(IDS_GRID_NO_SEL_REC);
    MessageBox(strWarnDesc,strWarn,MB_ICONWARNING);
    return( -1);
  }
  else
  {
    SetRecordsetPos(nRow);
    return( nRow);
  }
}

void CDataGrid::OnEditFind()
{

#ifdef IDD_DIAL_FIND

  CDialFind dlg;
  dlg.m_arFind.SetSize(0);
  int i,count=0;

  for(i=0;i<m_field.GetSize();i++)
  {
    if(m_field[i].Find)
    {
      dlg.m_arFind.SetAtGrow(count,CFind( m_field[i].Caption,  count ) );
      count++;
    }
  }

  if (dlg.DoModal() == IDOK)
  {
    int row=GetFocusCell().row ;
    SetRecordsetPos(row);
    int pos=m_pSet->AbsolutePosition;
    CExString strFind,strUp;
    i=dlg.m_arFind.GetAt(dlg.m_nField).m_index;
    if(m_field[i].Type==FIELD_NUMBER)
    {
      strFind=m_field[i].Field+"="+dlg.m_strFind;
    }
    else
    {
      strUp=dlg.m_strFind;
      strUp.MakeUpper();
      strUp.TrimRight();
      strUp.TrimLeft();
      strFind=m_field[i].Field+" like '%"+strUp+"%'";
    }
    m_pSet->Find(_bstr_t(strFind),0,adSearchForward);

    if(m_pSet->AbsolutePosition<1)
    {
      m_pSet->MoveFirst();
//    SetRecordsetPos(row);
      m_pSet->Find(_bstr_t(strFind),0,adSearchForward);
      if(m_pSet->AbsolutePosition<1)
      {
        m_pSet->MoveFirst();
        SetRecordsetPos(row);
        CString strWarn;
        strWarn.LoadString(IDS_GRID_FIND_WARN);
        MessageBox(strWarn,strWarn,MB_ICONWARNING);

      }
    }
    SetRowFocus(m_pSet->AbsolutePosition);
  }

#endif

}

void CDataGrid::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{

  CGridCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
  if (IsCTRLpressed())
  {
    switch (nChar)
    {
     case 'F':
       OnEditFind();
       break;
    }
  }

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Russian Federation Russian Federation
He is a Visual C++ developer,an MCSD and an MCDBA

He has been programming in C/C++ for 6 years, Visual C++ with MFC for 4 years and RDBMS: Oracle, MS SQL for 3 years

Comments and Discussions