MDB Viewer with Out_Lookstyle

(xiaojian.liu@port.ac.uk).
Home Page : http://www2.civl.port.ac.uk/structures/javafe/javacorner/content.html

 

Environment: VC++6 plus CJ60Lib v 6.07 (CodeGuru: Advanced UI)

Overview
This mdbViewer works with CJ60 version 6.07. It is difficult for me to identify what is cool in this piece of work, I just put Kirk Stowell's framework and CDaoRecordset together and make them work. I think the project may be used as framework for those who are interested with CDaoRecordset and are fancy "Good-look" GUI. In addition to these, the project shows people how to

(1) open any MDB and tables
(2) navigate an opened MDB
(3) make non-SQL query

All these will provide a flexible way to manipulate the database.

However, I have to leave the project as IT IS. Features not implemented:
(1) create a new mdb
(1) print
(2) extract data and statistics
(3) implement different document viewers


Some points

To open an MDB file

Following code is used to open mdb files.

void CmdbViewerDoc::OnFileOpenmdb()
{
// initialization of database pointers
m_strDatabasePath.Empty();
if(m_pRecordset != NULL)
{
ASSERT_VALID(m_pRecordset);
if(m_pRecordset->IsOpen())
m_pRecordset->Close();
delete m_pRecordset;
m_pRecordset = NULL;
}

if(&m_mdbDatabase != NULL)
{
ASSERT_VALID(&m_mdbDatabase);
if(m_mdbDatabase.IsOpen())
m_mdbDatabase.Close();
}

DaoOpenMdb();

}

void CmdbViewerDoc::DaoOpenMdb()
{
if (m_strDatabasePath.IsEmpty()) {
CFileDialog dlg(TRUE, ".mdb", "*.mdb");
if (dlg.DoModal() == IDCANCEL) return;
m_strDatabasePath = dlg.GetPathName();
}

BeginWaitCursor();
try {
// nonexclusive, can update(not read-only)
m_mdbDatabase.Open(m_strDatabasePath, FALSE, FALSE);
}
catch (CDaoException* e) {
::DaoErrorMsg(e);
EndWaitCursor();
e->Delete();
return;
}

GetTableInfo();

CContainerView* pContainer =
((CMainFrame*)AfxGetMainWnd())->GetContainerView();
CFolderView* pFolderView = pContainer->GetFolderView();

pFolderView->UpdateTree();

UpdateAllViews(NULL);
EndWaitCursor();
}

where m_strDatabasePath, m_pRecordset and m_mdbDatabase have been declared in the file mdbViewerDoc.h as:

// Attributes
public:
CString m_strDatabasePath;

private:
CDaoRecordset* m_pRecordset;
CDaoDatabase m_mdbDatabase;

To load a recordset by double clicking threeview item

The treeview is updated as soon as an MDB file is opened. You may view a table by left double clicking an item of the treeview. This is implemented by catching NM_DBLCLK message.

void CFolderView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// Get the pointer of GetmdbViewerView() from CMainFrame.
CmdbViewerView* pView =((CMainFrame*)AfxGetMainWnd())->GetmdbViewerView();
CmdbViewerDoc* pDoc =GetDocument();

HTREEITEM hti = m_pTreeCtrl->GetSelectedItem();

if (hti)
{
HTREEITEM htiP=m_pTreeCtrl->GetParentItem(hti);
// if the hited item's parent is the data base, it
// must be a table item, open it then.
if(htiP==m_htiDatabase) {
// set table name first
pDoc->SetTableName(m_pTreeCtrl->GetItemText (hti));
// open this table then
pView->ShowDBTable();
}
}
*pResult = 0;
}

The ShowDBTable() is responsible to update the listview. However, before override CListCtrl::SetItemText , we must convert the field value which is COleVariant, into CString, like this:

COleVariant var;
CString str;
... ...
var = m_pSet->GetFieldValue(0);
str=formatedValue(var);

where formatedValue is a public function.

CString CmdbViewerView::formatedValue(COleVariant var)
{
CString str;
switch (var.vt) {
case VT_BSTR:
str = (LPCSTR) var.bstrVal; // narrow characters in DAO
break;
case VT_I2:
str.Format("%d", (int) var.iVal);
break;
case VT_I4:
str.Format("%d", var.lVal);
break;
case VT_R4:
str.Format("%10.2f", (double) var.fltVal);
break;
case VT_R8:
str.Format("%10.2f", var.dblVal);
break;
case VT_CY:
str = COleCurrency(var).Format();
break;
case VT_DATE:
str = COleDateTime(var).Format();
break;
case VT_BOOL:
str = (var.boolVal == 0) ? "FALSE" : "TRUE";
break;
case VT_NULL:
str = "----";
break;
default:
str.Format("Unk type %d\n", var.vt);
TRACE("Unknown type %d\n", var.vt);
}
return str;
}

Non SQL-query

In this project no class is derived from CDaoRecordset and I did not use DoFieldExchange(CDaoFieldExchange* pFX) stuff. This makes thing flexible but it may difficult to make standard SQL query. Instead I wrote two functions to do the job: CmdbViewerView::Enquery() and CmdbViewerView::ExecuteQuery(). The Enquery() was called when L.Click the icon in the OutLookbar pane and then it passes m_queryField and m_queryString to the ExecuteQuery() as shown below:


void CmdbViewerView::ExecuteQuery()
{
if(m_queryString.IsEmpty()) {
m_IsQuery=FALSE;
return;
} else m_IsQuery=TRUE;
ProcessUpdating(_T("Loading recordset ..."));
// suppose a record set has been opened
CmdbViewerDoc* pDoc = GetDocument();
if(m_pListCtrl!=NULL) ClearListView();
pDoc->LoadRecordset();
m_pSet=pDoc->GetRecordSet();
m_TableName=pDoc->GetTableName();
ProcessUpdating(_T("Searching and updating list view ..."));
int queryFieldIndex=0;
if(m_pSet!= NULL)
{
ASSERT_VALID(m_pSet);
m_nFields = (int) m_pSet->GetFieldCount();
int nColSize =80;
CString fieldname;
CDaoFieldInfo fi;

// build columns first
LV_COLUMN lvCol;
lvCol.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvCol.cx = nColSize;
lvCol.fmt = LVCFMT_LEFT;

for(int i = 0; i < m_nFields; i++) {
m_pSet->GetFieldInfo(i, fi);
fieldname=fi.m_strName;
if(fieldname.Compare(m_queryField)==0) queryFieldIndex=i;
// Insert the ith column into the list control
lvCol.iSubItem = i;
lvCol.pszText = (char*)(LPCTSTR)fieldname;
if(i<m_nColsmax)
{
m_pListCtrl->SetColumn(i, &lvCol);
} else m_pListCtrl->InsertColumn(i, &lvCol);
}
if(m_nColsmax-m_nFields>0) {
for(i = m_nFields; i <m_nColsmax; i++) {
lvCol.iSubItem = i;
lvCol.pszText = (char*)(LPCTSTR)(_T(""));
lvCol.cx = 0; // set this column width as 0
m_pListCtrl->SetColumn(i, &lvCol);
}
}

if(m_nColsmax<m_nFields) m_nColsmax=m_nFields;

// insert items

LV_ITEM lvi;
lvi.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
lvi.stateMask = LVIS_STATEIMAGEMASK;
lvi.state = INDEXTOSTATEIMAGEMASK(1);
lvi.iSubItem = 0;
lvi.iImage = 1; // use icon IDI_ICON_RECORDSEL
COleVariant var;
CString str,str1,str2;
int selectedItems=0;
for (int j=0;! m_pSet->IsEOF () ;j++) {
var = m_pSet->GetFieldValue(queryFieldIndex);
str1=formatedValue(var);
str1.MakeLower();
str2=m_queryString;
str2.MakeLower();

if(str1.Find(str2)>=0) {
lvi.iItem = selectedItems;
var = m_pSet->GetFieldValue(0);
str=formatedValue(var);
lvi.pszText = (char*)(LPCTSTR)str;
if (m_pListCtrl->InsertItem(&lvi) != -1) {
for(i = 1; i < m_nFields; i++) {
var = m_pSet->GetFieldValue(i);
str=formatedValue(var);
m_pListCtrl->SetItemText(selectedItems, i, str);
} // loop on column index i
}
if(m_IsQuery) m_selectedRecords.SetAtGrow(selectedItems,j);
selectedItems++;
}
m_pSet->MoveNext();
} // loop on row index j
m_selectedRecords.FreeExtra();

} else {
AfxMessageBox(_T("This recordset is not properly opened"));
return;
}


}

 

Other matters?

Let the source code tell you more.

 

Download src - 220 Kb



Comments

  • I looked the CJ60Lib.

    Posted by Legacy on 06/04/2003 12:00am

    Originally posted by: Jongmin Cho

    Go to the following link.

    http://www.csdn.net/Dev/Visual%20C++/source%20code/Advanced_UI/demo_ui_mfcxlib.shtml.htm

    PS.
    Dear develpoers.
    If you want to find anything, first of all find in google with the related name(ex,"CJ60Lib Source").

    My home page for korean : www.LonDevice.com

    Reply
  • Windows 2000

    Posted by Legacy on 05/31/2000 12:00am

    Originally posted by: Chris


    I just found out that there is problem whit this program when using Windows 2000, the program starts and is ok, but by the time when i load any mdb database the program just exits. Any idea why?

    Reply
  • why not have cj60lib.h in the demo project?

    Posted by Legacy on 08/05/1999 12:00am

    Originally posted by: liu

    ?

    Reply
  • Executables

    Posted by Legacy on 06/24/1999 12:00am

    Originally posted by: Vinay

    Why don't you have executables so that we can download the executable try it out and then get the code
    

    Reply
  • Unhandled Exception in mdbViewer.exe

    Posted by Legacy on 05/28/1999 12:00am

    Originally posted by: _alin

    Sometimes(please read 'All the time') I receive this message (Unhandle exception ... ).
    in module mdbViewerView.cpp at line 310:
    str = COleDateTime(var).Format();
    the database is the database from demo.
    I tried with another databases and I receive the same Unhandle exception. All the databases has a datetime field.
    It is a problem with COleVariant or what ??

    P.S.
    1. Excellent Look&Feel !
    2. My database has up to 100 000 records, what do you think about a VirtualListView ??

    Reply
  • view too slow

    Posted by Legacy on 05/26/1999 12:00am

    Originally posted by: ipr

    Hi Xiaojian,

    Good examples but...
    Database with 5000 records is too slow.
    Jet database Engine error n� 3164.
    Sometime it crash when quitting.
    Sombody know how to solve these problems

    Thank and bye...
    i.padilla

    Reply
  • Design issues

    Posted by Legacy on 05/26/1999 12:00am

    Originally posted by: Masaaki Onishi

    Hi.

    I happen to make the database application - two views
    formview and listview.
    My application has same functionality of yours and more?
    So, I feel the following considerations to yours and mine.

    1) When we open the database, the cusomter may want to look
    at the listview at the whole display. Even though the customer can change the pane size of the mouse, we need
    some menu or button to this automatically.

    2) If the customer open the database and the record is huge,
    we don't need to show the whole data at one time because it takes much time to show all records. the customer can set how many the records will be displayed at one time and push the button like next view and prev view. This is one disadvangate of listview.

    Because I added the synchronizing of two views, I will get
    some problems to this approach.

    If I am a customer, I want to add more order.
    But thank you for your code and I'll add more functionality
    to my customer database GUI.

    Regards.
    -Masaaaki Onishi-

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

Most Popular Programming Stories

More for Developers

RSS Feeds