Annotation of mstools/mfc/samples/chart/chartwnd.cpp, revision 1.1

1.1     ! root        1: // chartwnd.cpp : Defines the class behaviors for the Chart 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: 
        !            14: #include "chart.h"
        !            15: 
        !            16: #include <math.h>
        !            17: 
        !            18: #include <commdlg.h>
        !            19: 
        !            20: // hPrintDlg and bUserAbort are used to handle the print abort
        !            21: // modeless dialog
        !            22: //
        !            23: static HWND hPrintDlg;
        !            24: BOOL bUserAbort;
        !            25: 
        !            26: // CChartWnd static member variables that define the bounds of
        !            27: // CChartWnd's custom anisotropic coordinate system
        !            28: //
        !            29: CRect CChartWnd::rectPage(0, 1000, 1000, 0);
        !            30: CRect CChartWnd::rectData(150, 100, 850, 800);
        !            31: 
        !            32: static short nBlue, nGreen, nRed, nCurrentColor;
        !            33: 
        !            34: /////////////////////////////////////////////////////////////////////////////
        !            35: // CChartWnd
        !            36: 
        !            37: BEGIN_MESSAGE_MAP(CChartWnd, CFrameWnd)
        !            38:        ON_WM_MOUSEMOVE()
        !            39:        ON_WM_PAINT()
        !            40:        ON_WM_CREATE()
        !            41:        ON_WM_CLOSE()
        !            42: 
        !            43:        ON_COMMAND(IDM_NEW, OnNew)
        !            44:        ON_COMMAND(IDM_OPEN, CmdFileOpen)
        !            45:        ON_COMMAND(IDM_SAVE, CmdFileSave)
        !            46:        ON_COMMAND(IDM_SAVEAS, CmdFileSaveAs)
        !            47:        ON_COMMAND(IDM_CHANGE, OnChange)
        !            48:        ON_COMMAND(IDM_PRINT, OnPrint)
        !            49:        ON_COMMAND(IDM_EXIT, OnClose)
        !            50: 
        !            51:        ON_COMMAND(IDM_BAR, OnBar)
        !            52:        ON_COMMAND(IDM_LINE, OnLine)
        !            53: 
        !            54:        ON_COMMAND(IDM_ABOUT, OnAbout)
        !            55: END_MESSAGE_MAP()
        !            56: 
        !            57: // Constructor:
        !            58: //
        !            59: CChartWnd::CChartWnd()
        !            60: {
        !            61:        m_bUntitled = TRUE;
        !            62:        m_szFileName = "";
        !            63:        m_bChartSerializedOK = FALSE;
        !            64:        Create("Chart");
        !            65: }
        !            66: 
        !            67: // Destructor:
        !            68: //
        !            69: CChartWnd::~CChartWnd()
        !            70: {
        !            71:        if (m_pChartObject != NULL)
        !            72:        {
        !            73:                delete m_pChartObject;  
        !            74:                m_pChartObject = NULL;
        !            75:        }
        !            76: }
        !            77: 
        !            78: // Create:
        !            79: // Load accelerator keys for this window and create a frame window.
        !            80: // The frame window uses a custom window class because it has a
        !            81: // non-standard icon.
        !            82: // The accelerator table, main menu, and icon are defined in chart.rc.
        !            83: //
        !            84: BOOL CChartWnd::Create(LPCSTR szTitle,
        !            85:        LONG style /* = WS_OVERLAPPEDWINDOW */,
        !            86:        const RECT& rect /* = rectDefault */,
        !            87:        CWnd* parent /* = NULL */)
        !            88: {
        !            89:        LoadAccelTable("MainAccelTable");
        !            90: 
        !            91:        const char* pszWndClass =
        !            92:                        AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
        !            93:                                                                NULL,
        !            94:                                                                (HBRUSH)(COLOR_WINDOW+1),
        !            95:                                                                LoadIcon(AfxGetInstanceHandle(), "chart"));
        !            96: 
        !            97:        return CFrameWnd::Create(pszWndClass, szTitle, style,
        !            98:                                                         rect, parent, "MainMenu");
        !            99: }
        !           100: 
        !           101: // OnCreate:
        !           102: // Get cursors and initialize the main menu
        !           103: //
        !           104: int CChartWnd::OnCreate(LPCREATESTRUCT)
        !           105: {
        !           106:        m_pChartObject = NULL;
        !           107:        m_hCross = LoadCursor(NULL, IDC_CROSS);
        !           108:        m_hArrow = LoadCursor(NULL, IDC_ARROW);
        !           109: 
        !           110:        UpdateMenu();
        !           111: 
        !           112:        return 0;
        !           113: }
        !           114: 
        !           115: // UpdateMenu:
        !           116: // Update main menu item state based on chart state
        !           117: //
        !           118: void CChartWnd::UpdateMenu()
        !           119: {
        !           120:        CMenu* menu = GetMenu();
        !           121: 
        !           122:        UINT nData = (m_pChartObject? MF_ENABLED : MF_GRAYED);
        !           123: 
        !           124:        menu->EnableMenuItem(IDM_SAVEAS, nData);
        !           125:        menu->EnableMenuItem(IDM_CHANGE, nData);
        !           126:        menu->EnableMenuItem(IDM_PRINT,  nData);
        !           127: 
        !           128:        menu->EnableMenuItem(IDM_BAR,    nData);
        !           129:        menu->EnableMenuItem(IDM_LINE,   nData);
        !           130: 
        !           131:        if (m_pChartObject != NULL)
        !           132:        {
        !           133:                nData = (m_pChartObject->m_nType == IDM_BAR);
        !           134:                menu->CheckMenuItem(IDM_BAR,  nData? MF_CHECKED : MF_UNCHECKED);
        !           135:                menu->CheckMenuItem(IDM_LINE, nData? MF_UNCHECKED : MF_CHECKED);
        !           136:                menu->EnableMenuItem(IDM_SAVE,
        !           137:                                                         m_bUntitled ? MF_GRAYED : MF_ENABLED);
        !           138: 
        !           139:                                        
        !           140:        }
        !           141:        else
        !           142:        {
        !           143:                menu->CheckMenuItem(IDM_BAR,  MF_UNCHECKED);
        !           144:                menu->CheckMenuItem(IDM_LINE, MF_UNCHECKED);
        !           145:                menu->EnableMenuItem(IDM_SAVE, MF_GRAYED);
        !           146:        }
        !           147: 
        !           148:        DrawMenuBar();
        !           149: }
        !           150: 
        !           151: // OnNew:
        !           152: // Create a new empty chart
        !           153: //
        !           154: void CChartWnd::OnNew()
        !           155: {
        !           156:        if (m_pChartObject != NULL)
        !           157:        {
        !           158:                if (m_pChartObject->m_bDirty)
        !           159:                {
        !           160: 
        !           161:                        if (MessageBox("Save existing data?", "Chart",
        !           162:                                                        MB_YESNO | MB_ICONQUESTION) == IDYES)
        !           163:                        {
        !           164:                                SaveFile(m_bUntitled);
        !           165:                        }
        !           166:                }
        !           167: 
        !           168:                delete m_pChartObject;
        !           169:                m_pChartObject = NULL;
        !           170:                m_bUntitled = TRUE;
        !           171:                m_szFileName = "";
        !           172:                m_pChartObject = NULL;
        !           173:        }
        !           174:        OnChange();
        !           175: }
        !           176: 
        !           177: // OnChange:
        !           178: // User wants to enter (or change) chart data.
        !           179: //
        !           180: void CChartWnd::OnChange()
        !           181: {
        !           182:        // Create data structure if there is none.
        !           183:        //
        !           184:        if (m_pChartObject == NULL)
        !           185:        {
        !           186:                m_pChartObject = new CChartObject();
        !           187:        }
        !           188: 
        !           189:        // Get the data.
        !           190:        //
        !           191:        CEntryDialog entryDlg(this);
        !           192:        entryDlg.DoModal(m_pChartObject);
        !           193: 
        !           194:        ASSERT(m_pChartObject->m_pChartData != NULL);
        !           195: 
        !           196:        if (m_pChartObject->m_pChartData->IsEmpty())
        !           197:        {
        !           198:                delete m_pChartObject;
        !           199:                m_pChartObject = NULL;
        !           200:        }
        !           201: 
        !           202:        // Update menu state based on the data
        !           203:        //
        !           204:        UpdateMenu();
        !           205:        Invalidate(TRUE);
        !           206: }
        !           207: 
        !           208: // OnPrint:
        !           209: // User wants to print the chart
        !           210: //
        !           211: void CChartWnd::OnPrint()
        !           212: {
        !           213:        if (!DoPrint())
        !           214:        {
        !           215:                MessageBox("Not able to print chart.", "Chart",
        !           216:                   MB_OK | MB_ICONEXCLAMATION);
        !           217:        }
        !           218: }
        !           219: 
        !           220: // OnBar:
        !           221: // Make the chart a bar chart
        !           222: //
        !           223: void CChartWnd::OnBar()
        !           224: {
        !           225:        ASSERT(m_pChartObject != NULL);
        !           226: 
        !           227:        m_pChartObject->m_nType = IDM_BAR;
        !           228: 
        !           229:        UpdateMenu();
        !           230:        Invalidate(TRUE);
        !           231: }
        !           232: 
        !           233: // OnLine:
        !           234: // Make the chart a line chart
        !           235: //
        !           236: void CChartWnd::OnLine()
        !           237: {
        !           238:        ASSERT(m_pChartObject != NULL);
        !           239: 
        !           240:        m_pChartObject->m_nType = IDM_LINE;
        !           241: 
        !           242:        UpdateMenu();
        !           243:        Invalidate(TRUE);
        !           244: }
        !           245: 
        !           246: // PrepareDC:
        !           247: // Prepare a DC for drawing the chart
        !           248: void CChartWnd::PrepareDC(CDC* pDC)
        !           249: {
        !           250:        pDC->SetMapMode(MM_ANISOTROPIC);
        !           251:        pDC->SetWindowExt(rectPage.right, rectPage.top);
        !           252:        pDC->SetViewportExt(m_cxClient, -m_cyClient);
        !           253:        pDC->SetViewportOrg(0, m_cyClient);
        !           254:        pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
        !           255:        pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
        !           256: }
        !           257: 
        !           258: // OnMouseMove:
        !           259: // We do some hit-testing here to make the cursor a crosshairs while inside
        !           260: // the data graphic, and an arrow otherwise.
        !           261: //
        !           262: void CChartWnd::OnMouseMove(UINT, CPoint mousePos)
        !           263: {
        !           264:        if (m_pChartObject == NULL)
        !           265:        {
        !           266:                SetCursor(m_hArrow);
        !           267:                return;
        !           268:        }
        !           269: 
        !           270:        // We use a custom logical coordinate system.  0,0 is the bottom-left
        !           271:        // corner of the client area, and 1000,1000 is the top-right.
        !           272:        // Convert the mouse coordinates to this scheme.
        !           273:        //
        !           274:        CDC* pDC;
        !           275:        pDC = GetDC();
        !           276:        PrepareDC(pDC);
        !           277:        pDC->DPtoLP(&mousePos, 1);
        !           278: 
        !           279:        if (rectData.PtInRect(mousePos))
        !           280:        {
        !           281:                SetCursor(m_hCross);
        !           282:        }
        !           283:        else
        !           284:        {
        !           285:                SetCursor(m_hArrow);
        !           286:        }
        !           287: 
        !           288:        ReleaseDC(pDC);
        !           289: }
        !           290:        
        !           291: // OnPaint:
        !           292: // Paint the chart...
        !           293: //
        !           294: void CChartWnd::OnPaint()
        !           295: {
        !           296:        CPaintDC dc(this);
        !           297:        CRect screenPos;
        !           298: 
        !           299:        GetClientRect(screenPos);
        !           300: 
        !           301:        m_cxClient = screenPos.Width();
        !           302:        m_cyClient = screenPos.Height();
        !           303: 
        !           304:        if (m_pChartObject != NULL)
        !           305:        {
        !           306:                RenderChart(&dc);
        !           307:        }
        !           308: }
        !           309: 
        !           310: // OnClose:
        !           311: // User picked 'Close' on system menu
        !           312: //
        !           313: void CChartWnd::OnClose()
        !           314: {
        !           315:        if (m_pChartObject != NULL)
        !           316:        {
        !           317:                if (m_pChartObject->m_bDirty)
        !           318:                {
        !           319:                        int fResponse;
        !           320: 
        !           321:                        fResponse = MessageBox("Save file before exit?", "Chart",
        !           322:                                                        MB_YESNOCANCEL | MB_ICONQUESTION);
        !           323: 
        !           324:                        if (fResponse == IDCANCEL)
        !           325:                        {
        !           326:                                return;
        !           327:                        }
        !           328:                        else if (fResponse == IDYES)
        !           329:                        {
        !           330:                                SaveFile(m_bUntitled);
        !           331:                        }
        !           332:                }
        !           333:                delete m_pChartObject;
        !           334:        }
        !           335: 
        !           336:        m_pChartObject = NULL;
        !           337: 
        !           338:        DestroyWindow();
        !           339: }
        !           340: 
        !           341: // GetHighValue:
        !           342: // Returns largest value in chart data.
        !           343: //
        !           344: short CChartWnd::GetHighValue()
        !           345: {
        !           346:        short i, count, nLargest, nCurrent;
        !           347:        POSITION pos;
        !           348:        CChartData* ptr;
        !           349: 
        !           350:        ASSERT(m_pChartObject != NULL);
        !           351:        CObList* pChartData = m_pChartObject->m_pChartData;
        !           352: 
        !           353:        ASSERT(pChartData != NULL);
        !           354: 
        !           355:        ptr = (CChartData*)(pChartData->GetHead());
        !           356: 
        !           357:        nLargest = ptr->height;
        !           358: 
        !           359:        pos = pChartData->GetHeadPosition();
        !           360:        count = pChartData->GetCount();
        !           361:        for (i = 0; i < count; i++)
        !           362:        {
        !           363:                ptr = (CChartData*)pChartData->GetNext(pos);
        !           364: 
        !           365:                if ((nCurrent = ptr->height) > nLargest)
        !           366:                {
        !           367:                        nLargest = nCurrent;
        !           368:                }
        !           369:        }
        !           370: 
        !           371:        return nLargest;
        !           372: }
        !           373: 
        !           374: // SetNewColors:
        !           375: // Progresses nCurrentColor through the possible colors.
        !           376: //
        !           377: void CChartWnd::SetNewColors()
        !           378: {
        !           379:        nCurrentColor++;
        !           380: 
        !           381:        ASSERT(m_pChartObject != NULL);
        !           382:        ASSERT(m_pChartObject->m_pChartData != NULL);
        !           383: 
        !           384:        nCurrentColor %= (m_pChartObject->m_pChartData->GetCount()+1);
        !           385: 
        !           386:        nBlue = (nCurrentColor & 1) ? 255 : 0;
        !           387:        nGreen = (nCurrentColor & 2) ? 255 : 0;
        !           388:        nRed = (nCurrentColor & 4) ? 255 : 0;
        !           389: 
        !           390: }
        !           391: 
        !           392: // RenderChart:
        !           393: // Draw the chart in a device context.  This routine handles both
        !           394: // screen DCs and printer DCs.
        !           395: //
        !           396: void CChartWnd::RenderChart(CDC* pDC)
        !           397: {
        !           398:        short i, nSize, nTextHeight;
        !           399:        float yTickMag, yTickGuess;
        !           400:        char szBuffer[80];
        !           401: 
        !           402:        ASSERT(m_pChartObject != NULL);
        !           403: 
        !           404:        if (m_pChartObject->m_pChartData->IsEmpty())
        !           405:        {
        !           406:                return;
        !           407:                // return if there are no entries in the list
        !           408:        }
        !           409: 
        !           410:        // We use a custom logical coordinate system.  0,0 is the bottom-left
        !           411:        // corner of the client area, and 1000,1000 is the top-right.
        !           412:        //
        !           413:        PrepareDC(pDC);
        !           414: 
        !           415:        // A rectangle around the chart.
        !           416:        //
        !           417:        pDC->Rectangle(rectData);
        !           418: 
        !           419:        // A blue dotted pen to draw the grid on the chart.
        !           420:        //
        !           421:        CPen newPen(PS_DOT, 2, RGB(0, 0, 255));
        !           422:        CPen* penOrig = pDC->SelectObject(&newPen);
        !           423: 
        !           424:        // Figure out a reasonable step size for the grid.
        !           425:        //
        !           426:        m_fTallest = GetHighValue();
        !           427:        yTickGuess = m_fTallest / 10;
        !           428:        yTickMag = (float)(((log10(yTickGuess) / log10(2.7182818))) /
        !           429:                                                (log10(10.0) / log10(2.7182818)));
        !           430:        yTickGuess = (float)(((yTickGuess / pow(10, (yTickMag - 1)) + 0.5) / 10) *
        !           431:                pow(10, yTickMag));
        !           432: 
        !           433:        // Draw grid.
        !           434:        //
        !           435:        m_fTallest = yTickGuess * 10;
        !           436:        int iTickDelta = rectData.Height()/10;
        !           437: 
        !           438:        for (i = 1; i <= 10; i++)
        !           439:        {
        !           440:                if (i != 10)
        !           441:                {       
        !           442:                        pDC->MoveTo(rectData.left, rectData.top + (iTickDelta*i));
        !           443:                        pDC->LineTo(rectData.right, rectData.top + (iTickDelta*i));
        !           444:                }
        !           445: 
        !           446:                sprintf(szBuffer,"%3.2f", (yTickGuess*i));
        !           447: 
        !           448:                nSize = pDC->GetTextExtent(szBuffer,strlen(szBuffer)).cx;
        !           449:                nTextHeight = pDC->GetTextExtent(szBuffer, strlen(szBuffer)).cy;
        !           450:                if (((nSize+25) < rectData.left) && (nTextHeight < iTickDelta))
        !           451:                {
        !           452:                        pDC->TextOut((125-nSize),
        !           453:                                                 rectData.top+(iTickDelta*i)+(nTextHeight/2),
        !           454:                                                szBuffer, strlen(szBuffer));
        !           455:                }
        !           456:        }
        !           457: 
        !           458:        // Done with the grid; re-select the original pen
        !           459: 
        !           460:        pDC->SelectObject(penOrig);
        !           461: 
        !           462:        // Create and select the brush to draw the chart data itself
        !           463:        //
        !           464:        CBrush* pOldBrush;
        !           465:        CBrush newBrush(RGB(nRed, nGreen, nBlue));
        !           466:        pOldBrush = pDC->SelectObject(&newBrush);
        !           467: 
        !           468:        switch (m_pChartObject->m_nType)
        !           469:        {
        !           470:        case IDM_LINE:
        !           471:                DrawLineChart(pDC);
        !           472:                break;
        !           473: 
        !           474:        case IDM_BAR:
        !           475:                DrawBarChart(pDC);
        !           476:                break;
        !           477:        }
        !           478: 
        !           479:        // Delete the brush, after selecting the old one back in the DC.
        !           480:        //
        !           481:        pDC->SelectObject(pOldBrush);
        !           482: 
        !           483:        // Draw the title, if there's room.
        !           484:        //
        !           485:        nSize = pDC->GetTextExtent(m_pChartObject->m_Title,
        !           486:                m_pChartObject->m_Title.GetLength()).cx;
        !           487: 
        !           488:        if ((nSize/2) < 500)
        !           489:        {
        !           490:                pDC->TextOut((500 - (nSize/2)), 900, m_pChartObject->m_Title,
        !           491:                        m_pChartObject->m_Title.GetLength());
        !           492:        }
        !           493: }
        !           494: 
        !           495: // DrawBarChart:
        !           496: // Render the chart as a bar chart
        !           497: //
        !           498: void CChartWnd::DrawBarChart(CDC* pDC)
        !           499: {
        !           500:        float flFraction;
        !           501:        short nWidth, i, nTextHeight, nCurrentHeight, nSize;
        !           502:        CRect rectBar;
        !           503:        POSITION pos;
        !           504:        CChartData* ptr;
        !           505:        char szBuffer[80];
        !           506: 
        !           507:        ASSERT(m_pChartObject != NULL);
        !           508:        ASSERT(m_pChartObject->m_pChartData != NULL);
        !           509: 
        !           510:        CObList* pChartData = m_pChartObject->m_pChartData;
        !           511: 
        !           512:        flFraction = (rectData.Width() / (pChartData->GetCount()));
        !           513:        nWidth = (short) flFraction;
        !           514:        pos = pChartData->GetHeadPosition();
        !           515: 
        !           516:        nCurrentColor = 0;
        !           517:        int cChart = pChartData->GetCount();
        !           518: 
        !           519:        for (i = 0; i < cChart; i++)
        !           520:        {
        !           521:                char szLabel[40];
        !           522:                ptr = (CChartData*)pChartData->GetNext(pos);
        !           523:                strcpy(szLabel, ptr->szName);
        !           524:                int nNewHeight = ptr->height;
        !           525: 
        !           526:                // Calculate the size of the bar.
        !           527:                //
        !           528:                flFraction = nNewHeight / m_fTallest;
        !           529:                nCurrentHeight = (short) (flFraction * rectData.Height());
        !           530: 
        !           531:                rectBar.left = rectData.left + (nWidth * i);
        !           532:                rectBar.top = nCurrentHeight + rectData.top;
        !           533:                rectBar.right = rectData.left + nWidth * (i+1);
        !           534:                rectBar.bottom = rectBar.top - nCurrentHeight;
        !           535: 
        !           536:                SetNewColors();
        !           537:                CBrush chartBrush(RGB(nRed, nGreen, nBlue));
        !           538:                CBrush* oldBrush = pDC->SelectObject(&chartBrush);
        !           539: 
        !           540:                pDC->Rectangle(rectBar);
        !           541: 
        !           542:                sprintf(szBuffer, "%s", szLabel);
        !           543:                nSize = pDC->GetTextExtent(szBuffer,strlen(szBuffer)).cx;
        !           544:                nTextHeight = pDC->GetTextExtent(szBuffer, strlen(szBuffer)).cy;
        !           545:                if (((nSize+20) < nWidth) && (nTextHeight < 95))
        !           546:                        pDC->TextOut(rectBar.left+(nWidth/2)-(nSize/2),
        !           547:                                                 rectBar.bottom-5,
        !           548:                                                 szBuffer, strlen(szBuffer));
        !           549: 
        !           550:                // Delete the brush, after selecting the old one back into the DC.
        !           551:                //
        !           552:                pDC->SelectObject(oldBrush);
        !           553:        }
        !           554: }
        !           555: 
        !           556: // DrawLineChart:
        !           557: // Render the chart data as a line chart
        !           558: //
        !           559: void CChartWnd::DrawLineChart(CDC* pDC)
        !           560: {
        !           561:        short nWidth, nSize, nTextHeight, i;
        !           562:        short nCurrentHeight, nBottom;
        !           563: 
        !           564:        CPoint ptStart;
        !           565:        CPoint ptEnd;
        !           566: 
        !           567:        LONG nTotalHeight;
        !           568:        float flFraction, flOffset;
        !           569:        POSITION pos;
        !           570:        CChartData* ptr;
        !           571:        char szBuffer[80];
        !           572: 
        !           573:        ASSERT(m_pChartObject != NULL);
        !           574: 
        !           575:        CObList* pChartData = m_pChartObject->m_pChartData;
        !           576: 
        !           577:        ASSERT(pChartData != NULL);
        !           578:        flFraction = (rectData.Width() / (pChartData->GetCount()));
        !           579:        nWidth = (short) flFraction;
        !           580: 
        !           581:        ptr = (CChartData*)pChartData->GetHead();
        !           582:        ptStart.x = rectData.left + (nWidth/2);
        !           583:        nTotalHeight = (LONG)(((LONG)ptr->height) * rectData.Height());
        !           584:        flOffset = (nTotalHeight / m_fTallest);
        !           585:        ptStart.y = rectData.top + (int)flOffset;
        !           586:        pos = pChartData->GetHeadPosition();
        !           587: 
        !           588:        int cChart = pChartData->GetCount();
        !           589:        for (i = 0; i < cChart; i++)
        !           590:        {
        !           591:                char szLabel[40];
        !           592:                ptr = (CChartData*)pChartData->GetNext(pos);
        !           593:                strcpy(szLabel, ptr->szName);
        !           594:                int nNewHeight = ptr->height;
        !           595: 
        !           596:                flFraction = nNewHeight / m_fTallest;
        !           597:                nCurrentHeight = (short) (flFraction * rectData.Height());
        !           598: 
        !           599:                ptEnd.x = nWidth/2 + rectData.left + nWidth*i;
        !           600:                ptEnd.y = rectData.top + nCurrentHeight;
        !           601:                nBottom = ptEnd.y - nCurrentHeight;
        !           602: 
        !           603:                pDC->MoveTo(ptStart);
        !           604:                pDC->LineTo(ptEnd);
        !           605: 
        !           606:                ptStart = ptEnd;
        !           607: 
        !           608:                sprintf(szBuffer, "%s", szLabel);
        !           609:                nSize = pDC->GetTextExtent(szBuffer, strlen(szBuffer)).cx;
        !           610:                nTextHeight = pDC->GetTextExtent(szBuffer, strlen(szBuffer)).cy;
        !           611:                if (((nSize+20) < nWidth) && (nTextHeight < 95))
        !           612:                {
        !           613:                        pDC->TextOut((ptEnd.x-(nSize/2)), (nBottom-5),
        !           614:                                szBuffer, strlen(szBuffer));
        !           615:                }
        !           616:        }
        !           617: }
        !           618: 
        !           619: // AbortProc:
        !           620: // While printing, the Printing... dialog (PrintDlgBox in chart.rc) is
        !           621: // displayed, which has a Cancel button on it.  This routine replaces the
        !           622: // normal message-handling mechanism, until the printing is done or the
        !           623: // Cancel button is pressed.
        !           624: //
        !           625: BOOL FAR PASCAL _export AbortProc(HDC, int)
        !           626: {
        !           627:        MSG msg;
        !           628: 
        !           629:        while(!bUserAbort && PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        !           630:        {
        !           631:                if (!hPrintDlg || !IsDialogMessage(hPrintDlg, &msg))
        !           632:                {
        !           633:                        TranslateMessage(&msg);
        !           634:                        DispatchMessage(&msg);
        !           635:                }
        !           636:        }
        !           637: 
        !           638:        return !bUserAbort;
        !           639: }
        !           640: 
        !           641: 
        !           642: // DoPrint: 
        !           643: // Get a printer DC and render the chart on it.  Uses COMMDLG
        !           644: // printer dialog.
        !           645: //
        !           646: BOOL CChartWnd::DoPrint()
        !           647: {
        !           648:        BOOL (FAR PASCAL _export * lpfnAbortProc)(HDC hPrinterDC, int nCode);
        !           649:        static char szMessage[] = "Printing chart...";
        !           650:        short xPage, yPage, oldX, oldY;
        !           651:        BOOL bError = FALSE;
        !           652:        CDC* pDC = NULL;
        !           653: 
        !           654:        lpfnAbortProc = AbortProc;
        !           655: 
        !           656:        CPrintDialog printDialog(FALSE);
        !           657:        if (printDialog.DoModal() == IDCANCEL)
        !           658:                return FALSE;
        !           659: 
        !           660:        pDC = new CDC;
        !           661:        pDC->Attach(printDialog.GetPrinterDC());
        !           662: 
        !           663:        xPage = pDC->GetDeviceCaps(HORZRES);
        !           664:        yPage = pDC->GetDeviceCaps(VERTRES);
        !           665: 
        !           666:        // The chart main window has to be disabled while printing so that
        !           667:        // the user can't change data.
        !           668:        //
        !           669:        EnableWindow(FALSE);
        !           670: 
        !           671:        // Set up the printer abort box and its window procedure control
        !           672:        // variables
        !           673:        //
        !           674:        bUserAbort = FALSE;
        !           675:        m_pPrintDlg = new CPrintDlgBox;
        !           676:        hPrintDlg = m_pPrintDlg->m_hWnd;
        !           677: 
        !           678:        if (pDC->SetAbortProc(lpfnAbortProc) < 0)
        !           679:        {
        !           680:                delete pDC;
        !           681:                return FALSE;
        !           682:        }
        !           683: 
        !           684: #ifndef _NTWIN
        !           685:        if (pDC->StartDoc(szMessage) > 0)
        !           686: #else
        !           687:        DOCINFO di;
        !           688:        di.cbSize = sizeof(di);
        !           689:        di.lpszDocName = szMessage;
        !           690:        di.lpszOutput = NULL;
        !           691:        if (pDC->StartDoc(&di) > 0)
        !           692: #endif
        !           693:        {
        !           694:                oldX = m_cxClient;
        !           695:                m_cxClient = xPage;
        !           696:                oldY = m_cyClient;
        !           697:                m_cyClient = yPage;
        !           698: 
        !           699:                RenderChart(pDC);
        !           700: 
        !           701:                if (pDC->EndPage() > 0)
        !           702:                {
        !           703:                        pDC->EndDoc();
        !           704:                }
        !           705:                else
        !           706:                {
        !           707:                        bError = TRUE;
        !           708:                }
        !           709:        }
        !           710:        else
        !           711:        {
        !           712:                bError = TRUE;
        !           713:        }
        !           714: 
        !           715:        m_cxClient = oldX;
        !           716:        m_cyClient = oldY;
        !           717: 
        !           718:        // Now that we're done, we can now allow the user access to the frame
        !           719:        // window again.  bUserAbort is set in the AbortProc just before this
        !           720:        // function.
        !           721:        //
        !           722:        if (!bUserAbort)
        !           723:        {
        !           724:                EnableWindow(TRUE);
        !           725:        }
        !           726: 
        !           727:        delete pDC;
        !           728:        delete m_pPrintDlg;
        !           729: 
        !           730:        return !bError && !bUserAbort;
        !           731: }
        !           732: 
        !           733: // CmdFileSave:
        !           734: // User wants to save current chart data in the current file
        !           735: //
        !           736: void CChartWnd::CmdFileSave()
        !           737: {
        !           738:        if (!m_bUntitled)
        !           739:        {
        !           740:                SaveFile(FALSE);
        !           741:                UpdateMenu();
        !           742:        }
        !           743: }
        !           744: 
        !           745: // CmdFileSaveAs:
        !           746: // User wants to save current chart data in a named file
        !           747: //
        !           748: void CChartWnd::CmdFileSaveAs()
        !           749: {
        !           750:        SaveFile(TRUE);
        !           751:        UpdateMenu();
        !           752: }
        !           753: 
        !           754: // CmdFileOpen
        !           755: // User wants to open an existing file and read in chart data
        !           756: //
        !           757: void CChartWnd::CmdFileOpen()
        !           758: {
        !           759:        // Create data structure if there is none.
        !           760:        //
        !           761:        if (m_pChartObject != NULL)
        !           762:        {
        !           763:                if (m_pChartObject->m_bDirty)
        !           764:                {
        !           765:                        if (MessageBox("Save existing data?", "Chart",
        !           766:                                                MB_YESNO | MB_ICONQUESTION) == IDYES)
        !           767:                        {
        !           768:                                SaveFile(m_bUntitled);
        !           769:                        }
        !           770:                }
        !           771:        }
        !           772: 
        !           773:        // Get the data.
        !           774:        //
        !           775:        ReadFile();
        !           776: 
        !           777:        // If read failed, or there's no data to read, clean up.
        !           778:        //
        !           779: 
        !           780:        if (!m_bChartSerializedOK)
        !           781:        {
        !           782:                // chart deserialization failed and chart is in an
        !           783:                // inconsistent state -- don't delete.  Just null
        !           784:                // the pointer and suffer a memory leak.
        !           785: 
        !           786:                m_pChartObject = NULL;
        !           787:        }
        !           788:        else
        !           789:        {
        !           790:                if ((m_pChartObject->m_pChartData == NULL) ||
        !           791:                         m_pChartObject->m_pChartData->IsEmpty())
        !           792:                {
        !           793:                        delete m_pChartObject;
        !           794:                        m_pChartObject = NULL;
        !           795:                }
        !           796:        }
        !           797: 
        !           798:        // Update the frame menu and client area
        !           799:        //
        !           800:        UpdateMenu();
        !           801:        Invalidate(TRUE);
        !           802: }
        !           803: 
        !           804: // OnAbout:
        !           805: //
        !           806: void CChartWnd::OnAbout()
        !           807: {
        !           808:        CModalDialog aboutBox("AboutBox");
        !           809:        aboutBox.DoModal();
        !           810: }

unix.superglobalmegacorp.com

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