Annotation of mstools/mfc/samples/tutorial/view.cpp, revision 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.