/************************************************************************* File: check.cpp Executable: check.exe Abstract: This program implements a farily minimal checkbook. It allows user input for the check number, payee, and amount, and stores these values into a file upon the clicking of the "Enter" button. It keeps a balance, and has basic file commands, accelerators, and command bar buttons. Editing of previous transactions may be added later. Only the last MAC_HISTORY transactions may be viewed. Functions Implemented in check.cpp : Windowing stuff: WinMain WndProc InitApplication InitInstance TermInstance MessageHandlers: DoMainCommandNew DoMainCommandOpen DoEnterButton DoPaintMain DoCreateMain DoAboutDialog Messages handled: Standard: WM_CLOSE WM_COMMAND WM_CREATE WM_DESTROY WM_PAINT Custom (WM_COMMAND stuff): IDM_NEW IDM_OPEN IDM_CLOSE IDM_ABOUT IDB_BUTTON IDM_EXIT ***************************************************************************/ #include "check.h" /*************************************************************************** Globals ***************************************************************************/ HINSTANCE hInst = NULL; // Global copy of hInstance HWND hwndMain = NULL; // Handle to Main window returned from CreateWindow HWND hwndCB = NULL; // Handle to a commandbar HMENU hMenu = NULL; // Handle to a commandbar menu HANDLE hOpenFile = INVALID_HANDLE_VALUE; // Handle to the currently open file double balance; //balance of the open file TCHAR szAppName[TEXTSIZE]; //name of the app (stored in string table resource) TCHAR szTitle[TEXTSIZE]; //name to be displayed (stored in string table resource) // Array tbMenuButton contains the buttons for the menubar static TBBUTTON tbMenuButton[] = { {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, -1}, {STD_FILENEW, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1}, {STD_FILEOPEN, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1}, {STD_DELETE, IDM_CLOSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1}, {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0, -1} }; // Array tbMenuButton contains the tool tips for the menubar TCHAR * szSmallTips[] = { NULL, //menu skipping TEXT("New File"), TEXT("Open File"), TEXT("Close File") }; UINT uNumSmallTips = 4; /************************************************************************************** WndProc - Responsible for dispatching messages sent to the application. *************************************************************************************/ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { LRESULT lResult = TRUE; switch(msg) { case WM_CREATE: //Create the window for the first time DoCreateMain(hwnd, msg, wp, lp); break; case WM_COMMAND: //Process a menu, button, or other user-entered command switch (GET_WM_COMMAND_ID(wp,lp)) { case IDM_NEW: //Open a new checkbook file DoMainCommandNew(hwnd, LOWORD(wp), (HWND)lp, HIWORD(wp)); break; case IDM_OPEN: //Open an old checkbook file DoMainCommandOpen(hwnd, LOWORD(wp), (HWND)lp, HIWORD(wp)); break; case IDM_CLOSE: //Close the checkbook that's currently open CloseHandle(hOpenFile); InvalidateRect(hwnd, NULL, TRUE); break; case IDM_ABOUT: //Spring up the Help About box DialogBox(hInst, TEXT("aboutbox"), hwnd, DoAboutDialog); break; case IDB_BUTTON: //Commit the newly-entered transaction DoEnterButton(hwnd, LOWORD(wp), (HWND)lp, HIWORD(wp)); break; case IDM_EXIT: //Exit the program SendMessage(hwnd, WM_CLOSE, 0, 0); break; default: //If none of the above, do whatever the default says return DefWindowProc(hwnd, msg, wp, lp); } break; case WM_CLOSE: //Exit the program CloseHandle(hOpenFile); //Free resources CommandBar_Destroy(hwndCB); DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); //Destroy these windows break; case WM_PAINT: //Paint pretty boxes on the main windows DoPaintMain(hwnd, msg, wp, lp); break; default: //If none of the above, do whatever the default says lResult = DefWindowProc(hwnd, msg, wp, lp); break; } return (lResult); } /**************************************************************************** DoAboutDialog - Basically closes the dialog no matter what happens *****************************************************************************/ BOOL CALLBACK DoAboutDialog(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg){ case WM_COMMAND: switch (LOWORD(wParam)){ //switch off the button the user presses case IDOK: case IDCANCEL: default: EndDialog(hWnd, 0); return TRUE; break; } break; } return FALSE; } /**************************************************************************** DoCreateMain - Creates the main application window *****************************************************************************/ LRESULT DoCreateMain(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ LPCREATESTRUCT lpcs; HWND hc1, hc2, hc3, hc4; int CBHeight; HICON hIcon; // Load the icon for the program hIcon = (HICON) SendMessage(hWnd, WM_GETICON, 0, 0); if( hIcon == 0) { hIcon = (HICON)LoadImage( hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 32, 32, 0); SendMessage(hWnd, WM_SETICON,FALSE, (LPARAM)hIcon); } // Create the command bar hwndCB = CommandBar_Create(hInst, hWnd, IDC_CMDBAR); // Add the tool tips CommandBar_AddToolTips( hwndCB, uNumSmallTips,szSmallTips); // Add the bitmaps for the command bar buttons CommandBar_AddBitmap(hwndCB, HINST_COMMCTRL, IDB_STD_SMALL_COLOR, 15, 16, 16); // Add the main menu CommandBar_InsertMenubar(hwndCB, hInst, IDM_MAIN_MENU, 0); // Add buttons in tbSTDButton to Commandbar CommandBar_AddButtons(hwndCB, dim(tbMenuButton), tbMenuButton); // Add exit button CommandBar_AddAdornments(hwndCB, 0, 0); // Get menu handle hMenu=CommandBar_GetMenu(hwndCB,0); // Store the height of the command bar (since it is part of the client area) CBHeight = CommandBar_Height(hwndCB); // store various data about the window to be created lpcs = (LPCREATESTRUCT) lp; // Create the window for the user to enter the check number hc1 = CreateWindowEx( WS_EX_WINDOWEDGE, TEXT("edit"), TEXT(""),WS_BORDER | WS_VISIBLE | WS_CHILD, 0, lpcs->cy-20, lpcs->cx-400, 18, hWnd, (HMENU)IDE_CHECKNUM, hInst, NULL ); // Create the window for the user to enter the check recipient hc2 = CreateWindowEx( WS_EX_WINDOWEDGE, TEXT("edit"), TEXT(""),WS_BORDER | WS_VISIBLE | WS_CHILD, lpcs->cx-400, lpcs->cy-20, lpcs->cx-240, 18, hWnd, (HMENU)IDE_CHECKREC, hInst, NULL ); // Create the window for the user to enter the check amount hc3 = CreateWindowEx( WS_EX_WINDOWEDGE, TEXT("edit"), TEXT(""),WS_BORDER | WS_VISIBLE | WS_CHILD, lpcs->cx-160, lpcs->cy-20, lpcs->cx-400, 18, hWnd, (HMENU)IDE_CHECKAMT, hInst, NULL ); // Create the window for the enter button hc4 = CreateWindowEx( WS_EX_WINDOWEDGE, TEXT("button"), TEXT("Enter"),WS_BORDER | WS_VISIBLE | WS_CHILD, lpcs->cx-80, lpcs->cy-20, lpcs->cx-400, 18, hWnd, (HMENU)IDB_BUTTON, hInst, NULL ); return(0); } /**************************************************************************** DoPaintMain - Paint the boxes and such on the main window *****************************************************************************/ LRESULT DoPaintMain(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ RECT rect, textrect; HDC hdc; PAINTSTRUCT ps; HBRUSH hbr, holdbr; int i, num_records; DWORD num_bytes; TCHAR char_buffer[TEXTSIZE]; double double_buffer; int int_buffer; //compensate rectangle for command bar height GetClientRect(hWnd, &rect); rect.top += CommandBar_Height(GetDlgItem(hWnd, IDC_CMDBAR)); hdc = BeginPaint(hWnd, &ps); //Draw rectangles hbr = (HBRUSH)GetStockObject(BLACK_PEN); holdbr = (HBRUSH)SelectObject(hdc, hbr); for(i=50; i<160; i+=18) { Rectangle(hdc, 0, i, 80, i+18); Rectangle(hdc, 80, i, 320, i+18); Rectangle(hdc, 320, i, 400, i+18); Rectangle(hdc, 400, i, 480, i+18); } SelectObject(hdc,holdbr); // Make caption area light gray SetBkMode(hdc, TRANSPARENT); hbr = (HBRUSH)GetStockObject(LTGRAY_BRUSH); holdbr = (HBRUSH)SelectObject(hdc, hbr); Rectangle(hdc,0,176,480,196); SelectObject(hdc,holdbr); // Make caption area light gray SetBkMode(hdc, TRANSPARENT); hbr = (HBRUSH)GetStockObject(LTGRAY_BRUSH); holdbr = (HBRUSH)SelectObject(hdc, hbr); Rectangle(hdc,0,rect.top,480,50); SelectObject(hdc,holdbr); // Write the caption to go above the register area textrect.left = 0; textrect.right = 480; textrect.top = 30; textrect.bottom = 45; DrawText(hdc, TEXT("The Long Brown Check Register"),-1,&textrect,DT_CENTER); // Write the captions to go above the user input area textrect.left = 0; textrect.right = 80; textrect.top = 178; textrect.bottom = 196; DrawText(hdc, TEXT("Check Number"),-1,&textrect,DT_CENTER); textrect.left = 80; textrect.right = 320; textrect.top = 178; textrect.bottom = 196; DrawText(hdc, TEXT("Transaction"),-1,&textrect,DT_CENTER); textrect.left = 320; textrect.right = 400; textrect.top = 178; textrect.bottom = 196; DrawText(hdc, TEXT("Amount"),-1,&textrect,DT_CENTER); textrect.left = 400; textrect.right = 480; textrect.top = 178; textrect.bottom = 196; DrawText(hdc, TEXT("Balance"),-1,&textrect,DT_CENTER); //Draw all the text values from the checkbook file if( hOpenFile != INVALID_HANDLE_VALUE ) { //Figure out how many records are in the currently open file num_records = (int)(GetFileSize(hOpenFile, NULL) / LINESIZE); if (num_records > MAX_HISTORY) num_records = MAX_HISTORY; for(i=1; i<=num_records; i++) { // adjust position in the file so data can be read out SetFilePointer( hOpenFile, -i*LINESIZE, NULL, FILE_END ); // Draw the check number ReadFile( hOpenFile, &int_buffer, sizeof(int), &num_bytes, NULL); if( num_bytes == sizeof(int) ) { _stprintf( char_buffer, TEXT("%d"), int_buffer ); textrect.top = 160 - ((i-1)*18); textrect.bottom = 178 - ((i-1)*18); textrect.left = 5; textrect.right = 75; DrawText( hdc, char_buffer, -1, &textrect, 0 ); } // Draw the check recipient ReadFile( hOpenFile, &char_buffer, TEXTSIZE, &num_bytes, NULL); if( num_bytes == TEXTSIZE ) { textrect.top = 160 - ((i-1)*18); textrect.bottom = 178 - ((i-1)*18); textrect.left = 85; textrect.right = 315; DrawText( hdc, char_buffer, -1, &textrect, 0 ); } // Draw the check amount ReadFile( hOpenFile, &double_buffer, sizeof(double), &num_bytes, NULL); if( num_bytes == sizeof(double) ) { _stprintf( char_buffer, TEXT("%.2f"), double_buffer ); textrect.top = 160 - ((i-1)*18); textrect.bottom = 178 - ((i-1)*18); textrect.left = 325; textrect.right = 395; DrawText( hdc, char_buffer, -1, &textrect, 0 ); } // Draw the check balance ReadFile( hOpenFile, &double_buffer, sizeof(double), &num_bytes, NULL); if( num_bytes == sizeof(double) ) { _stprintf( char_buffer, TEXT("%.2f"), double_buffer ); textrect.top = 160 - ((i-1)*18); textrect.bottom = 178 - ((i-1)*18); textrect.left = 405; textrect.right = 475; DrawText( hdc, char_buffer, -1, &textrect, 0 ); if(i == 1) balance = double_buffer; } } } EndPaint(hWnd, &ps); return (0); } /**************************************************************************** DoEnterButton - Commit the new transaction to a file *****************************************************************************/ LRESULT DoEnterButton(HWND hWnd, WORD idItem, HWND hWndCtrl, WORD wNotifyCode) { //Get the file handle and add to it. int rc, checknum; double checkamount; DWORD cBytes; HWND text_handle; TCHAR text_buffer[TEXTSIZE]; //Make sure we're at the end of the file SetFilePointer( hOpenFile, 0, NULL, FILE_END ); //Write check number to the file (as a raw binary int) text_handle = GetDlgItem(hWnd, IDE_CHECKNUM); GetWindowText(text_handle, text_buffer, TEXTSIZE); checknum = _ttoi(text_buffer); rc = WriteFile(hOpenFile, &checknum, sizeof(int), &cBytes, NULL); SetWindowText(text_handle, TEXT("")); //Write check recipient to the file text_handle = GetDlgItem(hWnd, IDE_CHECKREC); GetWindowText(text_handle, text_buffer, TEXTSIZE); rc = WriteFile(hOpenFile, text_buffer, TEXTSIZE, &cBytes, NULL); SetWindowText(text_handle, TEXT("")); //Write check amount to the file (as a raw binary double) text_handle = GetDlgItem(hWnd, IDE_CHECKAMT); GetWindowText(text_handle, text_buffer, TEXTSIZE); checkamount = _tcstod(text_buffer, NULL); rc = WriteFile(hOpenFile, &checkamount, sizeof(double), &cBytes, NULL); SetWindowText(text_handle, TEXT("")); //Update balance balance += -1*checkamount; rc = WriteFile(hOpenFile, &balance, sizeof(double), &cBytes, NULL); //Force a WM_PAINT message InvalidateRect(hWnd, NULL, TRUE); return(0); } /**************************************************************************** DoMainCommandNew - Create a new checkbook file and open it *****************************************************************************/ LPARAM DoMainCommandNew(HWND hWnd, WORD idItem, HWND hWndCtrl, WORD wNotifyCode) { OPENFILENAME openfile; TCHAR szFileName[MAX_PATH] ={0}; const LPTSTR pszOpenFilter = TEXT("Checkbook files (*.lbc)\0*.lbc\0\0"); INT rc; BOOL bTempBool = FALSE; CloseHandle(hOpenFile); //Free resources do{ //Initialize filename szFileName[0] = '\0'; //Initialize OPENFILENAME struct memset(&openfile, 0, sizeof(openfile)); openfile.lStructSize = sizeof(openfile); openfile.hwndOwner = hWnd; openfile.lpstrFile = szFileName; openfile.nMaxFile = dim(szFileName); openfile.lpstrFilter = pszOpenFilter; openfile.Flags = 0; //Here's where we get the user's selected file. rc = GetSaveFileName(&openfile); //Here's where we open that file hOpenFile = CreateFile((LPTSTR)szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); //Make sure the new file doesn't already exist bTempBool = (hOpenFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS); if (bTempBool == TRUE){ MessageBox(hWnd, TEXT("File already exists. Try again."), TEXT("Error"), MB_OK); } } while (bTempBool == TRUE); //Force a WM_PAINT message InvalidateRect(hWnd, NULL, TRUE); return 0; } /**************************************************************************** DoMainCommandOpen - Open an old file for editing *****************************************************************************/ LPARAM DoMainCommandOpen(HWND hWnd, WORD idItem, HWND hWndCtrl, WORD wNotifyCode) { OPENFILENAME openfile; TCHAR szFileName[MAX_PATH] ={0}; const LPTSTR pszOpenFilter = TEXT("Checkbook files (*.lbc)\0*.lbc\0\0"); INT rc; BOOL bTempBool = FALSE; CloseHandle(hOpenFile); //Free resources do{ //Initialize filename szFileName[0] = '\0'; //Initialize OPENFILENAME struct memset(&openfile, 0, sizeof(openfile)); openfile.lStructSize = sizeof(openfile); openfile.hwndOwner = hWnd; openfile.lpstrFile = szFileName; openfile.nMaxFile = dim(szFileName); openfile.lpstrFilter = pszOpenFilter; openfile.Flags = 0; //Here's where we get the user's selected file. rc = GetOpenFileName(&openfile); //Here's where we open that file hOpenFile = CreateFile((LPTSTR)szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Make sure the file to open actually exists bTempBool = (hOpenFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND); if (bTempBool == TRUE){ MessageBox(hWnd, TEXT("File not found. Try again."), TEXT("Error"), MB_OK); } } while (bTempBool == TRUE); //Force a WM_PAINT message InvalidateRect(hWnd, NULL, TRUE); return 0; } /**************************************************************************** InitInstance - Create the application window *****************************************************************************/ BOOL InitInstance (HINSTANCE hInstance, int CmdShow ) { hInst = hInstance; //Create the window appropriately for the platform #ifdef _WIN32_WCE_EMULATION hwndMain = CreateWindow(szAppName, szTitle, WS_POPUP, 0,0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); #else hwndMain = CreateWindow(szAppName, szTitle, WS_VISIBLE, 0,0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); #endif if ( !hwndMain ) { return FALSE; } //Standard calls ShowWindow(hwndMain, CmdShow ); UpdateWindow(hwndMain); return TRUE; } /**************************************************************************** TermInstance - Fluff function just there because we thought it should be *****************************************************************************/ int TermInstance(HINSTANCE hInstance, int nDefRC) { return nDefRC; } /**************************************************************************** InitApplication - Register the new application class with Windows *****************************************************************************/ BOOL InitApplication ( HINSTANCE hInstance ) { WNDCLASS wc; BOOL f; //Load application information strings LoadString(hInstance,IDS_APPNAME, szAppName,dim(szAppName)); LoadString(hInstance,IDS_APPNAME, szTitle,dim(szTitle)); //Fill up the window class info wc.style = CS_HREDRAW | CS_VREDRAW ; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hIcon = NULL; wc.hInstance = hInstance; wc.hCursor = NULL;// No cursor if target is not NT wc.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; //Register it f = (RegisterClass(&wc)); return f; } /***************************************************************************** WinMain - Program entry point ******************************************************************************/ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int CmdShow) { MSG msg; HACCEL hAccel; // Initialize the application if there is no previous instance if ( !hPrevInstance ) { if ( !InitApplication ( hInstance ) ) { return (FALSE); } } //Initialize the instance if ( !InitInstance( hInstance, CmdShow ) ) { return (FALSE); } //Load accelerators hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDA_ACCEL)); //Message loop while ( GetMessage( &msg, NULL, 0,0 ) == TRUE ) { if(!TranslateAccelerator(hwndMain, hAccel, &msg)){ TranslateMessage (&msg); DispatchMessage(&msg); } } return (msg.wParam); } // END CHECK.CPP