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

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];
                    292: #ifndef _NTWIN
                    293:                rc = dc->StartDoc( "Phone Book" );
                    294: #else
                    295:                DOCINFO di;
                    296:                di.cbSize = sizeof(di);
                    297:                di.lpszDocName = "Phone Book";
                    298:                di.lpszOutput = NULL;
                    299:                rc = dc->StartDoc(&di);
                    300: #endif
                    301:                if ( rc < 0 )
                    302:                {
                    303:                        sprintf( szError, "Unable to Begin printing - Error[%d]", rc );
                    304:                        MessageBox( szError, NULL,MB_OK );
                    305:                        return;
                    306:                }
                    307:                
                    308:                int x, y;
                    309:                CPerson* pCurrent;
                    310:                int nPerson=0;
                    311:                CString szDisplay;
                    312:                int nStart, nEnd;
                    313:                
                    314:                // Get Height and Width of large character
                    315:                CSize extentChar = dc->GetTextExtent( "M", 1 );
                    316:                int nCharHeight = extentChar.cy;
                    317:                int nCharWidth = extentChar.cx;
                    318:                
                    319:                // Get Page size in # of full lines
                    320:                int nExtPage = ( dc->GetDeviceCaps(VERTRES) - nCharHeight )
                    321:                                / nCharHeight;
                    322:                
                    323:                CString szTitle;
                    324:                szTitle = CString( "Phone Book - " ) + m_people.GetName();
                    325: 
                    326:                while ( nPerson != m_people.GetCount() )
                    327:                {
                    328:                        // Print a Page Header
                    329:                        dc->StartPage();
                    330:                        dc->SetTextAlign ( TA_LEFT | TA_TOP );
                    331:                        dc->TextOut( 0, 0, szTitle, szTitle.GetLength() );
                    332:                        dc->MoveTo( 0, nCharHeight );
                    333:                        dc->LineTo( 
                    334:                                dc->GetTextExtent( szTitle, szTitle.GetLength() ).cx,
                    335:                                nCharHeight );
                    336: 
                    337:                        // Print People from start to last person or page size minus
                    338:                        // 2 ( header size )
                    339:                        nEnd = min( m_people.GetCount() - nPerson, nExtPage-2 );
                    340:                        for ( nStart = 0; nStart < nEnd; nStart++, nPerson++ )
                    341:                        {
                    342:                                x = 0;
                    343:                                y = nCharHeight * ( nStart+2 );
                    344: 
                    345:                                pCurrent = m_people.GetPerson( nPerson );
                    346:                                szDisplay = " " + pCurrent->GetLastName() + ", " +
                    347:                                                pCurrent->GetFirstName();
                    348:                                dc->SetTextAlign( TA_LEFT | TA_TOP );
                    349:                                dc->TextOut( x, y, szDisplay, szDisplay.GetLength() );
                    350: 
                    351:                                szDisplay = pCurrent->GetPhoneNumber();
                    352:                                dc->SetTextAlign( TA_RIGHT | TA_TOP );
                    353:                                dc->TextOut( x + SIZENAME * nCharWidth, y, szDisplay,
                    354:                                                szDisplay.GetLength() );
                    355: 
                    356:                                szDisplay = pCurrent->GetModTime().Format( "%m/%d/%y %H:%M" );
                    357:                                dc->TextOut( x + ( SIZENAME + SIZEPHONE ) * nCharWidth, y,
                    358:                                        szDisplay, szDisplay.GetLength() );
                    359:                        }
                    360:                        dc->EndPage();
                    361:                }
                    362:                dc->EndDoc();
                    363:                dc->DeleteDC();
                    364:                SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) );
                    365:        }
                    366: }
                    367: 
                    368: //////////////////////////////////////////////////
                    369: //  CMainWindow::OnExit
                    370: //
                    371: void CMainWindow::OnExit()
                    372: {
                    373:        OnClose();
                    374: }
                    375: 
                    376: //////////////////////////////////////////////////
                    377: //  CMainWindow::OnAdd
                    378: //  Using the EditDialog fill in a new person object.  If the user
                    379: //  selects OK then add the person, call OnSize to resize the scroll
                    380: //  region, and invalidate the screen so it will be redrawn with the
                    381: //  new person in the correct order.
                    382: //
                    383: void CMainWindow::OnAdd()
                    384: {
                    385:        CPerson* person=new CPerson();
                    386:        
                    387:        CEditDialog dlgAdd( person, this );
                    388:        if ( dlgAdd.DoModal() == IDOK )
                    389:        {
                    390:                m_people.AddPerson( person );
                    391:                OnSize( 0, m_cxClient, m_cyClient );
                    392:        }
                    393:        else
                    394:                delete person;
                    395: }
                    396: 
                    397: //////////////////////////////////////////////////
                    398: //  CMainWindow::OnDelete
                    399: //  Deletes the current selection.  Check to see if the selection is
                    400: //  now past then end of the list.  Also call OnSize since the list
                    401: //  length has now changed.
                    402: //
                    403: void CMainWindow::OnDelete()
                    404: {
                    405:        if ( m_nSelectLine == -1 )
                    406:        {
                    407:                MessageBox( "Select a person to delete first" );
                    408:                return;
                    409:        }
                    410:        m_people.DeletePerson( m_nSelectLine );
                    411:        if ( m_nSelectLine >= (int)m_people.GetCount() )
                    412:                m_nSelectLine--;
                    413:        OnSize( 0, m_cxClient, m_cyClient );
                    414: }
                    415: 
                    416: ////////////////////////////////////////////////////
                    417: //  CMainWindow::OnFind
                    418: //  Gets information from the CFindDialog modal dialog box, then searches for
                    419: //  matching people.  Note the Add and Delete menu items are disabled after
                    420: //  a find is made.  Find All is enabled.
                    421: //
                    422: void CMainWindow::OnFind()
                    423: {
                    424:        CFindDialog dlgFind( this );
                    425:        if ( dlgFind.DoModal() == IDOK &&
                    426:                        dlgFind.GetFindString().GetLength() != 0 )
                    427:        {
                    428:                if ( m_people.DoFind( dlgFind.GetFindString() ) )
                    429:                {
                    430:                        m_nSelectLine = -1;
                    431:                        CString tmp;
                    432:                        tmp = m_people.GetTitle() + " Found: "
                    433:                                        + dlgFind.GetFindString();
                    434:                        SetWindowText( tmp );
                    435:                        CMenu* pMenu = GetMenu();
                    436:                        pMenu->EnableMenuItem( IDM_FINDALL, MF_ENABLED );
                    437:                        pMenu->EnableMenuItem( IDM_FIND, MF_GRAYED );
                    438:                        pMenu->EnableMenuItem( IDM_DELETE, MF_GRAYED );
                    439:                        pMenu->EnableMenuItem( IDM_ADD, MF_GRAYED );
                    440:                        OnSize( 0, m_cxClient, m_cyClient );
                    441:                }
                    442:                else
                    443:                        MessageBox( "No match found in list." );
                    444:        }
                    445: }
                    446: 
                    447: ////////////////////////////////////////////////////
                    448: //  CMainWindow::OnFindAll
                    449: //  Returns to view the whole database.  Add, Delete are re-enabled, and
                    450: //  Find All is again disabled.  OnSize is called because the list
                    451: //  has changed length.
                    452: //
                    453: void CMainWindow::OnFindAll()
                    454: {
                    455:        m_people.DoFind();
                    456:        SetWindowText( m_people.GetTitle() );
                    457:        CMenu* pMenu = GetMenu();
                    458:        pMenu->EnableMenuItem( IDM_FINDALL, MF_GRAYED );
                    459:        pMenu->EnableMenuItem( IDM_FIND, MF_ENABLED );
                    460:        pMenu->EnableMenuItem( IDM_DELETE, MF_ENABLED );
                    461:        pMenu->EnableMenuItem( IDM_ADD, MF_ENABLED );
                    462:        OnSize( 0, m_cxClient, m_cyClient );
                    463: }
                    464: 
                    465: ////////////////////////////////////////////////////
                    466: //  CMainWindow::OnEdit
                    467: //  Using the member variable m_nSelectLine a CEditDialog is created
                    468: //  and filled with the selected person.  If the dialog OK button is
                    469: //  used the dialog saves the changes into the object.
                    470: //  over any old information.
                    471: //
                    472: void CMainWindow::OnEdit()
                    473: {
                    474:        if ( m_nSelectLine == -1 )
                    475:        {
                    476:                MessageBox( "Select a person to edit first" );
                    477:                return;
                    478:        }
                    479: 
                    480:        // Get a pointer to the person in the list.
                    481:        CPerson* pPerson = m_people.GetPerson( m_nSelectLine );
                    482:        CPerson tmpPerson = *pPerson;
                    483:        
                    484:        //Edit the data.
                    485:        CEditDialog dlgEdit( &tmpPerson, this );
                    486:        
                    487:        //if the ok button is pressed redraw the screen
                    488:        if ( dlgEdit.DoModal() == IDOK )
                    489:        {
                    490:                m_people.ReplacePerson( pPerson, tmpPerson );
                    491:                InvalidateLine();
                    492:        }
                    493: }
                    494: 
                    495: //////////////////////////////////////////////////
                    496: //  CMainWindow::OnHelp
                    497: //
                    498: void CMainWindow::OnHelp()
                    499: {
                    500:        if ( !m_people.IsPresent() )
                    501:        {
                    502:                CModalDialog dlgHelp( "NoData", this );
                    503:                dlgHelp.DoModal();
                    504:                return;
                    505:        }
                    506:        
                    507:        if ( !m_people.IsNamed() )
                    508:        {
                    509:                CModalDialog dlgHelp( "NoName", this );
                    510:                if ( dlgHelp.DoModal() == IDCANCEL )
                    511:                        return;
                    512:        }
                    513:        
                    514:        CModalDialog dlgHelp( "Enter", this );
                    515:        dlgHelp.DoModal();
                    516: }
                    517: 
                    518: //////////////////////////////////////////////////
                    519: //  CMainWindow::OnAbout
                    520: //
                    521: void CMainWindow::OnAbout()
                    522: {
                    523:        CModalDialog dlgAbout( "AboutBox", this );
                    524:        dlgAbout.DoModal();
                    525: }
                    526: 
                    527: /////////////////////////////////////////////////////////////////////////////
                    528: //  The Following are WINDOW messages
                    529: 
                    530: //////////////////////////////////////////////////
                    531: //  CMainWindow::OnCreate
                    532: //  Queries the current text metrics to determine char size.
                    533: //
                    534: int CMainWindow::OnCreate( LPCREATESTRUCT )
                    535: {
                    536:        TEXTMETRIC tm;
                    537: 
                    538:        // Get the text metrics.
                    539:        CDC* dc = GetDC();
                    540:        dc->GetTextMetrics( &tm );
                    541:        ReleaseDC( dc );
                    542: 
                    543:        // Decide the statistics on how many rows, etc., we can display.
                    544:        m_cxChar = tm.tmAveCharWidth;
                    545:        m_cxCaps = ( (tm.tmPitchAndFamily & 1 )? 3 : 2 ) * m_cxChar / 2;
                    546:        m_cyChar = tm.tmHeight + tm.tmExternalLeading;
                    547:        m_nMaxWidth = ( SIZENAME + SIZEPHONE + 1 ) * m_cxCaps;
                    548:        m_nVscrollPos = m_nHscrollPos = 0;
                    549: 
                    550:        return 0;
                    551: }
                    552: 
                    553: //////////////////////////////////////////////////
                    554: //  CMainWindow::OnClose
                    555: //  Check to see if the current file needs to be saved.  Terminate
                    556: //  the database and destory the window.
                    557: //
                    558: void CMainWindow::OnClose()
                    559: {
                    560:        if ( !CheckForSave( "File Exit", "Save file before exit?" ) )
                    561:                return;
                    562:        m_people.Terminate();
                    563:        DestroyWindow();
                    564: }
                    565: 
                    566: //////////////////////////////////////////////////
                    567: //  CMainWindow::OnSize
                    568: //  When resized, we need to recalculate our scrollbar ranges based on what
                    569: //  part of the database is visible.
                    570: //
                    571: void CMainWindow::OnSize( UINT, int x, int y )
                    572: {
                    573:        m_cxClient = x;
                    574:        m_cyClient = y;
                    575: 
                    576:        m_nVscrollMax = max( 0,
                    577:                        (int)( m_people.GetCount() ) - m_cyClient / m_cyChar );
                    578:        m_nVscrollPos = min( m_nVscrollPos, m_nVscrollMax );
                    579: 
                    580:        SetScrollRange( SB_VERT, 0, m_nVscrollMax, FALSE );
                    581:        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    582: 
                    583:        m_nHscrollMax = max( 0, ( m_nMaxWidth - m_cxClient ) / m_cxChar );
                    584:        m_nHscrollPos = min( m_nHscrollPos, m_nHscrollMax );
                    585: 
                    586:        SetScrollRange( SB_HORZ, 0, m_nHscrollMax, FALSE );
                    587:        SetScrollPos( SB_HORZ, m_nHscrollPos, TRUE );
                    588:        Invalidate( TRUE );
                    589: }
                    590: 
                    591: //////////////////////////////////////////////////
                    592: //  CMainWindow::OnVScroll
                    593: //  Translate scroll messages into Scroll increments and then
                    594: //  checks the current position to determine if scrolling is possible
                    595: //
                    596: void CMainWindow::OnVScroll( UINT wParam, UINT pos, CScrollBar* )
                    597: {
                    598:        short nScrollInc;
                    599:        
                    600:        switch ( wParam )
                    601:        {
                    602:                case SB_TOP:
                    603:                        nScrollInc = -m_nVscrollPos;
                    604:                        break;
                    605: 
                    606:                case SB_BOTTOM:
                    607:                        nScrollInc = m_nVscrollMax - m_nVscrollPos;
                    608:                        break;
                    609:                        
                    610:                case SB_LINEUP:
                    611:                        nScrollInc = -1;
                    612:                        break;
                    613: 
                    614:                case SB_LINEDOWN:
                    615:                        nScrollInc = 1;
                    616:                        break;
                    617: 
                    618:                case SB_PAGEUP:
                    619:                        nScrollInc = min( -1, -m_cyClient / m_cyChar );
                    620:                        break;
                    621: 
                    622:                case SB_PAGEDOWN:
                    623:                        nScrollInc = max( 1, m_cyClient / m_cyChar );
                    624:                        break;
                    625: 
                    626:                case SB_THUMBTRACK:
                    627:                        nScrollInc = pos - m_nVscrollPos;
                    628:                        break;
                    629: 
                    630:                default:
                    631:                        nScrollInc = 0;
                    632:        }
                    633: 
                    634:        if ( nScrollInc = max( -m_nVscrollPos,
                    635:                        min( nScrollInc, m_nVscrollMax - m_nVscrollPos ) ) )
                    636:        {
                    637:                m_nVscrollPos += nScrollInc;
                    638:                ScrollWindow( 0, -m_cyChar * nScrollInc );
                    639:                SetScrollPos( SB_VERT, m_nVscrollPos );
                    640:                UpdateWindow();
                    641:        }
                    642: }
                    643: 
                    644: //////////////////////////////////////////////////
                    645: //  CMainWindow::OnHScroll
                    646: //  Translate scroll messages into Scroll increments and then
                    647: //  checks the current position to determine if scrolling is possible
                    648: //
                    649: void CMainWindow::OnHScroll( UINT wParam, UINT pos, CScrollBar* )
                    650: {
                    651:        int nScrollInc;
                    652:        switch ( wParam )
                    653:        {
                    654:                case SB_LINEUP:
                    655:                        nScrollInc = -1;
                    656:                        break;
                    657: 
                    658:                case SB_LINEDOWN:
                    659:                        nScrollInc = 1;
                    660:                        break;
                    661: 
                    662:                case SB_PAGEUP:
                    663:                        nScrollInc = -PAGESIZE;
                    664:                        break;
                    665: 
                    666:                case SB_PAGEDOWN:
                    667:                        nScrollInc = PAGESIZE;
                    668:                        break;
                    669: 
                    670:                case SB_THUMBPOSITION:
                    671:                        nScrollInc = pos - m_nHscrollPos;
                    672:                        break;
                    673: 
                    674:                default:
                    675:                        nScrollInc = 0;
                    676:        }
                    677: 
                    678:        if ( nScrollInc = max( -m_nHscrollPos,
                    679:                         min( nScrollInc, m_nHscrollMax - m_nHscrollPos ) ) )
                    680:        {
                    681:                m_nHscrollPos += nScrollInc;
                    682:                ScrollWindow( -m_cxChar * nScrollInc, 0 );
                    683:                SetScrollPos( SB_HORZ, m_nHscrollPos );
                    684:                UpdateWindow();
                    685:        }
                    686: }
                    687: 
                    688: //////////////////////////////////////////////////
                    689: //  CMainWindow::OnUp
                    690: //  Uses Accelerator tables to link the up arrow key to this
                    691: //  routine.  Decrements the select line with checking for scrolling
                    692: //  and wrapping off the top of the list.
                    693: //
                    694: //
                    695: void CMainWindow::OnUp()
                    696: {
                    697:        InvalidateLine();
                    698:        
                    699:        if ( m_nSelectLine <= 0 )
                    700:        {
                    701:                m_nSelectLine = m_people.GetCount() - 1;
                    702:                m_nVscrollPos = max( 0, m_nSelectLine + 1 - ( m_cyClient / m_cyChar ) );
                    703:                Invalidate( TRUE );
                    704:        }
                    705:        else
                    706:        {
                    707:                m_nSelectLine--;
                    708:                if ( m_nSelectLine - m_nVscrollPos < 0 )
                    709:                        OnVScroll( SB_LINEUP, 0, NULL );
                    710:                
                    711:                // Selection is off the screen
                    712:                if ( m_nSelectLine - m_nVscrollPos > ( m_cyClient / m_cyChar ) )
                    713:                {
                    714:                        m_nVscrollPos = m_nSelectLine + 1 - ( m_cyClient / m_cyChar );
                    715:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    716:                        Invalidate( TRUE );
                    717:                }
                    718:                if ( m_nSelectLine - m_nVscrollPos < 0 )
                    719:                {
                    720:                        m_nVscrollPos = m_nSelectLine;
                    721:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    722:                        Invalidate( TRUE );
                    723:                }
                    724:        }
                    725:        
                    726:        InvalidateLine();
                    727: }
                    728: 
                    729: //////////////////////////////////////////////////
                    730: //  CMainWindow::OnDown
                    731: //  Uses Accelerator tables to link the down arrow key to this
                    732: //  routine.  Inc the select line with checking for scrolling
                    733: //  and wrapping off the bottom of the list.
                    734: //
                    735: void CMainWindow::OnDown()
                    736: {
                    737:        InvalidateLine();
                    738:        
                    739:        if ( m_nSelectLine == (int)( m_people.GetCount() - 1 )
                    740:                        || m_nSelectLine == -1 )
                    741:        {
                    742:                m_nSelectLine = 0;
                    743:                m_nVscrollPos = 0;
                    744:                Invalidate( TRUE );
                    745:        }
                    746:        else
                    747:        {
                    748:                m_nSelectLine++;
                    749:                if ( ( m_nSelectLine - m_nVscrollPos + 1 ) > ( m_cyClient / m_cyChar ) )
                    750:                        OnVScroll( SB_LINEDOWN, 0, NULL );
                    751:                
                    752:                // Selection is off the screen
                    753:                if ( ( m_nSelectLine - m_nVscrollPos ) > ( m_cyClient / m_cyChar ) )
                    754:                {
                    755:                        m_nVscrollPos = m_nSelectLine + 1 - ( m_cyClient / m_cyChar );
                    756:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    757:                        Invalidate( TRUE );
                    758:                }
                    759:                if ( ( m_nSelectLine - m_nVscrollPos ) < 0 )
                    760:                {
                    761:                        m_nVscrollPos = m_nSelectLine;
                    762:                        SetScrollPos( SB_VERT, m_nVscrollPos, TRUE );
                    763:                        Invalidate( TRUE );
                    764:                }
                    765:        }
                    766: 
                    767:        InvalidateLine();
                    768: }
                    769: 
                    770: //////////////////////////////////////////////////
                    771: //  CMainWindow::OnLButtonDown
                    772: //  Turns the location of the mouse pointer into a line number
                    773: //  and stores that information in m_nSelectLine.  Uses
                    774: //  InvalidateLine to cause OnPaint to change the screen.
                    775: //
                    776: void CMainWindow::OnLButtonDown( UINT, CPoint location )
                    777: {
                    778:        InvalidateLine();
                    779:        
                    780:        int pos = m_nVscrollPos + location.y / m_cyChar;
                    781:        
                    782:        if ( ( m_nSelectLine != pos )  && ( pos < (int)m_people.GetCount() ) )
                    783:        {
                    784:                m_nSelectLine = pos;
                    785:                InvalidateLine();
                    786:        }
                    787:        else
                    788:                m_nSelectLine = -1;
                    789: }
                    790: 
                    791: //////////////////////////////////////////////////
                    792: //  CMainWindow::OnLButtonDblClk
                    793: //  Translates mouse left button double click into edit person.
                    794: //
                    795: void CMainWindow::OnLButtonDblClk( UINT wParam, CPoint location )
                    796: {
                    797:        if ( m_nSelectLine == -1 )
                    798:                OnLButtonDown( wParam, location );
                    799:        OnEdit();
                    800: }
                    801: 
                    802: //////////////////////////////////////////////////
                    803: //  CMainWindow::OnKeyDown
                    804: //  Translates keyboard input into scroll messages
                    805: //
                    806: void CMainWindow::OnKeyDown( UINT wParam, UINT, UINT )
                    807: {
                    808:        switch ( wParam )
                    809:        {
                    810:                case VK_HOME:
                    811:                        OnVScroll( SB_TOP, 0, NULL );
                    812:                        break;
                    813:                case VK_END:
                    814:                        OnVScroll( SB_BOTTOM, 0, NULL );
                    815:                        break;
                    816:                case VK_PRIOR:
                    817:                        OnVScroll( SB_PAGEUP, 0, NULL );
                    818:                        break;
                    819:                case VK_NEXT:
                    820:                        OnVScroll( SB_PAGEDOWN, 0, NULL );
                    821:                        break;
                    822:                case VK_LEFT:
                    823:                        OnHScroll( SB_PAGEUP, 0, NULL );
                    824:                        break;
                    825:                case VK_RIGHT:
                    826:                        OnHScroll( SB_PAGEDOWN, 0, NULL );
                    827:                        break;
                    828:        }
                    829: }
                    830: 
                    831: //////////////////////////////////////////////////
                    832: //  CMainWindow::OnPaint
                    833: //  This routine does all the painting for the screen.
                    834: //
                    835: void CMainWindow::OnPaint()
                    836: {
                    837:        
                    838:        CPaintDC dc( this );
                    839: 
                    840:        // Set the Text and background colors for the DC also create a Brush
                    841:        CBrush bBack;
                    842:        dc.SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
                    843:        dc.SetBkColor( GetSysColor( COLOR_WINDOW ) );
                    844:        bBack.CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
                    845: 
                    846:        // Compute the lines that need to be redrawn
                    847:        int nStart = max( 0, m_nVscrollPos + dc.m_ps.rcPaint.top / m_cyChar - 1 );
                    848:        int nEnd = min( (int)m_people.GetCount(),
                    849:                                m_nVscrollPos + ( dc.m_ps.rcPaint.bottom / m_cyChar+1 ) );
                    850: 
                    851:        // Create a rect the width of the display.
                    852:        CRect area( 0, 0, m_cxClient, 0 );
                    853:        
                    854:        CString szDisplay;
                    855:        CPerson* pCurrent;
                    856:        int x,y;
                    857:        for ( ;nStart < nEnd; nStart++ )
                    858:        {
                    859:                // if the current line is the select line then change the
                    860:                // colors to the highlight text colors.
                    861:                if ( m_nSelectLine == nStart )
                    862:                {
                    863:                        bBack.DeleteObject();
                    864:                        bBack.CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) );
                    865:                        dc.SetTextColor( GetSysColor( COLOR_HIGHLIGHTTEXT ) );
                    866:                        dc.SetBkColor( GetSysColor( COLOR_HIGHLIGHT ) );
                    867:                }
                    868: 
                    869:                // x is the number of characters horz scrolled * the width of
                    870:                // char.  y is the current line no. - number of lines scrolled
                    871:                // times the height of a line.
                    872:                x = m_cxChar * ( -m_nHscrollPos );
                    873:                y = m_cyChar * ( nStart - m_nVscrollPos );
                    874: 
                    875:                // Set the rect to y and y + the height of the line.  Fill the
                    876:                // rect with the background color.
                    877:                area.top = y;
                    878:                area.bottom = y+ m_cyChar;
                    879:                dc.FillRect( area, &bBack );
                    880: 
                    881:                // Get the person and build a string with his name.
                    882:                pCurrent = m_people.GetPerson( nStart );
                    883:                szDisplay = " " + pCurrent->GetLastName() + ", " +
                    884:                                pCurrent->GetFirstName();
                    885: 
                    886:                // Set the dc to write using the point as the left top of the
                    887:                // character.  Write the name.
                    888:                dc.SetTextAlign( TA_LEFT | TA_TOP );
                    889:                dc.TextOut ( x, y,szDisplay, szDisplay.GetLength() );
                    890: 
                    891:                // Write the phone number right aligned.
                    892:                szDisplay = pCurrent->GetPhoneNumber();
                    893:                dc.SetTextAlign ( TA_RIGHT | TA_TOP );
                    894:                dc.TextOut ( x + SIZENAME * m_cxCaps, y, szDisplay,
                    895:                        szDisplay.GetLength() );
                    896: 
                    897:                // Write the time.
                    898:                szDisplay = pCurrent->GetModTime().Format( "%m/%d/%y %H:%M" );
                    899:                dc.TextOut ( x + ( SIZENAME + SIZEPHONE ) * m_cxCaps, y,
                    900:                        szDisplay, szDisplay.GetLength() );
                    901: 
                    902:                // If this is the select line then we need to reset the dc
                    903:                // colors back to the original colors.
                    904:                if ( m_nSelectLine == nStart )
                    905:                {
                    906:                        bBack.DeleteObject();
                    907:                        bBack.CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
                    908:                        dc.SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
                    909:                        dc.SetBkColor( GetSysColor( COLOR_WINDOW ) );
                    910:                }
                    911:        }
                    912: }
                    913: 
                    914: /////////////////////////////////////////////////////////////////////////////
                    915: //  The following are utility routines
                    916: 
                    917: 
                    918: //////////////////////////////////////////////////
                    919: //  CMainWindow::FileDlg
                    920: //  Call the commdlg routine to display File Open or File Save As
                    921: //  dialogs.  The setup is the same for either.  If bOpen is TRUE
                    922: //  then File Open is display otherwise File Save As is displayed.
                    923: //  The File Name and File Title are stored at the string pointer
                    924: //  passed in.
                    925: //
                    926: BOOL CMainWindow::FileDlg( BOOL bOpen, int nMaxFile, LPSTR szFile,
                    927:                int nMaxFileTitle, LPSTR szFileTitle )
                    928: {
                    929:        
                    930:        OPENFILENAME of;
                    931: 
                    932:        char szDirName[SIZESTRING];
                    933:        char szFilter[] = "Phone Book Files (*.pb)\0"
                    934:                "*.pb\0"
                    935:                "\0";
                    936: 
                    937:        szDirName[0] = '.';
                    938: 
                    939:        of.lStructSize = sizeof( OPENFILENAME );
                    940:        of.hwndOwner = m_hWnd;
                    941:        of.lpstrFilter = szFilter;
                    942:        of.lpstrCustomFilter = NULL;
                    943:        of.nMaxCustFilter = 0L;
                    944:        of.nFilterIndex = 1L;
                    945:        of.lpstrFile=szFile;
                    946:        of.nMaxFile=nMaxFile;
                    947:        of.lpstrFileTitle = szFileTitle;
                    948:        of.nMaxFileTitle = nMaxFileTitle;
                    949:        of.lpstrInitialDir = szDirName;
                    950:        of.lpstrTitle = NULL;
                    951:        of.nFileOffset = 0;
                    952:        of.nFileExtension = 0;
                    953:        of.lpstrDefExt = "pb";
                    954:        if ( bOpen )
                    955:        {
                    956:                of.Flags = OFN_HIDEREADONLY;
                    957:                return GetOpenFileName( &of );
                    958:        }
                    959:        else
                    960:        {
                    961:                of.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
                    962:                return GetSaveFileName( &of );
                    963:        }
                    964: }
                    965: 
                    966: //////////////////////////////////////////////////
                    967: //  CMainWindow::Save
                    968: //  Handles any time a file needs to be saved to the disk.
                    969: //  Passing in FALSE for name brings up the file save as dialog
                    970: //  whether or not the database had a name before.
                    971: //
                    972: BOOL CMainWindow::Save( BOOL bIsNamed /* = FALSE */ )
                    973: {
                    974:        CString szFileName, szFileTitle;
                    975:        TRY
                    976:        {
                    977:                if ( bIsNamed )
                    978:                        m_people.DoSave();
                    979:                else
                    980:                {
                    981:                        szFileName = m_people.GetName();
                    982:                        if ( FileDlg( FALSE, SIZESTRING,
                    983:                                        szFileName.GetBuffer( SIZESTRING ), SIZESTRING,
                    984:                                        szFileTitle.GetBuffer( SIZESTRING ) ) )
                    985:                        {
                    986:                                szFileName.ReleaseBuffer();
                    987:                                m_people.DoSave( szFileName );
                    988:                                m_people.SetTitle( szFileTitle );
                    989:                                SetWindowText( m_people.GetTitle() );
                    990:                        }
                    991:                        else
                    992:                                return FALSE;
                    993:                }
                    994:        }
                    995:        CATCH( CFileException, e )
                    996:        {
                    997:                char ErrorMsg[SIZESTRING];
                    998:                sprintf( ErrorMsg,"Saving %s returned a 0x%lx.",
                    999:                                (const char*)szFileTitle, e->m_lOsError );
                   1000:                MessageBox( ErrorMsg, "File Open Error" );
                   1001:        }
                   1002:        AND_CATCH( CArchiveException, e )
                   1003:        {
                   1004:                char ErrorMsg[SIZESTRING];
                   1005:                sprintf( ErrorMsg,"Reading the %s archive failed.",
                   1006:                                (const char*)szFileTitle );
                   1007:                MessageBox( ErrorMsg, "File Open Error" );
                   1008:        }
                   1009:        END_CATCH
                   1010:        return TRUE;
                   1011: }
                   1012: 
                   1013: //////////////////////////////////////////////////
                   1014: //  CMainWindow::CheckForSave
                   1015: //  Whenever a new file is opened this routine will determine if
                   1016: //  there are unsaved changes in the current database.  If so it
                   1017: //  will query the user and determine save or not as appropriate.
                   1018: //
                   1019: BOOL CMainWindow::CheckForSave( const char* pszTitle, const char* pszMessage )
                   1020: {
                   1021:        if ( m_people.IsDirty() )
                   1022:        {
                   1023:                UINT nButton = MessageBox( pszMessage, pszTitle, MB_YESNOCANCEL );
                   1024:                if ( nButton == IDYES )
                   1025:                {
                   1026:                        if ( !Save( m_people.IsNamed() ) )
                   1027:                                return FALSE;
                   1028:                }
                   1029:                else if ( nButton == IDCANCEL )
                   1030:                        return FALSE;
                   1031:        }
                   1032:        return TRUE;
                   1033: }
                   1034: 
                   1035: 
                   1036: //////////////////////////////////////////////////
                   1037: //  CMainWindow::SetMenu
                   1038: //  Whenever the existance of the DataBase is changed this
                   1039: //  routine will reset the menus so only the possible commands
                   1040: //  are accessible.
                   1041: //
                   1042: void CMainWindow::SetMenu()
                   1043: {
                   1044:        CMenu* pMenu = GetMenu();
                   1045:        if ( m_people.IsPresent() )
                   1046:        {
                   1047:                if ( m_people.IsNamed() )
                   1048:                        pMenu->EnableMenuItem( IDM_SAVE, MF_ENABLED );
                   1049:                else
                   1050:                        pMenu->EnableMenuItem( IDM_SAVE, MF_GRAYED );
                   1051:                pMenu->EnableMenuItem( IDM_SAVEAS, MF_ENABLED );
                   1052:                pMenu->EnableMenuItem( IDM_CLOSE, MF_ENABLED );
                   1053:                pMenu->EnableMenuItem( IDM_PRINT, MF_ENABLED );
                   1054:                pMenu->EnableMenuItem( IDM_ADD, MF_ENABLED );
                   1055:                pMenu->EnableMenuItem( IDM_DELETE, MF_ENABLED );
                   1056:                pMenu->EnableMenuItem( IDM_FIND, MF_ENABLED );
                   1057:                pMenu->EnableMenuItem( IDM_EDIT, MF_ENABLED );
                   1058:        }
                   1059:        else
                   1060:        {
                   1061:                pMenu->EnableMenuItem( IDM_SAVE, MF_GRAYED );
                   1062:                pMenu->EnableMenuItem( IDM_SAVEAS, MF_GRAYED );
                   1063:                pMenu->EnableMenuItem( IDM_CLOSE, MF_GRAYED );
                   1064:                pMenu->EnableMenuItem( IDM_PRINT, MF_GRAYED );
                   1065:                pMenu->EnableMenuItem( IDM_ADD, MF_GRAYED );
                   1066:                pMenu->EnableMenuItem( IDM_DELETE, MF_GRAYED );
                   1067:                pMenu->EnableMenuItem( IDM_FIND, MF_GRAYED );
                   1068:                pMenu->EnableMenuItem( IDM_FINDALL, MF_GRAYED );
                   1069:                pMenu->EnableMenuItem( IDM_EDIT, MF_GRAYED );
                   1070:        }
                   1071: }
                   1072: 
                   1073: //////////////////////////////////////////////////
                   1074: //  CMainWindow::InvalidateLine
                   1075: //  Marks the screen area of the currently selected person as
                   1076: //  invalid causing windows to call OnPaint to redraw the area.
                   1077: //  This is normally used when the selected line is being changed.
                   1078: //
                   1079: void CMainWindow::InvalidateLine()
                   1080: {
                   1081:        CRect area( 0, ( m_nSelectLine - m_nVscrollPos ) * m_cyChar, m_cxClient,
                   1082:                                ( m_nSelectLine + 1 - m_nVscrollPos ) * m_cyChar );
                   1083:        InvalidateRect( area );
                   1084: }

unix.superglobalmegacorp.com

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