Click here to Skip to main content
15,892,298 members
Articles / Desktop Programming / WTL

Another WTL Grid

Rate me:
Please Sign up or sign in to vote.
4.94/5 (37 votes)
1 Jun 20035 min read 240.3K   8.4K   101  
A WTL Grid mostly aimed for use against databases.
// MainFrm.h : interface of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////

#pragma once

class CMainFrame : 
	public CFrameWindowImpl<CMainFrame>,
	public CMessageFilter,
	public CGridCtrl::CListener
{
public:
	DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)

	CGridCtrl			m_view, m_detail;
	CDlgEmployees*		m_pEmployees;

	CCommandBarCtrl		m_CmdBar;
	CHorSplitterWindow	m_hzSplit;
	CPaneContainer		m_tPane;
	CPaneContainer		m_bPane;

	ADODB::_ConnectionPtr	m_conn;


	CMainFrame() {
		m_pEmployees = NULL;
	}

	virtual ~CMainFrame() {
		if(m_pEmployees) delete m_pEmployees;
	}

	virtual BOOL PreTranslateMessage(MSG* pMsg) {
		if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
			return TRUE;

		if(m_view.PreTranslateMessage(pMsg))
			return TRUE;

		if(m_detail.PreTranslateMessage(pMsg))
			return TRUE;

		if(m_pEmployees && m_pEmployees->m_grid.PreTranslateMessage(pMsg))
			return TRUE;

		return FALSE;
	}

	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_USER+7, OnPostOpen)
		COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
		COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
		COMMAND_ID_HANDLER(ID_FILE_EMPLOYEES, OnFileEmployees)
		CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
		// create command bar window
		HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
		// attach menu
		m_CmdBar.AttachMenu(GetMenu());
		// load command bar images
		m_CmdBar.LoadImages(IDR_MAINFRAME);
		// remove old menu
		SetMenu(NULL);

		HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

		CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
		AddSimpleReBarBand(hWndCmdBar);
		AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

		CreateSimpleStatusBar();
		m_statusBar.Attach(m_hWndStatusBar);

		// create the horizontal splitter. Note that vSplit is parent of hzSplit
		m_hWndClient = m_hzSplit.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
		// set the horizontal splitter parameters
		m_hzSplit.m_cxyMin = 135; // minimum size
		m_hzSplit.SetSplitterPos(100); // from top

		// create the top container.  Note use of hzSplit as parent
		m_tPane.Create(m_hzSplit);
		// add container to top pane (0) of horizontal splitter
		m_hzSplit.SetSplitterPane(0, m_tPane);
		m_tPane.SetTitle("Orders");
		m_tPane.SetPaneContainerExtendedStyle(PANECNT_NOCLOSEBUTTON);

		m_view.Create(m_tPane, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE, 1);
		m_view.SetExtendedGridStyle(GS_EX_LINENUMBERS,GS_EX_LINENUMBERS);
		m_view.SetListener(this);
		m_tPane.SetClient(m_view);

		m_bPane.Create(m_hzSplit);
		m_hzSplit.SetSplitterPane(1, m_bPane);
		m_bPane.SetTitle("Order Details");
		m_bPane.SetPaneContainerExtendedStyle(PANECNT_NOCLOSEBUTTON);

		m_detail.Create(m_bPane, rcDefault, NULL, WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, WS_EX_CLIENTEDGE, 2);
		m_detail.SetExtendedGridStyle(GS_EX_LINENUMBERS,GS_EX_LINENUMBERS);
		m_detail.AddColumn("Product",240,CGridCtrl::EDIT_DROPDOWNLIST,CGridCtrl::LEFT,VT_I4,"ProductID");
		m_detail.AddColumn("Unit Price",100,CGridCtrl::EDIT_TEXT,CGridCtrl::RIGHT,VT_R8,"UnitPrice");
		m_detail.AddColumn("Quantity",100,CGridCtrl::EDIT_TEXT,CGridCtrl::RIGHT,VT_I4,"Quantity");
		m_detail.AddColumn("Discount",100,CGridCtrl::EDIT_TEXT,CGridCtrl::RIGHT,VT_R8,"Discount");
		
		m_detail.SetListener(this);
		m_bPane.SetClient(m_detail);

		// register object for message filtering and idle updates
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->AddMessageFilter(this);
		PostMessage(WM_USER+7);

		return 0;
	}

	LRESULT OnPostOpen(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
		CWaitCursor wait;

		m_hzSplit.SetSplitterPos(240);
		UpdateWindow();

		_variant_t vt;
		m_conn.CreateInstance("ADODB.Connection");
		m_conn->Open("Provider=sqloledb;Data Source=(local);Initial Catalog=northwind","sa","",0);
		
		m_view.AddColumn("ID",80,CGridCtrl::EDIT_NONE,CGridCtrl::LEFT,VT_I4,"OrderID");
		m_view.AddColumn("Customer",180,CGridCtrl::EDIT_DROPDOWNLIST,CGridCtrl::LEFT,VT_BSTR,"CustomerID");
		m_view.AddColumn("Employee",180,CGridCtrl::EDIT_DROPDOWNLIST,CGridCtrl::LEFT,VT_I4,"EmployeeID");
		m_view.AddColumn("OrderDate",180,CGridCtrl::EDIT_DATE,CGridCtrl::LEFT,VT_DATE,"OrderDate");

		ADODB::_RecordsetPtr rsCustomers = m_conn->Execute("select CustomerID,CompanyName from Customers",&vt,0);
		while(!rsCustomers->adEOF) {
			m_view.AddColumnLookup("CustomerID",rsCustomers->Fields->Item["CustomerID"]->Value,rsCustomers->Fields->Item["CompanyName"]->Value);
			rsCustomers->MoveNext();
		}

		ADODB::_RecordsetPtr rsEmployees = m_conn->Execute("select EmployeeID,Name=LastName + ', ' + FirstName from Employees",&vt,0);
		while(!rsEmployees->adEOF) {
			m_view.AddColumnLookup("EmployeeID",rsEmployees->Fields->Item["EmployeeID"]->Value,rsEmployees->Fields->Item["Name"]->Value);
			rsEmployees->MoveNext();
		}

		ADODB::_RecordsetPtr rsProducts = m_conn->Execute("select ProductID,ProductName from Products",&vt,0);
		while(!rsProducts->adEOF) {
			m_detail.AddColumnLookup("ProductID",rsProducts->Fields->Item["ProductID"]->Value,rsProducts->Fields->Item["ProductName"]->Value);
			rsProducts->MoveNext();
		}

		ADODB::_RecordsetPtr rs = m_conn->Execute("select * from Orders",&vt,0);
		m_view.SetRedraw(FALSE);
		while(!rs->adEOF) {
			long nItem = m_view.AddRow();
			m_view.SetItem(nItem,0L,rs->Fields->Item["OrderID"]->Value);
			m_view.SetItem(nItem,1L,rs->Fields->Item["CustomerID"]->Value);
			m_view.SetItem(nItem,2L,rs->Fields->Item["EmployeeID"]->Value);
			m_view.SetItem(nItem,3L,rs->Fields->Item["OrderDate"]->Value);
			rs->MoveNext();
		}
		m_view.SetRedraw(TRUE);

		return 0;
	}

	LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
		PostMessage(WM_CLOSE);
		return 0;
	}
	
	LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
		CAboutDlg().DoModal(m_hWnd);
		return 0;
	}

	LRESULT OnFileEmployees(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
		if(m_pEmployees) delete m_pEmployees;
		m_pEmployees = new CDlgEmployees(m_conn);
		m_pEmployees->Create(m_hWnd);
		m_pEmployees->ShowWindow(SW_SHOW);
		return 0;
	}

	bool					m_bStatusBar;
	bool					m_bToolBar;
	CStatusBarCtrl			m_statusBar;

	virtual bool OnRowChanging(UINT uID,long nRow) {
		if(uID==1 && m_detail.GetModified()) {
			if(IDYES==AtlMessageBox(m_hWnd,"Order details has changed. Save changes?",IDR_MAINFRAME,MB_YESNO|MB_ICONQUESTION)) {
				AtlMessageBox(m_hWnd,"TODO: No saving in this demo. Row change aborted!",IDR_MAINFRAME,MB_OK|MB_ICONEXCLAMATION);
				return false;
			}
		}

		return true;
	}

	virtual void OnRowChanged(UINT uID,long nRow) {
		if(uID!=1) return;

		CWaitCursor wait;
		CString tmp;
		tmp.Format("Changed row to %d",nRow);
		m_statusBar.SetWindowText(tmp);

		m_detail.DeleteAllItems();
		if(nRow<0) return;
		
		
		CString sql;
		sql.Format("select * from \"Order Details\" where OrderID=%d",(long)m_view.GetItem(nRow,0));

		_variant_t vt;
		ADODB::_RecordsetPtr rs = m_conn->Execute((LPCTSTR)sql,&vt,0);
		m_detail.SetRedraw(FALSE);
		while(!rs->adEOF) {
			long nItem = m_detail.AddRow();
			m_detail.SetItem(nItem,0,rs->Fields->Item["ProductID"]->Value);
			m_detail.SetItem(nItem,1,rs->Fields->Item["UnitPrice"]->Value);
			m_detail.SetItem(nItem,2,rs->Fields->Item["Quantity"]->Value);
			m_detail.SetItem(nItem,3,rs->Fields->Item["Discount"]->Value);
			rs->MoveNext();
		}
		rs->Close();
		m_detail.SetRedraw(TRUE);
	}

	virtual void OnEdit(UINT uID,long nRow) {
		m_statusBar.SetWindowText("Editing");
	}

	virtual bool OnDeleteRow(UINT uID,long nRow) {
		return AtlMessageBox(m_hWnd,"Delete this row?",IDR_MAINFRAME,MB_YESNO|MB_ICONQUESTION)==IDYES;
	}

	virtual void OnNewRow(UINT uID,long nRow) {
		m_view.SetItem(nRow,3,3);
		m_view.SetItem(nRow,0,(long)1);
	}

	virtual void OnRowActivate(UINT uID,long nRow) {
		CString tmp;
		tmp.Format("Row %d was activated",nRow);
		m_statusBar.SetWindowText(tmp);
	}

	virtual void OnModified(UINT uID,LPCTSTR pszColumn,_variant_t vtValue) {
		CString tmp;
		tmp.Format("%s: %s",pszColumn,(LPCTSTR)(_bstr_t)vtValue);
		//AtlMessageBox(m_hWnd,(LPCTSTR)tmp);
		m_statusBar.SetWindowText(tmp);
	}

	virtual COLORREF GetCellColor(UINT uID,long nRow,LPCTSTR pszColumn) {
		switch(uID) {
			case 1:
				if(m_view.GetModified(nRow))
					return RGB(255,240,240);
				break;
			case 2:
				if(m_detail.GetModified(nRow))
					return RGB(255,240,240);
				break;
		}

		return (COLORREF)-1;
	}

};

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
Norway Norway
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions