Annotation of mstools/mfc/samples/tutorial/view.cpp, revision 1.1.1.2

1.1       root        1: // view.cpp : Defines the behaviors for the application and frame window.
                      2: //
                      3: // This is a part of the Microsoft Foundation Classes C++ library.
                      4: // Copyright (C) 1992 Microsoft Corporation
                      5: // All rights reserved.
                      6: //
                      7: // This source code is only intended as a supplement to the
                      8: // Microsoft Foundation Classes Reference and Microsoft
                      9: // QuickHelp documentation provided with the library.
                     10: // See these sources for detailed information regarding the
                     11: // Microsoft Foundation Classes product.
                     12: 
                     13: #include <afxwin.h>
                     14: 
                     15: #include "resource.h"
                     16: #include "database.h"
                     17: #include "view.h"
                     18: 
                     19: #include <commdlg.h>
                     20: 
                     21: #define SIZESTRING 256
                     22: #define SIZENAME 30
                     23: #define SIZEPHONE 26
                     24: #define PAGESIZE 8
                     25: 
                     26: // a simple way to reduce size of C runtimes
                     27: // disables the use of getenv and argv/argc
                     28: extern "C" void _setargv() { }
                     29: extern "C" void _setenvp() { }
                     30: 
                     31: /////////////////////////////////////////////////////////////////////////////
                     32: // Create the single global instance of the database viewer app.
                     33: 
                     34: CTheApp PersonApp;
                     35: 
                     36: /////////////////////////////////////////////////////////////////////////////
                     37: // CTheApp
                     38: 
                     39: //////////////////////////////////////////////////
                     40: //  CtheApp::InitInstance
                     41: //  Override InitInstance function to create a CMainWindow object
                     42: //  and display it on the screen
                     43: //
                     44: BOOL CTheApp::InitInstance()
                     45: {
                     46:        m_pMainWnd = new CMainWindow();
                     47:        m_pMainWnd->ShowWindow( m_nCmdShow );
                     48:        m_pMainWnd->UpdateWindow();
                     49:        return TRUE;
                     50: }
                     51: 
                     52: /////////////////////////////////////////////////////////////////////////////
                     53: // CFindDialog
                     54: 
                     55: //////////////////////////////////////////////////
                     56: //  CFindDialog::OnOK
                     57: //  When the user hits OK get the data entered and store it in this
                     58: //  object.  Then end the dialog.
                     59: //
                     60: void CFindDialog::OnOK()
                     61: {
                     62:        GetDlgItemText( IDC_DATA, m_szFindName.GetBuffer( SIZESTRING ), SIZESTRING );
                     63:        m_szFindName.ReleaseBuffer();
                     64:        EndDialog( IDOK );
                     65: }
                     66: 
                     67: /////////////////////////////////////////////////////////////////////////////
                     68: // CEditPerson
                     69: 
                     70: //////////////////////////////////////////////////
                     71: //  CEditDialog::OnInitDialog
                     72: //  Fill in the fields witht the data placed in this object
                     73: //  when it was created.
                     74: //
                     75: BOOL CEditDialog::OnInitDialog()
                     76: {
                     77:        SetDlgItemText( IDC_LASTNAME,  m_pData->GetLastName() );
                     78:        SetDlgItemText( IDC_FIRSTNAME, m_pData->GetFirstName() );
                     79:        SetDlgItemText( IDC_PHONE, m_pData->GetPhoneNumber() );
                     80:        SetDlgItemText( IDC_MOD, m_pData->GetModTime().Format("%m/%d/%y %H:%M" ) );
                     81:        SendDlgItemMessage( IDC_LASTNAME, EM_SETSEL );
                     82: 
                     83:        return TRUE;
                     84: }
                     85: 
                     86: //////////////////////////////////////////////////
                     87: //  CEditDialog::OnOK
                     88: //  When OK is pressed set the data to what the user has entered.
                     89: //
                     90: void CEditDialog::OnOK()
                     91: {
                     92:        char szTmp[SIZESTRING];
                     93:        
                     94:        GetDlgItemText( IDC_LASTNAME, szTmp, sizeof ( szTmp ) );
                     95:        m_pData->SetLastName( szTmp );
                     96:        
                     97:        GetDlgItemText( IDC_FIRSTNAME, szTmp, sizeof ( szTmp ) );
                     98:        m_pData->SetFirstName( szTmp );
                     99:        
                    100:        GetDlgItemText( IDC_PHONE, szTmp, sizeof ( szTmp ) );
                    101:        m_pData->SetPhoneNumber( szTmp );
                    102:        
                    103:        EndDialog( IDOK );
                    104: }
                    105: 
                    106: /////////////////////////////////////////////////////////////////////////////
                    107: // CMainWindow
                    108: 
                    109: BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
                    110: 
                    111:        // File menu commands:
                    112:        ON_COMMAND( IDM_NEW, OnNew )
                    113:        ON_COMMAND( IDM_OPEN, OnOpen )
                    114:        ON_COMMAND( IDM_SAVE, OnSave )
                    115:        ON_COMMAND( IDM_SAVEAS, OnSaveAs )
                    116:        ON_COMMAND( IDM_CLOSE, OnDBClose )
                    117:        ON_COMMAND( IDM_PRINT, OnPrint )
                    118:        ON_COMMAND( IDM_EXIT, OnExit )
                    119: 
                    120:        // Person menu commands:
                    121:        ON_COMMAND( IDM_ADD, OnAdd )
                    122:        ON_COMMAND( IDM_DELETE, OnDelete )
                    123:        ON_COMMAND( IDM_EDIT, OnEdit )
                    124:        ON_COMMAND( IDM_FIND, OnFind )
                    125:        ON_COMMAND( IDM_FINDALL, OnFindAll )
                    126: 
                    127:        // Help menu commands:
                    128:        ON_COMMAND( IDM_HELP, OnHelp )
                    129:        ON_COMMAND( IDM_ABOUT, OnAbout )
                    130: 
                    131:        // Selection accelerators:
                    132:        ON_COMMAND( VK_UP, OnUp )
                    133:        ON_COMMAND( VK_DOWN, OnDown )
                    134: 
                    135:        // Other Windows messages:
                    136:        ON_WM_CREATE()
                    137:        ON_WM_CLOSE()
                    138:        ON_WM_SIZE()
                    139:        ON_WM_VSCROLL()
                    140:        ON_WM_HSCROLL()
                    141:        ON_WM_LBUTTONDOWN()
                    142:        ON_WM_LBUTTONDBLCLK()
                    143:        ON_WM_KEYDOWN()
                    144:        ON_WM_PAINT()
                    145: END_MESSAGE_MAP()
                    146: 
                    147: 
                    148: //////////////////////////////////////////////////
                    149: //  CMainWindow::CMainWindow
                    150: //  Constructs and initializes a CMainWindow object
                    151: //
                    152: CMainWindow::CMainWindow()
                    153: {
                    154:        VERIFY( LoadAccelTable( "MainAccelTable" ) );
                    155:        VERIFY( Create( NULL, "Phone Book",
                    156:                        WS_OVERLAPPEDWINDOW, rectDefault, NULL, "MainMenu" ) );
                    157:        m_nSelectLine = -1;
                    158: }
                    159: 
                    160: /////////////////////////////////////////////////////////////////////////////
                    161: //  The Following are CMainWindow Menu Items
                    162: 
                    163: //////////////////////////////////////////////////
                    164: //  CMainWindow::OnNew
                    165: //  After checking to see if current data needs to be stored, call
                    166: //  database New and resize/repaint the window.
                    167: //
                    168: void CMainWindow::OnNew()
                    169: {
                    170:        if ( !CheckForSave( "File New", "Save file before New?" ) )
                    171:                return;
                    172:        m_people.New();
                    173:        SetMenu();
                    174:        SetWindowText( m_people.GetTitle() );
                    175:        OnSize( 0, m_cxClient, m_cyClient );
                    176: }
                    177: 
                    178: //////////////////////////////////////////////////
                    179: //  CMainWindow::OnOpen
                    180: //
                    181: void CMainWindow::OnOpen()
                    182: {
                    183:        if ( !CheckForSave( "File Open", "Save file before Open?" ) )
                    184:                return;
                    185: 
                    186:        // Attempt to open a database file and read it.
                    187:        // If a file or archive exception occurs, catch it and
                    188:        // present an error message box.
                    189:        CString szFileName, szFileTitle;
                    190:        TRY
                    191:        {
                    192:                // Use CommDlg to get the file name and then call DoOpen.
                    193:                // Set the Window title and menus.  Resize/Repaint.
                    194:                if ( FileDlg( TRUE, SIZESTRING, szFileName.GetBuffer( SIZESTRING ),
                    195:                                SIZESTRING, szFileTitle.GetBuffer( SIZESTRING ) ) )
                    196:                {
                    197:                        szFileName.ReleaseBuffer();
                    198:                        szFileTitle.ReleaseBuffer();
                    199:                        m_people.DoOpen( szFileName );
                    200:                        m_people.SetTitle( szFileTitle );
                    201:                        SetWindowText( m_people.GetTitle() );
                    202:                        SetMenu();
                    203:                        OnSize( 0, m_cxClient, m_cyClient );
                    204:                }
                    205:        }
                    206:        CATCH( CFileException, e )
                    207:        {
                    208:                char ErrorMsg[SIZESTRING];
                    209:                sprintf( ErrorMsg,"Opening %s returned a 0x%lx.",
                    210:                                (const char*)szFileTitle, e->m_lOsError );
                    211:                MessageBox( ErrorMsg, "File Open Error" );
                    212:        }
                    213:        AND_CATCH( CArchiveException, e )
                    214:        {
                    215:                char ErrorMsg[SIZESTRING];
                    216:                sprintf( ErrorMsg,"Reading the %s archive failed.",
                    217:                                (const char*)szFileTitle );
                    218:                MessageBox( ErrorMsg, "File Open Error" );
                    219:        }
                    220:        END_CATCH
                    221: }
                    222: 
                    223: //////////////////////////////////////////////////
                    224: //  CMainWindow::OnSave
                    225: //
                    226: void CMainWindow::OnSave()
                    227: {
                    228:        Save( m_people.IsNamed() );
                    229: }
                    230: 
                    231: //////////////////////////////////////////////////
                    232: //  CMainWindow::OnSaveAs
                    233: //
                    234: void CMainWindow::OnSaveAs()
                    235: {
                    236:        Save();
                    237: }
                    238: 
                    239: //////////////////////////////////////////////////
                    240: //  CMainWindow::OnDBClose
                    241: //  Closes the current database, checking to see if it should be
                    242: //  saved first.  Reset the window title and the scroll regions.
                    243: //  Invalidating the entire screen causes OnPaint to repaint but
                    244: //  this time without any data.
                    245: //
                    246: void CMainWindow::OnDBClose()
                    247: {
                    248:        if ( !CheckForSave( "File Close", "Save file before closing?" ) )
                    249:                return;
                    250:        m_people.Terminate();
                    251:        SetWindowText( "Phone Book" );
                    252:        SetMenu();
                    253:        OnSize( 0, m_cxClient, m_cyClient );
                    254: }
                    255: 
                    256: //////////////////////////////////////////////////
                    257: //  CMainWindow::OnPrint
                    258: //  Uses the commdlg print dialog to create a printer dc
                    259: //  Then it uses code almost identical to the OnPaint code
                    260: //  to write the data to the printer.
                    261: //
                    262: void CMainWindow::OnPrint()
                    263: {
                    264: 
                    265:        PRINTDLG pd;
                    266:        
                    267:        pd.lStructSize = sizeof( PRINTDLG );
                    268:        pd.hwndOwner=m_hWnd;
                    269:        pd.hDevMode=(HANDLE)NULL;
                    270:        pd.hDevNames=(HANDLE)NULL;
                    271:        pd.Flags=PD_RETURNDC | PD_NOSELECTION | PD_NOPAGENUMS;
                    272:        pd.nFromPage=0;
                    273:        pd.nToPage=0;
                    274:        pd.nMinPage=0;
                    275:        pd.nMaxPage=0;
                    276:        pd.nCopies=1;
                    277:        pd.hInstance=(HINSTANCE)NULL;
                    278: 
                    279:        if ( PrintDlg( &pd ) != 0 )
                    280:        {
                    281:                // CommDlg returned a DC so create a CDC object from it.
                    282:                ASSERT( pd.hDC != 0 );
                    283:                CDC * dc;
                    284:                dc = CDC::FromHandle( pd.hDC );
                    285: 
                    286:                // Change to hour glass while printing
                    287:                SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT ) );
                    288: 
                    289:                // Begin printing the document.
                    290:                int rc;
                    291:                char szError[SIZESTRING];
1.1.1.2 ! root      292: 
1.1       root      293:                rc = dc->StartDoc( "Phone Book" );
1.1.1.2 ! root      294: 
1.1       root      295:                if ( rc < 0 )
                    296:                {
                    297:                        sprintf( szError, "Unable to Begin printing - Error[%d]", rc );
                    298:                        MessageBox( szError, NULL,MB_OK );
                    299:                        return;
                    300:                }
                    301:                
                    302:                int x, y;
                    303:                CPerson* pCurrent;
                    304:                int nPerson=0;
                    305:                CString szDisplay;
                    306:                int nStart, nEnd;
                    307:                
                    308:                // Get Height and Width of large character
                    309:                CSize extentChar = dc->GetTextExtent( "M", 1 );
                    310:                int nCharHeight = extentChar.cy;
                    311:                int nCharWidth = extentChar.cx;
                    312:                
                    313:                // Get Page size in # of full lines
                    314:                int nExtPage = ( dc->GetDeviceCaps(VERTRES) - nCharHeight )
                    315:                                / nCharHeight;
                    316:                
                    317:                CString szTitle;
                    318:                szTitle = CString( "Phone Book - " ) + m_people.GetName();
                    319: 
                    320:                while ( nPerson != m_people.GetCount() )
                    321:                {
                    322:                        // Print a Page Header
                    323:                        dc->StartPage();
                    324:                        dc->SetTextAlign ( TA_LEFT | TA_TOP );
                    325:                        dc->TextOut( 0, 0, szTitle, szTitle.GetLength() );
                    326:                        dc->MoveTo( 0, nCharHeight );
                    327:                        dc->LineTo( 
                    328:                                dc->GetTextExtent( szTitle, szTitle.GetLength() ).cx,
                    329:                                nCharHeight );
                    330: 
                    331:                        // Print People from start to last person or page size minus
                    332:                        // 2 ( header size )
                    333:                        nEnd = min( m_people.GetCount() - nPerson, nExtPage-2 );
                    334:                        for ( nStart = 0; nStart < nEnd; nStart++, nPerson++ )
                    335:                        {
                    336:                                x = 0;
                    337:                                y = nCharHeight * ( nStart+2 );
                    338: 
                    339:                                pCurrent = m_people.GetPerson( nPerson );
                    340:                                szDisplay = " " + pCurrent->GetLastName() + ", " +
                    341:                                                pCurrent->GetFirstName();
                    342:                                dc->SetTextAlign( TA_LEFT | TA_TOP );
                    343:                                dc->TextOut( x, y, szDisplay, szDisplay.GetLength() );
                    344: 
                    345:                                szDisplay = pCurrent->GetPhoneNumber();
                    346:                                dc->SetTextAlign( TA_RIGHT | TA_TOP );
                    347:                                dc->TextOut( x + SIZENAME * nCharWidth, y, szDisplay,
                    348:                                                szDisplay.GetLength() );
                    349: 
                    350:                                szDisplay = pCurrent->GetModTime().Format( "%m/%d/%y %H:%M" );
                    351:                                dc->TextOut( x + ( SIZENAME + SIZEPHONE ) * nCharWidth, y,
                    352:                                        szDisplay, szDisplay.GetLength() );
                    353:                        }
                    354:                        dc->EndPage();
                    355:                }
                    356:                dc->EndDoc();
                    357:                dc->DeleteDC();
                    358:                SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) );
                    359:        }
                    360: }
                    361: 
                    362: //////////////////////////////////////////////////
                    363: //  CMainWindow::OnExit
                    364: //
                    365: void CMainWindow::OnExit()
                    366: {
                    367:        OnClose();
                    368: }
                    369: 
                    370: //////////////////////////////////////////////////
                    371: //  CMainWindow::OnAdd
                    372: //  Using the EditDialog fill in a new person object.  If the user
                    373: //  selects OK then add the person, call OnSize to resize the scroll
                    374: //  region, and invalidate the screen so it will be redrawn with the
                    375: //  new person in the correct order.
                    376: //
                    377: void CMainWindow::OnAdd()
                    378: {
                    379:        CPerson* person=new CPerson();
                    380:        
                    381:        CEditDialog dlgAdd( person, this );
                    382:        if ( dlgAdd.DoModal() == IDOK )
                    383:        {
                    384:                m_people.AddPerson( person );
                    385:                OnSize( 0, m_cxClient, m_cyClient );
                    386:        }
                    387:        else
                    388:                delete person;
                    389: }
                    390: 
                    391: //////////////////////////////////////////////////
                    392: //  CMainWindow::OnDelete
                    393: //  Deletes the current selection.  Check to see if the selection is
                    394: //  now past then end of the list.  Also call OnSize since the list
                    395: //  length has now changed.
                    396: //
                    397: void CMainWindow::OnDelete()
                    398: {
                    399:        if ( m_nSelectLine == -1 )
                    400:        {
                    401:                MessageBox( "Select a person to delete first" );
                    402:                return;
                    403:        }
                    404:        m_people.DeletePerson( m_nSelectLine );
                    405:        if ( m_nSelectLine >= (int)m_people.GetCount() )
                    406:                m_nSelectLine--;
                    407:        OnSize( 0, m_cxClient, m_cyClient );
                    408: }
                    409: 
                    410: ////////////////////////////////////////////////////
                    411: //  CMainWindow::OnFind
                    412: //  Gets information from the CFindDialog modal dialog box, then searches for
                    413: //  matching people.  Note the Add and Delete menu items are disabled after
                    414: //  a find is made.  Find All is enabled.
                    415: //
                    416: void CMainWindow::OnFind()
                    417: {
                    418:        CFindDialog dlgFind( this );
                    419:        if ( dlgFind.DoModal() == IDOK &&
                    420:                        dlgFind.GetFindString().GetLength() != 0 )
                    421:        {
                    422:                if ( m_people.DoFind( dlgFind.GetFindString() ) )
                    423:                {
                    424:                        m_nSelectLine = -1;
                    425:                        CString tmp;
                    426:                        tmp = m_people.GetTitle() + " Found: "
                    427:                                        + dlgFind.GetFindString();
                    428:                        SetWindowText( tmp );
                    429:                        CMenu* pMenu = GetMenu();
                    430:                        pMenu->EnableMenuItem( IDM_FINDALL, MF_ENABLED );
                    431:                        pMenu->EnableMenuItem( IDM_FIND, MF_GRAYED );
                    432:                        pMenu->EnableMenuItem( IDM_DELETE, MF_GRAYED );
                    433:                        pMenu->EnableMenuItem( IDM_ADD, MF_GRAYED );
                    434:                        OnSize( 0, m_cxClient, m_cyClient );
                    435:                }
                    436:                else
                    437:                        MessageBox( "No match found in list." );
                    438:        }
                    439: }
                    440: 
                    441: ////////////////////////////////////////////////////
                    442: //  CMainWindow::OnFindAll
                    443: //  Returns to view the whole database.  Add, Delete are re-enabled, and
                    444: //  Find All is again disabled.  OnSize is called because the list
                    445: //  has changed length.
                    446: //
                    447: void CMainWindow::OnFindAll()
                    448: {
                    449:        m_people.DoFind();
                    450:        SetWindowText( m_people.GetTitle() );
                    451:        CMenu* pMenu = GetMenu();
                    452:        pMenu->EnableMenuItem( IDM_FINDALL, MF_GRAYED );
                    453:        pMenu->EnableMenuItem( IDM_FIND, MF_ENABLED );
                    454:        pMenu->EnableMenuItem( IDM_DELETE, MF_ENABLED );
                    455:        pMenu->EnableMenuItem( IDM_ADD, MF_ENABLED );
                    456:        OnSize( 0, m_cxClient, m_cyClient );
                    457: }
                    458: 
                    459: ////////////////////////////////////////////////////
                    460: //  CMainWindow::OnEdit
                    461: //  Using the member variable m_nSelectLine a CEditDialog is created
                    462: //  and filled with the selected person.  If the dialog OK button is
                    463: //  used the dialog saves the changes into the object.
                    464: //  over any old information.
                    465: //
                    466: void CMainWindow::OnEdit()
                    467: {
                    468:        if ( m_nSelectLine == -1 )
                    469:        {
                    470:                MessageBox( "Select a person to edit first" );
                    471:                return;
                    472:        }
                    473: 
                    474:        // Get a pointer to the person in the list.
                    475:        CPerson* pPerson = m_people.GetPerson( m_nSelectLine );
                    476:        CPerson tmpPerson = *pPerson;
                    477:        
                    478:        //Edit the data.
                    479:        CEditDialog dlgEdit( &tmpPerson, this );
                    480:        
                    481:        //if the ok button is pressed redraw the screen
                    482:        if ( dlgEdit.DoModal() == IDOK )
                    483:        {
                    484:                m_people.ReplacePerson( pPerson, tmpPerson );
                    485:                InvalidateLine();
                    486:        }
                    487: }
                    488: 
                    489: //////////////////////////////////////////////////
                    490: //  CMainWindow::OnHelp
                    491: //
                    492: void CMainWindow::OnHelp()
                    493: {
                    494:        if ( !m_people.IsPresent() )
                    495:        {
                    496:                CModalDialog dlgHelp( "NoData", this );
                    497:                dlgHelp.DoModal();
                    498:                return;
                    499:        }
                    500:        
                    501:        if ( !m_people.IsNamed() )
                    502:        {
                    503:                CModalDialog dlgHelp( "NoName", this );
                    504:                if ( dlgHelp.DoModal() == IDCANCEL )
                    505:                        return;
                    506:        }
                    507:        
                    508:        CModalDialog dlgHelp( "Enter", this );
                    509:        dlgHelp.DoModal();
                    510: }
                    511: 
                    512: //////////////////////////////////////////////////
                    513: //  CMainWindow::OnAbout
                    514: //
                    515: void CMainWindow::OnAbout()
                    516: {
                    517:        CModalDialog dlgAbout( "AboutBox", this );
                    518:        dlgAbout.DoModal();
                    519: }
                    520: 
                    521: /////////////////////////////////////////////////////////////////////////////
                    522: //  The Following are WINDOW messages
                    523: 
                    524: //////////////////////////////////////////////////
                    525: //  CMainWindow::OnCreate
                    526: //  Queries the current text metrics to determine char size.
                    527: //
                    528: int CMainWindow::OnCreate( LPCREATESTRUCT )
                    529: {
                    530:        TEXTMETRIC tm;
                    531: 
                    532:        // Get the text metrics.
                    533:        CDC* dc = GetDC();
                    534:        dc->GetTextMetrics( &tm );
                    535:        ReleaseDC( dc );
                    536: 
                    537:        // Decide the statistics on how many rows, etc., we can display.
                    538:        m_cxChar = tm.tmAveCharWidth;
                    539:        m_cxCaps = ( (tm.tmPitchAndFamily & 1 )? 3 : 2 ) * m_cxChar / 2;
                    540:        m_cyChar = tm.tmHeight + tm.tmExternalLeading;
                    541:        m_nMaxWidth = ( SIZENAME + SIZEPHONE + 1 ) * m_cxCaps;
                    542:        m_nVscrollPos = m_nHscrollPos = 0;
                    543: 
                    544:        return 0;
                    545: }
                    546: 
                    547: //////////////////////////////////////////////////
                    548: //  CMainWindow::OnClose
                    549: //  Check to see if the current file needs to be saved.  Terminate
                    550: //  the database and destory the window.
                    551: //
                    552: void CMainWindow::OnClose()
                    553: {
                    554:        if ( !CheckForSave( "File Exit", "Save file before exit?" ) )
                    555:                return;
                    556:        m_people.Terminate();
                    557:        DestroyWindow();
                    558: }
                    559: 
                    560: //////////////////////////////////////////////////
                    561: //  CMainWindow::OnSize
                    562: //  When resized, we need to recalculate our scrollbar ranges based on what
                    563: //  part of the database is visible.
                    564: //
                    565: void CMainWindow::OnSize( UINT, int x, int y )
                    566: {
                    567:        m_cxClient = x;
                    568:        m_cyClient = y;
                    569: 
                    570:        m_nVscrollMax = max( 0,
                    571:                        (int)( m_people.GetCount() ) - m_cyClient / m_cyChar );
                    572:        m_nVscrollPos = min( m_nVscrollPos, m_nVscrollMax );
                    573: 
                    574:        SetScrollRange( SB_VERT, 0, m_nVscrollMax, FALSE );
                    575:        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    576: 
                    577:        m_nHscrollMax = max( 0, ( m_nMaxWidth - m_cxClient ) / m_cxChar );
                    578:        m_nHscrollPos = min( m_nHscrollPos, m_nHscrollMax );
                    579: 
                    580:        SetScrollRange( SB_HORZ, 0, m_nHscrollMax, FALSE );
                    581:        SetScrollPos( SB_HORZ, m_nHscrollPos, TRUE );
                    582:        Invalidate( TRUE );
                    583: }
                    584: 
                    585: //////////////////////////////////////////////////
                    586: //  CMainWindow::OnVScroll
                    587: //  Translate scroll messages into Scroll increments and then
                    588: //  checks the current position to determine if scrolling is possible
                    589: //
                    590: void CMainWindow::OnVScroll( UINT wParam, UINT pos, CScrollBar* )
                    591: {
                    592:        short nScrollInc;
                    593:        
                    594:        switch ( wParam )
                    595:        {
                    596:                case SB_TOP:
                    597:                        nScrollInc = -m_nVscrollPos;
                    598:                        break;
                    599: 
                    600:                case SB_BOTTOM:
                    601:                        nScrollInc = m_nVscrollMax - m_nVscrollPos;
                    602:                        break;
                    603:                        
                    604:                case SB_LINEUP:
                    605:                        nScrollInc = -1;
                    606:                        break;
                    607: 
                    608:                case SB_LINEDOWN:
                    609:                        nScrollInc = 1;
                    610:                        break;
                    611: 
                    612:                case SB_PAGEUP:
                    613:                        nScrollInc = min( -1, -m_cyClient / m_cyChar );
                    614:                        break;
                    615: 
                    616:                case SB_PAGEDOWN:
                    617:                        nScrollInc = max( 1, m_cyClient / m_cyChar );
                    618:                        break;
                    619: 
                    620:                case SB_THUMBTRACK:
                    621:                        nScrollInc = pos - m_nVscrollPos;
                    622:                        break;
                    623: 
                    624:                default:
                    625:                        nScrollInc = 0;
                    626:        }
                    627: 
                    628:        if ( nScrollInc = max( -m_nVscrollPos,
                    629:                        min( nScrollInc, m_nVscrollMax - m_nVscrollPos ) ) )
                    630:        {
                    631:                m_nVscrollPos += nScrollInc;
                    632:                ScrollWindow( 0, -m_cyChar * nScrollInc );
                    633:                SetScrollPos( SB_VERT, m_nVscrollPos );
                    634:                UpdateWindow();
                    635:        }
                    636: }
                    637: 
                    638: //////////////////////////////////////////////////
                    639: //  CMainWindow::OnHScroll
                    640: //  Translate scroll messages into Scroll increments and then
                    641: //  checks the current position to determine if scrolling is possible
                    642: //
                    643: void CMainWindow::OnHScroll( UINT wParam, UINT pos, CScrollBar* )
                    644: {
                    645:        int nScrollInc;
                    646:        switch ( wParam )
                    647:        {
                    648:                case SB_LINEUP:
                    649:                        nScrollInc = -1;
                    650:                        break;
                    651: 
                    652:                case SB_LINEDOWN:
                    653:                        nScrollInc = 1;
                    654:                        break;
                    655: 
                    656:                case SB_PAGEUP:
                    657:                        nScrollInc = -PAGESIZE;
                    658:                        break;
                    659: 
                    660:                case SB_PAGEDOWN:
                    661:                        nScrollInc = PAGESIZE;
                    662:                        break;
                    663: 
                    664:                case SB_THUMBPOSITION:
                    665:                        nScrollInc = pos - m_nHscrollPos;
                    666:                        break;
                    667: 
                    668:                default:
                    669:                        nScrollInc = 0;
                    670:        }
                    671: 
                    672:        if ( nScrollInc = max( -m_nHscrollPos,
                    673:                         min( nScrollInc, m_nHscrollMax - m_nHscrollPos ) ) )
                    674:        {
                    675:                m_nHscrollPos += nScrollInc;
                    676:                ScrollWindow( -m_cxChar * nScrollInc, 0 );
                    677:                SetScrollPos( SB_HORZ, m_nHscrollPos );
                    678:                UpdateWindow();
                    679:        }
                    680: }
                    681: 
                    682: //////////////////////////////////////////////////
                    683: //  CMainWindow::OnUp
                    684: //  Uses Accelerator tables to link the up arrow key to this
                    685: //  routine.  Decrements the select line with checking for scrolling
                    686: //  and wrapping off the top of the list.
                    687: //
                    688: //
                    689: void CMainWindow::OnUp()
                    690: {
                    691:        InvalidateLine();
                    692:        
                    693:        if ( m_nSelectLine <= 0 )
                    694:        {
                    695:                m_nSelectLine = m_people.GetCount() - 1;
                    696:                m_nVscrollPos = max( 0, m_nSelectLine + 1 - ( m_cyClient / m_cyChar ) );
                    697:                Invalidate( TRUE );
                    698:        }
                    699:        else
                    700:        {
                    701:                m_nSelectLine--;
                    702:                if ( m_nSelectLine - m_nVscrollPos < 0 )
                    703:                        OnVScroll( SB_LINEUP, 0, NULL );
                    704:                
                    705:                // Selection is off the screen
                    706:                if ( m_nSelectLine - m_nVscrollPos > ( m_cyClient / m_cyChar ) )
                    707:                {
                    708:                        m_nVscrollPos = m_nSelectLine + 1 - ( m_cyClient / m_cyChar );
                    709:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    710:                        Invalidate( TRUE );
                    711:                }
                    712:                if ( m_nSelectLine - m_nVscrollPos < 0 )
                    713:                {
                    714:                        m_nVscrollPos = m_nSelectLine;
                    715:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    716:                        Invalidate( TRUE );
                    717:                }
                    718:        }
                    719:        
                    720:        InvalidateLine();
                    721: }
                    722: 
                    723: //////////////////////////////////////////////////
                    724: //  CMainWindow::OnDown
                    725: //  Uses Accelerator tables to link the down arrow key to this
                    726: //  routine.  Inc the select line with checking for scrolling
                    727: //  and wrapping off the bottom of the list.
                    728: //
                    729: void CMainWindow::OnDown()
                    730: {
                    731:        InvalidateLine();
                    732:        
                    733:        if ( m_nSelectLine == (int)( m_people.GetCount() - 1 )
                    734:                        || m_nSelectLine == -1 )
                    735:        {
                    736:                m_nSelectLine = 0;
                    737:                m_nVscrollPos = 0;
                    738:                Invalidate( TRUE );
                    739:        }
                    740:        else
                    741:        {
                    742:                m_nSelectLine++;
                    743:                if ( ( m_nSelectLine - m_nVscrollPos + 1 ) > ( m_cyClient / m_cyChar ) )
                    744:                        OnVScroll( SB_LINEDOWN, 0, NULL );
                    745:                
                    746:                // Selection is off the screen
                    747:                if ( ( m_nSelectLine - m_nVscrollPos ) > ( m_cyClient / m_cyChar ) )
                    748:                {
                    749:                        m_nVscrollPos = m_nSelectLine + 1 - ( m_cyClient / m_cyChar );
                    750:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    751:                        Invalidate( TRUE );
                    752:                }
                    753:                if ( ( m_nSelectLine - m_nVscrollPos ) < 0 )
                    754:                {
                    755:                        m_nVscrollPos = m_nSelectLine;
                    756:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    757:                        Invalidate( TRUE );
                    758:                }
                    759:        }
                    760: 
                    761:        InvalidateLine();
                    762: }
                    763: 
                    764: //////////////////////////////////////////////////
                    765: //  CMainWindow::OnLButtonDown
                    766: //  Turns the location of the mouse pointer into a line number
                    767: //  and stores that information in m_nSelectLine.  Uses
                    768: //  InvalidateLine to cause OnPaint to change the screen.
                    769: //
                    770: void CMainWindow::OnLButtonDown( UINT, CPoint location )
                    771: {
                    772:        InvalidateLine();
                    773:        
                    774:        int pos = m_nVscrollPos + location.y / m_cyChar;
                    775:        
                    776:        if ( ( m_nSelectLine != pos )  && ( pos < (int)m_people.GetCount() ) )
                    777:        {
                    778:                m_nSelectLine = pos;
                    779:                InvalidateLine();
                    780:        }
                    781:        else
                    782:                m_nSelectLine = -1;
                    783: }
                    784: 
                    785: //////////////////////////////////////////////////
                    786: //  CMainWindow::OnLButtonDblClk
                    787: //  Translates mouse left button double click into edit person.
                    788: //
                    789: void CMainWindow::OnLButtonDblClk( UINT wParam, CPoint location )
                    790: {
                    791:        if ( m_nSelectLine == -1 )
                    792:                OnLButtonDown( wParam, location );
                    793:        OnEdit();
                    794: }
                    795: 
                    796: //////////////////////////////////////////////////
                    797: //  CMainWindow::OnKeyDown
                    798: //  Translates keyboard input into scroll messages
                    799: //
                    800: void CMainWindow::OnKeyDown( UINT wParam, UINT, UINT )
                    801: {
                    802:        switch ( wParam )
                    803:        {
                    804:                case VK_HOME:
                    805:                        OnVScroll( SB_TOP, 0, NULL );
                    806:                        break;
                    807:                case VK_END:
                    808:                        OnVScroll( SB_BOTTOM, 0, NULL );
                    809:                        break;
                    810:                case VK_PRIOR:
                    811:                        OnVScroll( SB_PAGEUP, 0, NULL );
                    812:                        break;
                    813:                case VK_NEXT:
                    814:                        OnVScroll( SB_PAGEDOWN, 0, NULL );
                    815:                        break;
                    816:                case VK_LEFT:
                    817:                        OnHScroll( SB_PAGEUP, 0, NULL );
                    818:                        break;
                    819:                case VK_RIGHT:
                    820:                        OnHScroll( SB_PAGEDOWN, 0, NULL );
                    821:                        break;
                    822:        }
                    823: }
                    824: 
                    825: //////////////////////////////////////////////////
                    826: //  CMainWindow::OnPaint
                    827: //  This routine does all the painting for the screen.
                    828: //
                    829: void CMainWindow::OnPaint()
                    830: {
                    831:        
                    832:        CPaintDC dc( this );
                    833: 
                    834:        // Set the Text and background colors for the DC also create a Brush
                    835:        CBrush bBack;
                    836:        dc.SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
                    837:        dc.SetBkColor( GetSysColor( COLOR_WINDOW ) );
                    838:        bBack.CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
                    839: 
                    840:        // Compute the lines that need to be redrawn
                    841:        int nStart = max( 0, m_nVscrollPos + dc.m_ps.rcPaint.top / m_cyChar - 1 );
                    842:        int nEnd = min( (int)m_people.GetCount(),
                    843:                                m_nVscrollPos + ( dc.m_ps.rcPaint.bottom / m_cyChar+1 ) );
                    844: 
                    845:        // Create a rect the width of the display.
                    846:        CRect area( 0, 0, m_cxClient, 0 );
                    847:        
                    848:        CString szDisplay;
                    849:        CPerson* pCurrent;
                    850:        int x,y;
                    851:        for ( ;nStart < nEnd; nStart++ )
                    852:        {
                    853:                // if the current line is the select line then change the
                    854:                // colors to the highlight text colors.
                    855:                if ( m_nSelectLine == nStart )
                    856:                {
                    857:                        bBack.DeleteObject();
                    858:                        bBack.CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) );
                    859:                        dc.SetTextColor( GetSysColor( COLOR_HIGHLIGHTTEXT ) );
                    860:                        dc.SetBkColor( GetSysColor( COLOR_HIGHLIGHT ) );
                    861:                }
                    862: 
                    863:                // x is the number of characters horz scrolled * the width of
                    864:                // char.  y is the current line no. - number of lines scrolled
                    865:                // times the height of a line.
                    866:                x = m_cxChar * ( -m_nHscrollPos );
                    867:                y = m_cyChar * ( nStart - m_nVscrollPos );
                    868: 
                    869:                // Set the rect to y and y + the height of the line.  Fill the
                    870:                // rect with the background color.
                    871:                area.top = y;
                    872:                area.bottom = y+ m_cyChar;
                    873:                dc.FillRect( area, &bBack );
                    874: 
                    875:                // Get the person and build a string with his name.
                    876:                pCurrent = m_people.GetPerson( nStart );
                    877:                szDisplay = " " + pCurrent->GetLastName() + ", " +
                    878:                                pCurrent->GetFirstName();
                    879: 
                    880:                // Set the dc to write using the point as the left top of the
                    881:                // character.  Write the name.
                    882:                dc.SetTextAlign( TA_LEFT | TA_TOP );
                    883:                dc.TextOut ( x, y,szDisplay, szDisplay.GetLength() );
                    884: 
                    885:                // Write the phone number right aligned.
                    886:                szDisplay = pCurrent->GetPhoneNumber();
                    887:                dc.SetTextAlign ( TA_RIGHT | TA_TOP );
                    888:                dc.TextOut ( x + SIZENAME * m_cxCaps, y, szDisplay,
                    889:                        szDisplay.GetLength() );
                    890: 
                    891:                // Write the time.
                    892:                szDisplay = pCurrent->GetModTime().Format( "%m/%d/%y %H:%M" );
                    893:                dc.TextOut ( x + ( SIZENAME + SIZEPHONE ) * m_cxCaps, y,
                    894:                        szDisplay, szDisplay.GetLength() );
                    895: 
                    896:                // If this is the select line then we need to reset the dc
                    897:                // colors back to the original colors.
                    898:                if ( m_nSelectLine == nStart )
                    899:                {
                    900:                        bBack.DeleteObject();
                    901:                        bBack.CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
                    902:                        dc.SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
                    903:                        dc.SetBkColor( GetSysColor( COLOR_WINDOW ) );
                    904:                }
                    905:        }
                    906: }
                    907: 
                    908: /////////////////////////////////////////////////////////////////////////////
                    909: //  The following are utility routines
                    910: 
                    911: 
                    912: //////////////////////////////////////////////////
                    913: //  CMainWindow::FileDlg
                    914: //  Call the commdlg routine to display File Open or File Save As
                    915: //  dialogs.  The setup is the same for either.  If bOpen is TRUE
                    916: //  then File Open is display otherwise File Save As is displayed.
                    917: //  The File Name and File Title are stored at the string pointer
                    918: //  passed in.
                    919: //
                    920: BOOL CMainWindow::FileDlg( BOOL bOpen, int nMaxFile, LPSTR szFile,
                    921:                int nMaxFileTitle, LPSTR szFileTitle )
                    922: {
                    923:        
                    924:        OPENFILENAME of;
                    925: 
                    926:        char szDirName[SIZESTRING];
                    927:        char szFilter[] = "Phone Book Files (*.pb)\0"
                    928:                "*.pb\0"
                    929:                "\0";
                    930: 
                    931:        szDirName[0] = '.';
                    932: 
                    933:        of.lStructSize = sizeof( OPENFILENAME );
                    934:        of.hwndOwner = m_hWnd;
                    935:        of.lpstrFilter = szFilter;
                    936:        of.lpstrCustomFilter = NULL;
                    937:        of.nMaxCustFilter = 0L;
                    938:        of.nFilterIndex = 1L;
                    939:        of.lpstrFile=szFile;
                    940:        of.nMaxFile=nMaxFile;
                    941:        of.lpstrFileTitle = szFileTitle;
                    942:        of.nMaxFileTitle = nMaxFileTitle;
                    943:        of.lpstrInitialDir = szDirName;
                    944:        of.lpstrTitle = NULL;
                    945:        of.nFileOffset = 0;
                    946:        of.nFileExtension = 0;
                    947:        of.lpstrDefExt = "pb";
                    948:        if ( bOpen )
                    949:        {
                    950:                of.Flags = OFN_HIDEREADONLY;
                    951:                return GetOpenFileName( &of );
                    952:        }
                    953:        else
                    954:        {
                    955:                of.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
                    956:                return GetSaveFileName( &of );
                    957:        }
                    958: }
                    959: 
                    960: //////////////////////////////////////////////////
                    961: //  CMainWindow::Save
                    962: //  Handles any time a file needs to be saved to the disk.
                    963: //  Passing in FALSE for name brings up the file save as dialog
                    964: //  whether or not the database had a name before.
                    965: //
                    966: BOOL CMainWindow::Save( BOOL bIsNamed /* = FALSE */ )
                    967: {
                    968:        CString szFileName, szFileTitle;
                    969:        TRY
                    970:        {
                    971:                if ( bIsNamed )
                    972:                        m_people.DoSave();
                    973:                else
                    974:                {
                    975:                        szFileName = m_people.GetName();
                    976:                        if ( FileDlg( FALSE, SIZESTRING,
                    977:                                        szFileName.GetBuffer( SIZESTRING ), SIZESTRING,
                    978:                                        szFileTitle.GetBuffer( SIZESTRING ) ) )
                    979:                        {
                    980:                                szFileName.ReleaseBuffer();
                    981:                                m_people.DoSave( szFileName );
                    982:                                m_people.SetTitle( szFileTitle );
                    983:                                SetWindowText( m_people.GetTitle() );
                    984:                        }
                    985:                        else
                    986:                                return FALSE;
                    987:                }
                    988:        }
                    989:        CATCH( CFileException, e )
                    990:        {
                    991:                char ErrorMsg[SIZESTRING];
                    992:                sprintf( ErrorMsg,"Saving %s returned a 0x%lx.",
                    993:                                (const char*)szFileTitle, e->m_lOsError );
                    994:                MessageBox( ErrorMsg, "File Open Error" );
                    995:        }
                    996:        AND_CATCH( CArchiveException, e )
                    997:        {
                    998:                char ErrorMsg[SIZESTRING];
                    999:                sprintf( ErrorMsg,"Reading the %s archive failed.",
                   1000:                                (const char*)szFileTitle );
                   1001:                MessageBox( ErrorMsg, "File Open Error" );
                   1002:        }
                   1003:        END_CATCH
                   1004:        return TRUE;
                   1005: }
                   1006: 
                   1007: //////////////////////////////////////////////////
                   1008: //  CMainWindow::CheckForSave
                   1009: //  Whenever a new file is opened this routine will determine if
                   1010: //  there are unsaved changes in the current database.  If so it
                   1011: //  will query the user and determine save or not as appropriate.
                   1012: //
                   1013: BOOL CMainWindow::CheckForSave( const char* pszTitle, const char* pszMessage )
                   1014: {
                   1015:        if ( m_people.IsDirty() )
                   1016:        {
                   1017:                UINT nButton = MessageBox( pszMessage, pszTitle, MB_YESNOCANCEL );
                   1018:                if ( nButton == IDYES )
                   1019:                {
                   1020:                        if ( !Save( m_people.IsNamed() ) )
                   1021:                                return FALSE;
                   1022:                }
                   1023:                else if ( nButton == IDCANCEL )
                   1024:                        return FALSE;
                   1025:        }
                   1026:        return TRUE;
                   1027: }
                   1028: 
                   1029: 
                   1030: //////////////////////////////////////////////////
                   1031: //  CMainWindow::SetMenu
                   1032: //  Whenever the existance of the DataBase is changed this
                   1033: //  routine will reset the menus so only the possible commands
                   1034: //  are accessible.
                   1035: //
                   1036: void CMainWindow::SetMenu()
                   1037: {
                   1038:        CMenu* pMenu = GetMenu();
                   1039:        if ( m_people.IsPresent() )
                   1040:        {
                   1041:                if ( m_people.IsNamed() )
                   1042:                        pMenu->EnableMenuItem( IDM_SAVE, MF_ENABLED );
                   1043:                else
                   1044:                        pMenu->EnableMenuItem( IDM_SAVE, MF_GRAYED );
                   1045:                pMenu->EnableMenuItem( IDM_SAVEAS, MF_ENABLED );
                   1046:                pMenu->EnableMenuItem( IDM_CLOSE, MF_ENABLED );
                   1047:                pMenu->EnableMenuItem( IDM_PRINT, MF_ENABLED );
                   1048:                pMenu->EnableMenuItem( IDM_ADD, MF_ENABLED );
                   1049:                pMenu->EnableMenuItem( IDM_DELETE, MF_ENABLED );
                   1050:                pMenu->EnableMenuItem( IDM_FIND, MF_ENABLED );
                   1051:                pMenu->EnableMenuItem( IDM_EDIT, MF_ENABLED );
                   1052:        }
                   1053:        else
                   1054:        {
                   1055:                pMenu->EnableMenuItem( IDM_SAVE, MF_GRAYED );
                   1056:                pMenu->EnableMenuItem( IDM_SAVEAS, MF_GRAYED );
                   1057:                pMenu->EnableMenuItem( IDM_CLOSE, MF_GRAYED );
                   1058:                pMenu->EnableMenuItem( IDM_PRINT, MF_GRAYED );
                   1059:                pMenu->EnableMenuItem( IDM_ADD, MF_GRAYED );
                   1060:                pMenu->EnableMenuItem( IDM_DELETE, MF_GRAYED );
                   1061:                pMenu->EnableMenuItem( IDM_FIND, MF_GRAYED );
                   1062:                pMenu->EnableMenuItem( IDM_FINDALL, MF_GRAYED );
                   1063:                pMenu->EnableMenuItem( IDM_EDIT, MF_GRAYED );
                   1064:        }
                   1065: }
                   1066: 
                   1067: //////////////////////////////////////////////////
                   1068: //  CMainWindow::InvalidateLine
                   1069: //  Marks the screen area of the currently selected person as
                   1070: //  invalid causing windows to call OnPaint to redraw the area.
                   1071: //  This is normally used when the selected line is being changed.
                   1072: //
                   1073: void CMainWindow::InvalidateLine()
                   1074: {
                   1075:        CRect area( 0, ( m_nSelectLine - m_nVscrollPos ) * m_cyChar, m_cxClient,
                   1076:                                ( m_nSelectLine + 1 - m_nVscrollPos ) * m_cyChar );
                   1077:        InvalidateRect( area );
                   1078: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.