Click here to Skip to main content
15,881,424 members
Articles / Web Development / HTML

A Comprehensive CE Class Library to Replace ATL and MFC

Rate me:
Please Sign up or sign in to vote.
4.48/5 (14 votes)
4 Oct 2000CPOL 277.9K   998   70  
A collection of classes for CE that do not use ATL or MFC, plus an FTP client, database viewer, and sample application that solves beam deflection equations.
#include "StdAfx.h"
#include "DbMainWnd.h"

#include "DbViewRes.h"
#include "CeFontDlg.h"

#include "DbWiz.h"

#define IDC_TREE	100
#define IDC_LIST	101
#define IDC_BAND	102

#if defined(_WIN32_WCE_POCKETPC)
	static SHACTIVATEINFO s_saiDlgBox;
	static SHACTIVATEINFO s_sai;
#endif

LPCTSTR GetTypeName(WORD wType)
{
	switch (wType)
	{
	case 0:				return _T("Unspecified");
	case CEVT_I2:		return _T("Short");
	case CEVT_UI2:		return _T("UShort");
	case CEVT_I4:		return _T("Int");
	case CEVT_UI4:		return _T("UInt");
	case CEVT_FILETIME:	return _T("FileTime");
	case CEVT_LPWSTR:	return _T("String");
	case CEVT_BLOB:		return _T("Blob");
	}
	return _T("???");
}

///////////////////////////////////////////////////////////////////////////////
//
// CeAboutDlg = Dialog for displaying information about the product
//
///////////////////////////////////////////////////////////////////////////////

class CeAboutDlg: public CeScrollDialog
{
private:
	CeChildMgr m_mgr;

public:
	CeAboutDlg(): CeScrollDialog(IDD_ABOUT)
		{}

	virtual BOOL OnInitDialog();
	virtual void OnSize(UINT nType, int cx, int cy, bool& bHandled)
	{
		m_mgr.OnSize(nType, cx, cy);
		CeScrollDialog::OnSize(nType, cx, cy, bHandled);
	}
};


#define IDT_ANIM_ICON	100

BOOL CeAboutDlg::OnInitDialog()
{
	BOOL bRet = CeScrollDialog::OnInitDialog();

	m_mgr.Manage(GetDlgItem(IDC_NAME_STATIC), AL_ADJUST_SIZE);

#ifdef _WIN32_WCE_POCKETPC
	// Create a Done button and size it.  
	SHINITDLGINFO shidi;
	shidi.dwMask = SHIDIM_FLAGS;
	shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
	shidi.hDlg = m_hWnd;

	SHInitDialog(&shidi);
#endif

	// allow controls to be created
	return bRet;
}


///////////////////////////////////////////////////////////////////////////////

class CePropDlg: public CeScrollDialog
{
private:
	CeChildMgr m_mgr;

public:
	CEOID m_oidDb;

	CePropDlg(): CeScrollDialog()
		{ m_oidDb = 0; }

	virtual BOOL OnInitDialog();
	virtual void OnSettingChange(WORD wFlag, LPCTSTR pszSection, bool& bHandled);
	virtual void OnSize(UINT nType, int cx, int cy, bool& bHandled);
};

BOOL CePropDlg::OnInitDialog()
{
	CeScrollDialog::OnInitDialog();


	CeString str;
	CEOIDINFO oidInfo;
	ZeroMemory(&oidInfo, sizeof oidInfo);
	::CeOidGetInfo(m_oidDb, &oidInfo);

	SetDlgItemText(IDC_STATIC_NAME, oidInfo.infDatabase.szDbaseName);

	if (oidInfo.infDatabase.dwFlags & CEDB_VALIDTYPE)
	{
		str.SetULong(oidInfo.infDatabase.dwDbaseType);
		SetDlgItemText(IDC_STATIC_TYPE, str);
	}
	else
		SetDlgItemText(IDC_STATIC_TYPE, _T(""));

	str.SetULong(oidInfo.infDatabase.wNumRecords);
	SetDlgItemText(IDC_STATIC_RECORDS, str);

	str.SetULong(oidInfo.infDatabase.dwSize);
	SetDlgItemText(IDC_STATIC_SIZE, str);

	SYSTEMTIME st;
	BOOL bSuccess = ::FileTimeToSystemTime(&oidInfo.infDatabase.ftLastModified, &st);
	if (! bSuccess || st.wYear > 9999)
	{
		str.Empty();
	}
	else
	{
		CeString strTime;

		::GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_SHORTDATE,
			&st, NULL, str.GetBufferSetLength(32), 32);
		str.ReleaseBuffer();

		str += _T(" ");

		::GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS,
			&st, NULL, strTime.GetBufferSetLength(32), 32);
		strTime.ReleaseBuffer();

		str += strTime;
	}
	SetDlgItemText(IDC_STATIC_MODIFIED, str);

	str.Format(_T("0x%x"), m_oidDb);
	SetDlgItemText(IDC_STATIC_OID, str);

	// Set up the columns for the sort
	HWND hList = GetDlgItem(IDC_KEYS);

	ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);

	// No sorts
	if (! (oidInfo.infDatabase.dwFlags & CEDB_VALIDSORTSPEC) ||
		(oidInfo.infDatabase.wNumSortOrder == 1) && 
		(oidInfo.infDatabase.rgSortSpecs[0].propid == 0))
		return TRUE;

	// Setup the columns
	LVCOLUMN col;
	col.mask = LVCF_TEXT; 
	col.pszText = _T("Column");
	ListView_InsertColumn(hList, 0, &col);

	col.pszText = _T("Type");
	ListView_InsertColumn(hList, 1, &col);

	col.pszText = _T("Style");
	ListView_InsertColumn(hList, 2, &col);
	
	LVITEM item;
	for (int ii = 0; ii < oidInfo.infDatabase.wNumSortOrder; ii++)
	{
		CeString str;
		str.SetLong(HIWORD(oidInfo.infDatabase.rgSortSpecs[ii].propid), 16);

		item.mask = LVIF_TEXT;
		item.pszText = (LPTSTR) (LPCTSTR) str;
		item.iSubItem = 0; 
		item.iItem = ListView_GetItemCount(hList);

		ListView_InsertItem(hList, &item);

		LPCTSTR lpszType = GetTypeName(
			TypeFromPropID(oidInfo.infDatabase.rgSortSpecs[ii].propid));

		item.pszText = (LPTSTR) lpszType;
		item.iSubItem = 1;

		ListView_SetItem(hList, &item);

		str.Empty();
		DWORD dwFlags = oidInfo.infDatabase.rgSortSpecs[ii].dwFlags;
		if (dwFlags & CEDB_SORT_DESCENDING)
			str += _T("Descending ");
		if (dwFlags & CEDB_SORT_CASEINSENSITIVE)
			str += _T("CaseInsensitive ");
		if (dwFlags & CEDB_SORT_UNKNOWNFIRST)
			str += _T("UnknownFirst");

		item.pszText = (LPTSTR) (LPCTSTR) str;
		item.iSubItem = 2;

		ListView_SetItem(hList, &item);
	}

	m_mgr.Manage(GetDlgItem(IDC_STATIC_NAME), AL_ADJUST_WIDTH);
	m_mgr.Manage(GetDlgItem(IDC_STATIC_TYPE), AL_ADJUST_WIDTH);
	m_mgr.Manage(GetDlgItem(IDC_STATIC_RECORDS), AL_ADJUST_WIDTH);
	m_mgr.Manage(GetDlgItem(IDC_STATIC_SIZE), AL_ADJUST_WIDTH);
	m_mgr.Manage(GetDlgItem(IDC_STATIC_MODIFIED), AL_ADJUST_WIDTH);
	m_mgr.Manage(GetDlgItem(IDC_STATIC_OID), AL_ADJUST_WIDTH);
	m_mgr.Manage(GetDlgItem(IDC_KEYS), AL_ADJUST_SIZE);

	ListView_SetColumnWidth(hList, 0, LVSCW_AUTOSIZE_USEHEADER);
	ListView_SetColumnWidth(hList, 1, LVSCW_AUTOSIZE_USEHEADER);
	ListView_SetColumnWidth(hList, 2, LVSCW_AUTOSIZE_USEHEADER);

#ifdef _WIN32_WCE_POCKETPC
	// Create a Done button and size it.  
	SHINITDLGINFO shidi;
	shidi.dwMask = SHIDIM_FLAGS;
	shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
	shidi.hDlg = m_hWnd;

	SHInitDialog(&shidi);
#endif

	return TRUE;
}

void CePropDlg::OnSize(UINT nType, int cx, int cy, bool& bHandled)
{
	m_mgr.OnSize(nType, cx, cy);

	CeScrollDialog::OnSize(nType, cx, cy, bHandled);
}

void CePropDlg::OnSettingChange( WORD wFlag, LPCTSTR pszSection, bool& bHandled )
{
#if defined(_WIN32_WCE_POCKETPC)

	s_saiDlgBox.cbSize = sizeof s_saiDlgBox;
	SHHandleWMSettingChange(m_hWnd, wFlag, (long) pszSection, &s_saiDlgBox);
	bHandled = true;

#elif defined(_WIN32_WCE_PSPC)

	switch (wFlag)
	{
	case SPI_SETSIPINFO:
		{
			SIPINFO si;
			memset( &si, 0, sizeof( si ) );
			si.cbSize = sizeof( si );
			if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) ) 
			{
				MoveWindow(
					si.rcVisibleDesktop.left,
					si.rcVisibleDesktop.top,
					si.rcVisibleDesktop.right - si.rcVisibleDesktop.left,
					si.rcVisibleDesktop.bottom -
					si.rcVisibleDesktop.top,
					TRUE );
			}
		}
		break;
	default:
		break;
	}

#endif // _WIN32_PPC_

}

///////////////////////////////////////////////////////////////////////////////

CeDbMainWnd::CeDbMainWnd()
{
	m_hFont = NULL;
	m_hImages = NULL;
	m_bPalm = false;
	m_bMoving = false;
	m_nFontSize = 0;

	m_nFirst = 0;
	m_nRecs = 0;

	// always 1 to start, well, not yet
	m_nCols = 0;

	m_hwndList = NULL;
	m_hwndTree = NULL;
}


BOOL CeDbMainWnd::OnCommand(WPARAM wParam, LPARAM lParam, bool& bHandled)
{
	WORD wNotify = HIWORD(wParam);	// notification code 
	WORD wId	 = LOWORD(wParam);	// item, control, or accelerator identifier 
	HWND hwndCtl = (HWND) lParam;	// handle of control 

	// menu commands
	if (0 == wNotify)
	{
		// Parse the menu selections:
		bHandled = true;
		switch (wId)
		{
		case IDM_ABOUT:			OnAbout();			break;
		case IDM_QUIT:			DestroyWindow();	break;
		case IDM_DELDB:			OnDeleteDb();		break;
		case IDM_DELRECORD:		OnDeleteRecord();	break;
		case IDM_REFRESH:		OnRefresh();		break;
		case IDM_PROPERTIES:	OnProperties();		break;
		case ID_VIEW_OPTIONS:	OnOptions();		break;

		default:
			bHandled = false;
			break;
		}
	}

	return 0;
}


void CeDbMainWnd::OnSettingChange( WORD wFlag, LPCTSTR pszSection, bool& bHandled )
{
#if defined(_WIN32_WCE_POCKETPC)

	s_sai.cbSize = sizeof s_sai;

  	SHHandleWMSettingChange(m_hWnd, wFlag, (long) pszSection, &s_sai);
	bHandled = true;

#elif defined(_WIN32_WCE_PSPC)

	switch (wFlag)
	{
	case SPI_SETSIPINFO:
		{
			SIPINFO si;
			memset( &si, 0, sizeof( si ) );
			si.cbSize = sizeof( si );
			if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) ) 
			{
				MoveWindow(
					si.rcVisibleDesktop.left,
					si.rcVisibleDesktop.top,
					si.rcVisibleDesktop.right - si.rcVisibleDesktop.left,
					si.rcVisibleDesktop.bottom -
					si.rcVisibleDesktop.top,
					TRUE );
			}
		}
		break;
	default:
		break;
	}

#endif // _WIN32_PPC_
}


TCHAR* g_szSmallTips[] =
{
	NULL, // skipping menu
	_T("Delete Datebase"),
	_T("Delete Records"),
	_T("About DbView"),
	_T("Database Properties"),
};

TBBUTTON g_tb[] =
{
	{0, 0,				TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0},
	{0, IDM_DELDB,		TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
	{0, IDM_DELRECORD,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
	{0, IDM_ABOUT,		TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
	{0, IDM_PROPERTIES, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
};

extern HINSTANCE g_hInst;

void CeDbMainWnd::CreateBars()
{
#if defined(_WIN32_WCE_POCKETPC)

	#pragma comment(lib, "aygshell.lib")

	HDC hDC = GetWindowDC();
	int nBits = ::GetDeviceCaps(hDC, BITSPIXEL);
	ReleaseDC(hDC);

	SHMENUBARINFO mbi;

	//set up menu bar structure
	memset(&mbi, 0, sizeof(SHMENUBARINFO));
	mbi.cbSize		= sizeof(SHMENUBARINFO);
	mbi.hwndParent	= m_hWnd;
	mbi.nToolBarId	= IDR_MENU1;
	mbi.hInstRes	= g_hInst;
	mbi.cBmpImages	= 3;
//mbi.nBmpId		= IDR_MENU1;
	mbi.nBmpId		= (nBits <= 2) ? IDR_MENU1_4: IDR_MENU1_16;
	mbi.dwFlags		= 0; //SHCMBF_EMPTYBAR;

	if (!SHCreateMenuBar(&mbi))
	{
		DWORD dw = GetLastError();
		MessageBox(_T("SHCreateMenuBar Failed"), _T("Error"), MB_OK|MB_ICONERROR);
	}

	//m_hwndCmdBar = mbi.hwndMB;

#elif defined(_WIN32_WCE)

	m_cmdband.Create(m_hWnd, IDC_BAND, RBS_SMARTLABELS|RBS_VARHEIGHT|RBS_BANDBORDERS, NULL);

	REBARBANDINFO rbbi;
	memset(&rbbi, 0, sizeof rbbi);

	// specific init
	rbbi.cbSize = sizeof REBARBANDINFO;
	rbbi.wID    = IDC_BAND;
	rbbi.fMask  = RBBIM_ID|RBBIM_IMAGE|RBBIM_STYLE;
	rbbi.fStyle = RBBS_NOGRIPPER;
	rbbi.iImage = 0;

	if (m_cmdband.AddBands(1, &rbbi))
	{
		// Add the menu bar first
		m_cmdband.GetCommandBar(0).InsertMenubar(IDR_MENU1, 0);

		int nStd = m_cmdband.GetCommandBar(0).AddStdBitmap(IDB_STD_SMALL_COLOR);
		HDC hDC = GetWindowDC();
		int nBits = ::GetDeviceCaps(hDC, BITSPIXEL);
		int nLocal;
		ReleaseDC(hDC);

		if (nBits <= 2)
		{
			nLocal = m_cmdband.GetCommandBar(0).AddBitmap(IDB_DELDB4, 1, 16, 16);
			m_cmdband.GetCommandBar(0).AddBitmap(IDB_DELRECORD4, 1, 16, 16);
			m_cmdband.GetCommandBar(0).AddBitmap(IDB_HELP4, 1, 16, 16);
		}
		else
		{
			nLocal = m_cmdband.GetCommandBar(0).AddBitmap(IDB_DELDB16, 1, 16, 16);
			m_cmdband.GetCommandBar(0).AddBitmap(IDB_DELRECORD16, 1, 16, 16);
			m_cmdband.GetCommandBar(0).AddBitmap(IDB_HELP16, 1, 16, 16);
		}
		 
		g_tb[0].iBitmap = 0;
		g_tb[1].iBitmap = nLocal + 0;
		g_tb[2].iBitmap = nLocal + 1;
		g_tb[3].iBitmap = nLocal + 2;
		g_tb[4].iBitmap = nStd + STD_PROPERTIES;

		m_cmdband.GetCommandBar(0).AddButtons(sizeof(g_tb) / sizeof(TBBUTTON), g_tb);

		// Add tooltips for the buttons we added
	    m_cmdband.GetCommandBar(0).AddToolTips(sizeof(g_szSmallTips)/sizeof(TCHAR*), (LPTSTR) g_szSmallTips);
	}
#endif

}



BOOL CeDbMainWnd::OnCreate(LPCREATESTRUCT lpCS, bool& bHandled)
{
	bHandled = true;

	CreateBars();

	CeRect rc;
	GetClientRect(&rc);

#if defined(_WIN32_WCE)
	if (m_cmdband)
		rc.top += m_cmdband.Height();
#endif

	CeRect rcTree, rcList;
	GetWindowPlacements(rc, rcTree, rcList);

	//
	DWORD dwStyle =	WS_VISIBLE|
		WS_CHILD|
		TVS_HASBUTTONS|
		TVS_HASLINES|
		TVS_LINESATROOT|
		TVS_DISABLEDRAGDROP|
		TVS_SHOWSELALWAYS;

	m_hwndTree = CreateWindowEx(0 /*WS_EX_CLIENTEDGE*/, 
		WC_TREEVIEW, NULL, dwStyle, 
		rcTree.left, rcTree.top, rcTree.Width(), rcTree.Height(),
		*this, (HMENU) IDC_TREE, CeGetAppInstance(), NULL);

	HIMAGELIST hImages = ImageList_Create(16, 16, ILC_MASK, 1, 1);
	HICON hSmallIcon = (HICON) LoadImage(CeGetAppInstance(),
		MAKEINTRESOURCE(IDI_ICON1),
		IMAGE_ICON, 16, 16, 0);
	ImageList_AddIcon(hImages, hSmallIcon);
	TreeView_SetImageList(m_hwndTree, hImages, TVSIL_NORMAL);

	CreateList(rcList, false);

	//
	AddDatabases();

#if defined(_WIN32_WCE)
	if (m_cmdband)
	    // Add Close button
		m_cmdband.AddAdornments(0);
#endif

	// Get the font back from the settings
	CeRegKey key;
	key.Create(HKEY_LOCAL_MACHINE, _T("Software\\Magenic\\DbView"));

	LOGFONT lf;
	DWORD dwByteCnt = sizeof(LOGFONT);
	if (S_OK == key.QueryValue((BYTE*) &lf, _T("Font"), &dwByteCnt))
	{
		if (sizeof(LOGFONT) == dwByteCnt)
		{
			// create an initial font from the LOGFONT structure written
			// out to the registry
			HFONT hFont = ::CreateFontIndirect(&lf);
			SetCtrlFont(hFont);
		}
	}

	return TRUE;
}

void CeDbMainWnd::CreateList(CeRect& rcList, bool bOwnerData)
{
	DWORD dwStyle = WS_VISIBLE|WS_CHILD | LVS_REPORT|LVS_SHOWSELALWAYS;

	if (m_hwndList)
		::DestroyWindow(m_hwndList);

	if (bOwnerData)
		// virtual listview...
		dwStyle |= LVS_OWNERDATA;

	m_hwndList = CreateWindowEx(0 /*WS_EX_CLIENTEDGE*/,
		WC_LISTVIEW, NULL, dwStyle, 
		rcList.left, rcList.top, rcList.Width(), rcList.Height(),
		*this, (HMENU) IDC_LIST, CeGetAppInstance(), NULL);

	// Set the panes
	SetPanes(m_hwndTree, m_hwndList);

	ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT);

	::SendMessage(m_hwndList, WM_SETFONT, (WPARAM) m_hFont, TRUE);
}

void CeDbMainWnd::ReCreateList(bool bOwnerData)
{
	ASSERT(m_hwndList != NULL);

	CeRect rc;

	::GetWindowRect(m_hwndList, &rc);
	ScreenToClient(&rc);

	bool bVirtual = (::GetWindowLong(m_hwndList, GWL_STYLE) & LVS_OWNERDATA) ? true: false;

	if (bVirtual != bOwnerData)
		CreateList(rc, bOwnerData);
}


bool CeDbMainWnd::AddDatabases()
{
	CeDbEnum dbenum;
	TVINSERTSTRUCT tvis;
	::ZeroMemory(&tvis, sizeof tvis);

	tvis.hParent = TVI_ROOT;
	tvis.hInsertAfter = TVI_ROOT;
	tvis.item.mask = TVIF_TEXT | TVIF_PARAM;
	tvis.item.pszText = _T("Databases");
	tvis.item.lParam = 0xffffffff;
	tvis.item.cchTextMax = 9;

	// call for refresh
	TreeView_DeleteAllItems(m_hwndTree);

	HTREEITEM hRoot = TreeView_InsertItem(m_hwndTree, &tvis);
	CEOID oid = 0;

	if (! dbenum.First())
		return false;

	while (dbenum.Next())
	{
		CeString str = dbenum.GetName();

		tvis.hParent = hRoot;
		tvis.hInsertAfter = 0;
		tvis.item.mask = TVIF_CHILDREN | TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE;
		tvis.item.pszText = (LPTSTR) (LPCTSTR) str;
		tvis.item.cchTextMax = str.Length();
		tvis.item.cChildren = 0;
		tvis.item.iImage = 0;
		tvis.item.lParam = dbenum.GetOid();

		HTREEITEM hSelItem = TreeView_InsertItem(m_hwndTree, &tvis);

		if (0 == oid)
		{
			// select the first database
			oid = dbenum.GetOid();
			TreeView_SelectItem(m_hwndTree, hSelItem);
			ResetList();
		}
	}

	// Add the records for the selected database
	return true;
}


void CeDbMainWnd::ResetContent(CEOID oidDb, DWORD dwProp)
{
	// reset the content of the list
	ListView_SetItemCount(m_hwndList, 0);

	if (oidDb == 0)
		// reuse 
		oidDb = m_oidDb;
	else if (0xffffffff != oidDb)
		// new database
		m_oidDb = oidDb;
	else
		// at the root
		m_oidDb = 0xffffffff;

	// close if open
	m_db.Close();

	if (m_oidDb != 0xffffffff)
	{
		ReCreateList(true);

		CEOIDINFO oidInfo;
		ZeroMemory(&oidInfo, sizeof oidInfo);
		if (! ::CeOidGetInfo(oidDb, &oidInfo))
			return;

		CEPROPID prop = 0;
		for (int ii = 0; ii < oidInfo.infDatabase.wNumSortOrder; ii++)
		{
			if (dwProp == oidInfo.infDatabase.rgSortSpecs[ii].propid)
			{
				prop = dwProp;
				break;
			}
		}

		m_nRecs = m_nCols = m_nFirst = 0;
		if (! m_db.Open(oidDb, prop))
		{
			// print error
			return;
		}

		// Set the count to actual
		ListView_SetItemCount(m_hwndList, oidInfo.infDatabase.wNumRecords);
	}
	else
	{
		ReCreateList(false);

		LV_COLUMN lvc;
		lvc.mask = LVCF_TEXT;
		lvc.pszText = _T("Name");
		ListView_InsertColumn(m_hwndList, 0, &lvc);

		lvc.pszText = _T("Records");
		ListView_InsertColumn(m_hwndList, 1, &lvc);

		lvc.pszText = _T("Sorts");
		ListView_InsertColumn(m_hwndList, 2, &lvc);

		lvc.pszText = _T("Size");
		ListView_InsertColumn(m_hwndList, 3, &lvc);

		CeDbEnum dbenum;

		if (! dbenum.First())
			return;

		int ii = 0;
		while (dbenum.Next())
		{
			LV_ITEM lvi;
			lvi.mask = LVIF_TEXT;
			lvi.pszText = (LPWSTR) dbenum.GetName();
			lvi.iItem = ListView_GetItemCount(m_hwndList);
			lvi.iSubItem = 0;

			lvi.iItem = ListView_InsertItem(m_hwndList, &lvi);

			if (dbenum.GetInfo())
			{
				CeString strTmp;

				strTmp.SetULong(dbenum.GetNumRecords());
				lvi.pszText = (LPWSTR) (LPCWSTR) strTmp;
				lvi.iSubItem++;
				ListView_SetItem(m_hwndList, &lvi);

				strTmp.SetULong(dbenum.GetNumSorts());
				lvi.pszText = (LPWSTR) (LPCWSTR) strTmp;
				lvi.iSubItem++;
				ListView_SetItem(m_hwndList, &lvi);

				strTmp.SetULong(dbenum.GetSize());
				lvi.pszText = (LPWSTR) (LPCWSTR) strTmp;
				lvi.iSubItem++;
				ListView_SetItem(m_hwndList, &lvi);
			}
		}

		ListView_SetColumnWidth(m_hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
		ListView_SetColumnWidth(m_hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
		ListView_SetColumnWidth(m_hwndList, 2, LVSCW_AUTOSIZE_USEHEADER);
		ListView_SetColumnWidth(m_hwndList, 3, LVSCW_AUTOSIZE_USEHEADER);
		ListView_SetColumnWidth(m_hwndList, 4, LVSCW_AUTOSIZE_USEHEADER);
	}
}


void CeDbMainWnd::ResetList()
{
	CeWaitCursor wait;

	// clean up the column map
	m_mapColumn.RemoveAll();

	::SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);

	// remove all the columns
	while (ListView_DeleteColumn(m_hwndList, 0))
		;

	// get the CEOID of the database selected (lParam)
	// of the treeview
	HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
	TVITEM tvi;
	tvi.mask = TVIF_HANDLE;
	tvi.hItem = hItem;
	TreeView_GetItem(m_hwndTree, &tvi);
	CEOID oidDb = tvi.lParam;

	::SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0);

	ResetContent(oidDb, 0);
}


bool CeDbMainWnd::DeleteRecord(int nRecord)
{
	if (nRecord < m_nFirst || m_nFirst + m_nRecs <= nRecord)
		// not available in the cache
		return false;

	memmove(&m_records[nRecord], &m_records[nRecord+1], (m_nRecs-(nRecord+1))*sizeof(m_records[0]));
	memmove(&m_oids[nRecord],    &m_oids[nRecord+1],    (m_nRecs-(nRecord+1))*sizeof(m_oids[0]));
	m_nRecs--;

	return true;
}


//
// Cache records for later data retreival, additionally add the columns
// that are required for the data read in if they haven't been yet
//
bool CeDbMainWnd::CacheRecords(int nStart, int nRecords)
{
	if (nStart >= m_nFirst && m_nFirst + m_nRecs >= nStart + nRecords)
		// already available in the cache
		return true;

	if (MAX_RECS < nRecords)
		return false;

	TRACE2(_T("Start: %d, nRecords: %d\n"), nStart, nRecords);

	// Set the Wait cursor
//	HCURSOR hCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));

	// Add the column value and row

	if (! m_db.IsOpen())
		return false;

	// quick hack, should change
	m_nFirst = nStart;
	m_nRecs = nRecords;

	CEOID oidRec = m_db.SeekBegin(nStart);
	for (int nRow = 0; 0 != oidRec && nRow < nRecords;  oidRec = m_db.SeekNext(), nRow++)
	{
		if (!m_db.ReadRec(m_records[nRow]))
			continue;

		m_oids[nRow] = oidRec;

		for (int ii = 0; ii < m_records[nRow].m_wProps; ii++)
		{
			DWORD dwProp = m_records[nRow].m_pProps[ii].propid;
			int nCol = m_mapColumn.FindKey(dwProp);
			CeString str;

			if (nCol < 0)
			{
				// Setup a new property column
				nCol = m_nCols++;
				m_mapColumn.Add(dwProp, nCol);

				LVCOLUMN col;
				col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; 

				switch ( TypeFromPropID(dwProp) )
				{
				case CEVT_I2:
					col.pszText = _T("Short");
					col.fmt = LVCFMT_RIGHT;
					break;
				case CEVT_UI2:
					col.pszText = _T("UShort");
					col.fmt = LVCFMT_RIGHT;
					break;
				case CEVT_I4:
					col.pszText = _T("Int");
					col.fmt = LVCFMT_RIGHT;
					break;
				case CEVT_UI4:
					col.pszText = _T("UInt");
					col.fmt = LVCFMT_RIGHT;
					break;
				case CEVT_FILETIME:
					col.pszText = _T("FileTime");
					col.fmt = LVCFMT_LEFT;
					break;
				case CEVT_LPWSTR:
					col.pszText = _T("String");
					col.fmt = LVCFMT_LEFT;
					break;
				case CEVT_BLOB:
					col.pszText = _T("Blob");
					col.fmt = LVCFMT_LEFT;
					break;
				}

				str.Format(_T("0x%04hx (%s)"), HIWORD(dwProp), col.pszText);

				col.pszText = (LPTSTR) (LPCTSTR) str;
				col.cx = 80;

				ListView_InsertColumn(m_hwndList, nCol, &col);
			}
		}
	}

	return true;
}


void CeDbMainWnd::OnDeleteDb()
{
	// get the CEOID of the database selected (lParam)
	TCHAR szBuf[CEDB_MAXDBASENAMELEN];
	HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
	TVITEM tvi;
	tvi.mask = TVIF_HANDLE|TVIF_TEXT;
	tvi.hItem = hItem;
	tvi.pszText = szBuf;
	tvi.cchTextMax = CEDB_MAXDBASENAMELEN;

	TreeView_GetItem(m_hwndTree, &tvi);

	CEOID oidDb = tvi.lParam;
	if (0 == oidDb)
		return;

	CeString str;
	str.Format(_T("Delete Database %s?"), tvi.pszText);
	int nRet = MessageBox(str, _T("Delete Database"),
		MB_OKCANCEL|MB_ICONWARNING);
	if (IDOK != nRet)
		return;

	// close our active database
	m_db.Close();

	if (! ::CeDeleteDatabase(oidDb))
	{
		str.FormatMessage(GetLastError());
		MessageBox(str, _T("Delete Failed"), MB_OK|MB_ICONWARNING);
	}
	else
	{
		TreeView_DeleteItem(m_hwndTree, hItem);

		// force update of the newly selected database
		ResetList();
	}
}


CEOID CeDbMainWnd::GetListOid(int nSel)
{
	int nRow = nSel - m_nFirst;
	if (m_nRecs <= 0 || nRow < 0 || nRow >= m_nRecs)
		return 0;

	return m_oids[nRow];
}


void CeDbMainWnd::OnDeleteRecord()
{
	// get the CEOID of the database selected (lParam)
	HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
	TVITEM tvi;
	tvi.mask = TVIF_HANDLE;
	tvi.hItem = hItem;
	TreeView_GetItem(m_hwndTree, &tvi);

	CEOID oidDb = tvi.lParam;
	if (0 == oidDb || 0xffffffff == oidDb)
		return;

	// get the selected item
	int nSel = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
	if (-1 == nSel)
	{
		//MessageBox(_T("There are no records to delete."), _T("Delete"),
		//	MB_OK|MB_ICONINFORMATION);
		return;
	}

	int nRet = MessageBox(_T("Delete ALL selected records?"),
		_T("Delete"),	MB_YESNO|MB_ICONWARNING);
	if (IDYES != nRet)
		return;

	for (int ii = 0; (-1 != nSel) && (ii < 40); ii++)
	{
		CEOID oid = GetListOid(nSel);

		TRACE0("Deleting record...\n");
		if (! m_db.DeleteRecord(oid))
		{
			CeString str;
			str.FormatMessage(GetLastError());
			MessageBox(str, _T("Delete Failed"), MB_OK|MB_ICONWARNING);
			break;
		}

		nSel = ListView_GetNextItem(m_hwndList, nSel, LVNI_SELECTED);
	}

	ResetList();
}

void CeDbMainWnd::OnRefresh()
{
	AddDatabases();
}

void CeDbMainWnd::OnOptions()
{
	LOGFONT logfont;
	if (NULL == m_hFont)
	{
		m_nFontSize = 9;
		GetObject(GetStockObject(SYSTEM_FONT), sizeof LOGFONT, &logfont);
	}
	else
	{
		GetObject(m_hFont, sizeof LOGFONT, &logfont);
	}

	CeFontDlg dlg(m_nFontSize, &logfont);

	if (IDOK == dlg.DoModal(IDD_FONTDLG, *this))
	{
		SetCtrlFont(dlg.m_hFont);
		m_nFontSize = dlg.m_nPointSize;
	}
}

void CeDbMainWnd::SetCtrlFont(HFONT hFont)
{
	if (m_hFont)
		::DeleteObject(m_hFont);

	if (NULL == hFont)
	{
		m_hFont = NULL;
		return;
	}
	
	LOGFONT logfont;
	GetObject(hFont, sizeof logfont, &logfont);
	m_hFont = ::CreateFontIndirect(&logfont);
	::SendMessage(m_hwndTree, WM_SETFONT, (WPARAM) m_hFont, TRUE);
	::SendMessage(m_hwndList, WM_SETFONT, (WPARAM) m_hFont, TRUE);
}


void CeDbMainWnd::OnAbout()
{
	CeAboutDlg dlg;
	dlg.DoModal(IDD_ABOUT, *this);
}


void CeDbMainWnd::OnProperties()
{
	// get the CEOID of the database selected (lParam)
	CeString strDb;
	HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
	TVITEM tvi;
	tvi.mask = TVIF_HANDLE | TVIF_PARAM;
	tvi.hItem = hItem;
	TreeView_GetItem(m_hwndTree, &tvi);

	CEOID oidDb = tvi.lParam;
	if (0 == oidDb || 0xffffffff == oidDb)
		return;

	CePropDlg dlg;
	dlg.m_oidDb = oidDb;
	if (GetSystemMetrics(SM_CXSCREEN) >= GetSystemMetrics(SM_CYSCREEN))
		// HPC
		dlg.DoModal(IDD_DBPROPHPC, *this);
	else
		// PPC
		dlg.DoModal(IDD_DBPROPPPC, *this);
}


void CeDbMainWnd::OnDestroy(bool& bHandled)
{
	if (NULL != m_hFont)
	{
		CeRegKey key;
		key.Create(HKEY_LOCAL_MACHINE, _T("Software\\Magenic\\DbView"));

		LOGFONT lf;
		::GetObject((HGDIOBJ) m_hFont, sizeof LOGFONT, &lf);

		DWORD dwByteCnt = sizeof(LOGFONT);
		key.SetValue((BYTE*) &lf, sizeof LOGFONT, _T("Font"));
	}

	bHandled = true;
	PostQuitMessage(0);
}


void CeDbMainWnd::OnClose(bool& bHandled)
{
	bHandled = true;
	DestroyWindow();
}

LRESULT CeDbMainWnd::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
	switch (uMsg)
	{
	case WM_HELP:
		{
		//	PROCESS_INFORMATION pi;
		//	::CreateProcess(_T("peghelp.exe"), _T("file:BeamEx.htc"),
		//		NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
		//	CloseHandle(pi.hProcess);
		//	CloseHandle(pi.hThread);
		}
		break;
	}
	return 1;
}


LRESULT CeDbMainWnd::OnNotify(int nCtrlId, LPNMHDR pNMH, bool& bHandled)
{
	bHandled = false;
	if (IDC_TREE == nCtrlId)
	{
		LPNMTREEVIEW pnmtv;
		switch (pNMH->code)
		{
		case TVN_SELCHANGED:
			pnmtv = (LPNMTREEVIEW) pNMH;
			if (pnmtv->action == TVC_BYKEYBOARD || pnmtv->action == TVC_BYMOUSE)
				ResetList();
			break;
		}
	}
	else if (IDC_LIST == nCtrlId)
	{
		bHandled = true;
		switch (pNMH->code)
		{
		case LVN_COLUMNCLICK:
			OnColumnClick((NMLISTVIEW *) pNMH);
			break;

		case LVN_GETDISPINFO:
			return OnDispInfo((NMLVDISPINFO *) pNMH);

		case LVN_ODCACHEHINT:
			return OnCacheHint((NMLVCACHEHINT *) pNMH);

		case LVN_ODFINDITEM:
			return OnFindItem((NMLVFINDITEM *) pNMH);
		}
	}

	return 0;
}


void CeDbMainWnd::OnColumnClick(NMLISTVIEW *pLV)
{
//	ASSERT(pLV->iItem == -1);

	if (m_oidDb != 0xffffffff)
	{
		// sort on column, but not when at the root
		DWORD dwProp = m_mapColumn.ReverseLookup((WORD) pLV->iSubItem);
		ResetContent(0, dwProp);
	}
}


LRESULT CeDbMainWnd::OnDispInfo(NMLVDISPINFO* pDI)
{
//	typedef struct tagLVDISPINFO
//	{
//		NMHDR hdr;
//		LVITEM item;
//	};

	int nRow = pDI->item.iItem - m_nFirst;
	if (m_nRecs <= 0 || nRow < 0 || nRow >= m_nRecs)
		return 0;

	CeString str;

	// get the column we need data about
	WORD wCol = pDI->item.iSubItem;

	if (0 == wCol)
		TRACE(_T("OnDispInfo: %d\n"), pDI->item.iItem);

	if (pDI->item.mask & LVIF_TEXT)
	{
		DWORD dwProp;
		int nCol = m_mapColumn.FindVal(wCol);
		if (nCol != -1)
		{
			dwProp = m_mapColumn.GetKeyAt(nCol);

			m_records[nRow].GetIdVal(HIWORD(dwProp), str);
			_tcsncpy(pDI->item.pszText, str, pDI->item.cchTextMax);
		}
		else
			*pDI->item.pszText = 0;
	}

	if (pDI->item.mask & LVIF_PARAM)
		// doesn't get sent 
		pDI->item.lParam = m_oids[nRow];

	if (pDI->item.mask & (LVIF_IMAGE|LVIF_STATE))
	{
		pDI->item.iImage = 0;
		pDI->item.state = 0;
	}

	return 0;
}


LRESULT CeDbMainWnd::OnCacheHint(NMLVCACHEHINT * pCacheHint)
{
//	typedef struct tagNMLVCACHEHINT
//	{
//		NMHDR hdr;
//		int iFrom;
//		int  iTo;
//	};

	CacheRecords(pCacheHint->iFrom, pCacheHint->iTo - pCacheHint->iFrom + 1);

	return 0;
}

LRESULT CeDbMainWnd::OnFindItem(NMLVFINDITEM * pFindItem)
{

//	typedef struct tagLVFINDINFO
//	{
//		UINT flags;
//		LPCTSTR psz;
//		LPARAM lParam;
//		POINT pt;
//		UINT vkDirection;
//	};

	return -1;	// nothing found
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions