Click here to Skip to main content
Click here to Skip to main content

BasicAdmin - Personal Organizer

, 1 Aug 2009
Rate this:
Please Sign up or sign in to vote.
Finance, contacts, notes organizer
Imagen

Introduction

There are many financial administration programs on the web. But they lack the functionality I need. Shortcuts, fast filter, hierarchical account structure, speed. So I ended up writing my own. It may seem like rewriting the wheel (yet another finance manager program). On the other hand, it was an opportunity to learn and I already had most of the components to build it.

The Program

The utility is an MFC program that uses the feature pack. It also uses a lot of controls from CodeProject. It stores data in a SQLite database. It is compiled so that it works starting with Windows 2000 (no dependencies that I know). It can be modified to work with Win9x by changing the version with PE Explorer, adding GDIPlus.dll and some functions in the code.

It has its own help, but it's not in English (yet).
I have disabled some functionality:

  • Get/upload to/from the web: I have a web page where I can access an SQL Server database. I cannot write in the web server. So, I can save and retrieve the data vía HTTP. All the database is encrypted and put in a text field.
  • Password/Security: The utility has a very basic protection by using a password. You can enable/disable it in BasicAdmin.cpp.

Structure

The code was written directly. It was not well planned. I added functionality as I needed. This code is not supposed to be a tutorial. It wasn't supposed to be an article. I post it because I used a lot of code from CodeProject. The general structure of the code is:

Imagen

I modified the original code to upload it in the article. The SQLite and Crypto++ go into separate DLLs in the original code. That is to speed up full compilation.
Also, code in the "Graph" directory are a subset of a larger project (also called Graph) that static links with this project, that is also to speed up compilation.

It compiles OK with warnings in VS 2008.

Functionality

This project implements a lot of functionality, usually required in many projects:

  • Fast search
  • Add, modify, delete
  • Print
  • Tree management
  • Screen resize
  • Database management
  • Encryption (security)
  • Help

On the other hand, that functionality is not implemented with correctness in mind. It was implemented having in mind time (I don't have much) and features.

Design and Ideas

Explorer View

I always liked the way explorer works. A tree pane in the left and a view pane in the right. The reasons are simple:

  • People are used to the way explorer works
  • It allows to organize lots of items
  • It is not very complicated

There are many other programs that work that way: Visual Studio, SQL Server manager and others to name a few. So, I replicated that functionality (kind of) here. If you click a folder in the tree, you will see a list of the children items in the right pane until you reach an item with no children.

Single Click Access

I don't like functionality that is "buried" inside screens. For example, to go to screen4. Screen1 calls Screen2 calls Screen3 calls Screen4. So, if possible, every screen will be accessible from the tree, directly.

Screen Usage

The data view (grid) should use all the available space. After all, the data view is one of the screens you use the most. So, it should resize with the application. Its columns should resize too. The grid should show all the data loaded.

Grid and Filter

The grid should be fast. It should filter data fast. The problem is that, when you want to filter, you have to go to the database. But, why go to the database if you had to load all the data? So, you can filter the data directly in the grid (putting invisible rows that do not match the filter). When you add an item, you can also add it to the list (no requery the database). That, while it complicates the code a bit, can greatly improve performance and responsiveness.

Graphics

I really like the way Office 2007 looks. And VS 2008 offers the Feature Pack. So, why not use it? To keep the colors consistent, I had to add code for the background, buttons, grid, etc.

Speed

I usually don't like entering data. When I need data, it should be easy to get. So, the utility features:

  • Minimized mode in the system tray
  • Fast filter (again)
  • Shortcuts
  • Few fields (columns)

The Code

There are several parts of the code that can be useful to solve different problems. For example:

Color the Background and Avoid Gray Static Controls

BEGIN_MESSAGE_MAP(CFrmCashManTotals, CDialog)
	ON_WM_CTLCOLOR()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
HBRUSH CFrmCashManTotals::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	int nID = pWnd->GetDlgCtrlID();

	switch (nID)
    {
	case LBLFROM2:case LBLFROM3: case LBLACC: case LBLORDEN:
			pDC->SetBkMode(OPAQUE);
			pDC->SetBkColor(DarColor());
			return (HBRUSH) GetStockObject(NULL_BRUSH);
	}
	return hbr;
}
BOOL CFrmCashManTotals::OnEraseBkgnd(CDC* pDC)
{
	CRect rect;
	GetClientRect(&rect);
	pDC->FillSolidRect(0,0,rect.Width(),rect.Height(),DarColor());
	return TRUE;
}

where DarColor gets the correct color based on the application look:

const COLORREF TemaCeleste            = RGB(227,239,255);
const COLORREF TemaPlateado           = RGB(240,241,242);
const COLORREF TemaNegro              = RGB(220,222,224);
const COLORREF TemaAqua               = RGB(195,202,217);
static COLORREF DarColor()
{
	switch (theApp.m_nAppLook)
	{
		case ID_VIEW_APPLOOK_OFF_2007_BLUE: return TemaCeleste;
		case ID_VIEW_APPLOOK_OFF_2007_BLACK: return TemaNegro;
		case ID_VIEW_APPLOOK_OFF_2007_SILVER: return TemaPlateado;
		case ID_VIEW_APPLOOK_OFF_2007_AQUA: return TemaAqua;
	}
}

Printing

void CFrmAccounts::OnBnClickedBtnPrint2()
{
	CMainFrame* pDato = (CMainFrame*)(AfxGetMainWnd( ));
	::SetWindowLong(this->m_hWnd, GWL_ID, 0);
	CCreateContext context;
	context.m_pNewViewClass=RUNTIME_CLASS(CViewPrintPreview);
	context.m_pCurrentDoc=NULL;
	context.m_pNewDocTemplate=NULL;
	context.m_pLastView=NULL;
	context.m_pCurrentFrame=NULL;
	CViewPrintPreview* pviewpreview = 
		(CViewPrintPreview*)pDato->CreateView(&context);
	pviewpreview->pant = this;
	pviewpreview->m_pCtrl=&m_grid;
	pDato->SetActiveView(pviewpreview);	
	pviewpreview->OnFilePrintPreview();
	ShowWindow(SW_HIDE);
}

and when you close it, switch back to the old view:

void CViewPrintPreview::OnEndPrintPreview
	(CDC* pDC, CPrintInfo* pInfo, POINT point, CPreviewView* pView) 
{
	CView::OnEndPrintPreview(pDC, pInfo, point, pView);
	// Show the original frame
	CMainFrame* pDato = (CMainFrame*)(AfxGetMainWnd( ));
	pDato->CambiarCantRows(nrows);
	pant->ShowWindow(SW_SHOW);
	pDato->SetActiveView((CView*)pant, TRUE);
	pant->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
	this->DestroyWindow();
}

The most important lines here are:

::SetWindowLong(this->m_hWnd, GWL_ID, 0);
pant->SetDlgCtrlID(AFX_IDW_PANE_FIRST); 

Feature Pack

I modified the ribbon (so it doesn't show the orb), the outlook control (so it doesn't show buttons) and the CaptionBar (multiline text). To do that, I created classes that inherit from the Feature Pack classes and overridden methods.

Custom Ribbon

class CCustRibbon: public CMFCRibbonBar
{
	BOOL OnShowRibbonContextMenu
		(CWnd* pWnd, int x, int y, CMFCRibbonBaseElement* pHit);
};

BOOL CCustRibbon::OnShowRibbonContextMenu
		(CWnd* pWnd, int x, int y, CMFCRibbonBaseElement* pHit)
{
	return TRUE;
}

Outlook Bar

class CControlOutLook: public CMFCOutlookBarTabCtrl
{
public:
	CMFCOutlookBarToolBar* GetToolBar();
	DECLARE_MESSAGE_MAP()
	void RecalcLayout();
};

CMFCOutlookBarToolBar* CControlOutLook::GetToolBar()
{
	return &m_wndToolBar;
}
void CControlOutLook::RecalcLayout()
{
	ShowWindow(SW_HIDE);
	CMFCOutlookBarTabCtrl::RecalcLayout();
	GetToolBar()->EnableCustomizeButton(FALSE, 0, _T(""), FALSE);
	GetToolBar()->Invalidate();
	ShowWindow(SW_SHOW);
}

Caption Bar

class CBarraOutLook: public CMFCCaptionBar
{
protected:
	void OnDrawText(CDC* pDC,CRect rect,const CString& strText);
	DECLARE_MESSAGE_MAP()
public:
	CBarraOutLook();
	int AltoTexto;
	void OnSize(UINT nType, int cx, int cy);
	
	//afx_msg void CBarraOutLook::OnNcCalcSize
	// (BOOL bCalcValidRects,NCCALCSIZE_PARAMS* lpncsp);
};

void CBarraOutLook::OnDrawText(CDC* pDC,CRect rect,const CString& strText)
{
	CString dato = strText;
	LPSTR valor = dato.GetBuffer();

	CRect rectdato;
	GetClientRect(&rectdato);

	rect.top = rectdato.top + 9;
	AltoTexto = pDC->DrawTextEx(valor, dato.GetLength(), 
				rect, DT_NOCLIP | DT_WORDBREAK, NULL);
	AltoTexto +=  14;
	
	dato.ReleaseBuffer();

}

I'm sure there must be some easier way to "customize" the feature pack controls. But I couldn't find it.

References

The references to the articles used are in the About screen. I have modified some code and made corrections to some of them.

Other Personal Finance Software

There are many, many good double entry finance manager programs in SourceForge like GNUCash and Money Manager Ex. There is even a Personal Finance category in SourceForge.
You should check them before writing your own. If you find any that you like, you can use it and even contribute.

But, as you already know, there are a lot of "considerations" to take care with software:

  • Programming languages and frameworks: They greatly impact visualization, code simplicity, speed, platforms supported, etc.
  • Decisions regarding features. Many people prioritize some, other people others. In most cases, you have to choose (you cannot have both).
  • Simplicity. I like software easy to use, but I also like customization and power functionality.
  • Control. Eventually, someone has control of the project. If it is not unified, it forks.

Those considerations led me to write my own. I find it difficult to use personal software (for a long time, I used Excel), and I must feel comfortable with the organization software I use.

Pending

The Calendar part of the utility is not finished and it needs major improvement. In fact, that part I'm not using yet. I'm still using TodoList (another great personal organizer software). For passwords, I'm using Keepass but I'll eventually try to include it in this utility. I also have and use a rudimentary PocketPC version in my IPAQ that is not ready to post.

History

  • 1st August, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

ErnestoNet
Software Developer
Argentina Argentina
System developer from Argentina.
 
Programmed in VB 5,6,.NET, C#, Java, PL-SQL, Transac-SQL, C, C++ and even some "calculator" language.
 
Love to build small, useful applications.
Usually building big and complicated apps based on solid, reliable components.
 
Hobbies: reading, photography, chess, paddle, running.

Comments and Discussions

 
GeneralMy vote of 5 Pinmembergabegabe15-Sep-13 5:56 
QuestionHow to compile the project? Pinmemberenterprisingcpp14-Dec-12 22:06 
AnswerRe: How to compile the project? PinmemberErnestoNet16-Dec-12 7:24 
QuestionBasic Admin c# Code PinmemberPrabhakantha Chandrakumara4-May-12 0:16 
AnswerRe: Basic Admin c# Code PinmemberErnestoNet10-May-12 2:24 
GeneralMy vote of 5 PinmemberJoao Araujo6-Feb-11 19:11 
GeneralRe: My vote of 5 PinmemberErnestoNet10-Feb-11 6:30 
Thanks. I´ll post an update soon
it´s the journey, not the destination that matters

GeneralString table in English PinmemberFlackPanzer3-Jun-10 10:19 
GeneralVC 2005 project PinmembervizEQ5-Aug-09 22:44 
GeneralRe: VC 2005 project PinmembervizEQ6-Aug-09 2:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 1 Aug 2009
Article Copyright 2009 by ErnestoNet
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid