/***************************************************************************** * * Copyright (c) 1999, KL GROUP INC. All Rights Reserved. * http://www.klgroup.com * * This file is provided for demonstration and educational uses only. * Permission to use, copy, modify and distribute this file for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of KL Group not be used in advertising * or publicity pertaining to this material without the specific, * prior written permission of an authorized representative of * KL Group. * * KL GROUP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. KL GROUP SHALL NOT BE LIABLE FOR ANY * DAMAGES SUFFERED BY USERS AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ // ScrollTimeView.cpp : implementation of the CScrollTimeView class // #include #include #include #include "stdafx.h" #include "ScrollTime.h" #include "ScrollTimeDoc.h" #include "ScrollTimeView.h" #include "SplashDialog.h" //Olectra Chart Includes #include "Axis.h" #include "AxisCollection.h" #include "Border.h" #include "Chart2DData.h" #include "ChartArea.h" #include "ChartGroup.h" #include "ChartGroupCollection.h" #include "ChartLabel.h" #include "ChartLabelCollection.h" #include "DataCoord.h" #include "DerivedDouble.h" #include "DerivedLong.h" #include "Interior.h" #include "Label.h" #include "LabelCollection.h" #include "Location.h" #include "Marker.h" #include "MarkerCollection.h" #include "PlotArea.h" #include "TimeScale.h" #include "Title.h" #include "2dconst.h" #include "oc_color.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif TEMPS CScrollTimeView::m_TempRange[] = { {31, 5, 20}, //January {29, 10, 22}, {31, 18, 35}, {30, 33, 48}, {31, 45, 60}, {30, 55, 72}, {31, 62, 79}, {31, 60, 77}, {30, 55, 73}, {31, 48, 60}, {30, 32, 50}, {31, 10, 28}, }; ///////////////////////////////////////////////////////////////////////////// // CScrollTimeView IMPLEMENT_DYNCREATE(CScrollTimeView, CFormView) BEGIN_MESSAGE_MAP(CScrollTimeView, CFormView) //{{AFX_MSG_MAP(CScrollTimeView) ON_WM_CREATE() ON_WM_HSCROLL() ON_WM_DESTROY() ON_BN_CLICKED(IDC_UpOneZoom, OnUpOneZoom) ON_BN_CLICKED(IDC_ResetZoom, OnResetZoom) ON_WM_CTLCOLOR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Event sink for the Olectra Chart 2D Control (m_chart) ///////////////////////////////////////////////////////////////////////////// BEGIN_EVENTSINK_MAP(CScrollTimeView, CFormView) //{{AFX_EVENTSINK_MAP(CScrollTimeView) ON_EVENT(CScrollTimeView, IDC_CHART2D1, -605 /* MouseDown */, Chart_OnMouseDown, VTS_I2 VTS_I2 VTS_I4 VTS_I4) ON_EVENT(CScrollTimeView, IDC_CHART2D1, -606 /* MouseMove */, Chart_OnMouseMove, VTS_I2 VTS_I2 VTS_I4 VTS_I4) ON_EVENT(CScrollTimeView, IDC_CHART2D1, -607 /* MouseUp */, Chart_OnMouseUp, VTS_I2 VTS_I2 VTS_I4 VTS_I4) ON_EVENT(CScrollTimeView, IDC_CHART2D1, -601 /* DblClick */, Chart_OnDblClick, VTS_NONE) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() ///////////////////////////////////////////////////////////////////////////// // CScrollTimeView construction/destruction CScrollTimeView::CScrollTimeView() : CFormView(CScrollTimeView::IDD) { //{{AFX_DATA_INIT(CScrollTimeView) //}}AFX_DATA_INIT //Create a brush for the Background Color of the Window m_hBackColor.CreateSolidBrush( RGB(0, 128, 128) ); //AquaGreen } CScrollTimeView::~CScrollTimeView() { } void CScrollTimeView::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CScrollTimeView) DDX_Control(pDX, IDC_UpOneZoom, m_UpOneZoom); DDX_Control(pDX, IDC_ResetZoom, m_ResetZoom); DDX_Control(pDX, IDC_DATETEMP, m_lblDateTemp); DDX_Control(pDX, IDC_SCROLLBAR2, m_hScroll); DDX_Control(pDX, IDC_CHART2D1, m_chart); //}}AFX_DATA_MAP } BOOL CScrollTimeView::PreCreateWindow(CREATESTRUCT& cs) { return CFormView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CScrollTimeView diagnostics #ifdef _DEBUG void CScrollTimeView::AssertValid() const { CFormView::AssertValid(); } void CScrollTimeView::Dump(CDumpContext& dc) const { CFormView::Dump(dc); } CScrollTimeDoc* CScrollTimeView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CScrollTimeDoc))); return (CScrollTimeDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CScrollTimeView message handlers ///////////////////////////////////////////////////////////////////////////// // This is where it all begins ///////////////////////////////////////////////////////////////////////////// int CScrollTimeView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFormView::OnCreate(lpCreateStruct) == -1) return -1; m_bDoubleClickCapture = false; m_bMaxZoomsReached = false; m_StartPoint.x = -1; m_StartPoint.y = -1; m_EndPoint.x = -1; m_EndPoint.y = -1; return 0; } ///////////////////////////////////////////////////////////////////////////// // Do some Setup that only occurs once ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::OnInitialUpdate() { CFormView::OnInitialUpdate(); // Initialize the Random Number Generator using the Timer srand( (unsigned)time( NULL ) ); // Pre-Define some variables for easier reference later m_cGroup = m_chart.GetChartGroups().GetItem(COleVariant(short(1))); m_AxisX = m_chart.GetChartArea().GetAxes().GetItem(COleVariant("x")); m_AxisY = m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y")); m_MarkerX = m_chart.GetChartArea().GetMarkers().GetItem(COleVariant("x")); // Set the mouse cursor to an HourGlass BeginWaitCursor(); // Create a splash screen so users know we are doing something CScrollTimeApp* ScrTime = (CScrollTimeApp*)AfxGetApp(); ScrTime->m_splash.Create(this); ScrTime->m_splash.ShowWindow(SW_SHOW); ScrTime->m_splash.UpdateWindow(); // Generate the data GenerateTimeData(); // Store the number of points that were generated m_TotalPoints = m_cGroup.GetData().GetNumPoints(1); // Set the initial zoom values m_StoredZooms[0][0] = 1; m_StoredZooms[0][1] = m_TotalPoints; SetZoom(0); // Store the values of the Chart for use when drawing the Rubber Band rectangle m_MyRect.top = m_chart.GetChartArea().GetLocation().GetTop().GetValue() + m_chart.GetChartArea().GetPlotArea().GetTop().GetValue(); m_MyRect.left = m_chart.GetChartArea().GetLocation().GetLeft().GetValue() + m_chart.GetChartArea().GetPlotArea().GetLeft().GetValue(); m_MyRect.bottom = (m_chart.GetChartArea().GetLocation().GetTop().GetValue() + m_chart.GetChartArea().GetLocation().GetHeight().GetValue()) - m_chart.GetChartArea().GetPlotArea().GetBottom().GetValue() - m_chart.GetChartArea().GetBorder().GetWidth(); m_MyRect.right = (m_chart.GetChartArea().GetLocation().GetLeft().GetValue() + m_chart.GetChartArea().GetLocation().GetWidth().GetValue()) - m_chart.GetChartArea().GetPlotArea().GetRight().GetValue() - m_chart.GetChartArea().GetBorder().GetWidth(); // Setup the Marker m_MarkerX.SetMethod(oc2dMarkerDataCoord); m_MarkerX.GetValue().SetX(1E+308); m_MarkerX.SetIsShowing(true); // Rotate the axis labels m_AxisY.SetAnnotationRotationAngle(45); m_chart.GetChartArea().GetAxes().GetItem(COleVariant("y2")).SetAnnotationRotationAngle(315); // Set up the footer area in case there's an error to report m_chart.GetFooter().GetInterior().SetBackgroundColor(RGB(0xFF, 0xFF, 0xFF)); m_chart.GetFooter().GetInterior().SetForegroundColor(RGB(0xFF, 0, 0)); m_chart.GetFooter().GetBorder().SetType(oc2dBorderPlain); m_chart.GetFooter().GetBorder().SetWidth(4); //Remove the splash screen as we are done generating the data ScrTime->m_splash.DestroyWindow(); // Set the mouse cursor back to its default state EndWaitCursor(); } ///////////////////////////////////////////////////////////////////////////// // Create temperature data once an hour that falls within a reasonable range ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::GenerateTimeData() { long Start, End, NumPoints; // Start Time "01/01/1995 12:00:00AM" Start = mktime(Convert_Time(95, 0, 1, 0, 0, 0)); // End Time "01/01/1996 12:00:00AM" End = mktime(Convert_Time(96, 0, 1, 0, 0, 0)) / HOURS; NumPoints = End - (Start / HOURS) + 1; // Setup the Time Axis information m_AxisX.SetAnnotationMethod(oc2dAnnotateTimeLabels); m_AxisX.GetTimeScale().SetUnit(oc2dTimeHours); m_AxisX.GetTimeScale().SetBase(COleDateTime(Start)); // Store the Start Date for later use m_BaseTime = Start; // Batch the updates to the Chart and the Data Object m_chart.SetIsBatched(true); m_cGroup.GetData().SetIsBatched(true); // Set the number of Series and Points m_cGroup.GetData().SetNumSeries(1); m_cGroup.GetData().SetNumPoints(1, NumPoints); // Create the data and put it into the Chart for (int i = 1; i <= NumPoints; i++) { m_cGroup.GetData().SetX(1, i, (i - 1)); m_cGroup.GetData().SetY(1, i, (GenTemp(i - 1))); } // Go back to normal updates on the Chart and Data Object m_cGroup.GetData().SetIsBatched(false); m_chart.SetIsBatched(false); } ///////////////////////////////////////////////////////////////////////////// // Generate a reasonable Temperature for this hour ///////////////////////////////////////////////////////////////////////////// double CScrollTimeView::GenTemp(long XValue) { time_t tval; int Hi, Lo; int m1, m2; struct tm *tm; static int Last_YDay = -1; static double Fudge = 1; static double DHi, DLo; static double Temp; tval = XValue * HOURS; tm = localtime(&tval); if( tm == NULL ) { // Bad date! return 0.0; } Lo = m_TempRange[tm->tm_mon].Lo; Hi = m_TempRange[tm->tm_mon].Hi; m1 = tm->tm_mon; m2 = (m1 + 1)%12; // Start floating towards the next months range. // Fudge the values by +- 20%, giving the actual range for this day. // Note that we must only generate one fudge factor per day. if (tm->tm_yday != Last_YDay) { // Generate the Fudge value Fudge = VRAND(20.0) / 100.0; // Create a new Hi temperature DHi = (float)m_TempRange[m1].Hi + ((float)(m_TempRange[m2].Hi - m_TempRange[m1].Hi)) * (tm->tm_mday - 1.0) / m_TempRange[m1].NDays; //If the last day has not been initialized yet, create a low temperature if (Last_YDay == -1) { DLo = (float)m_TempRange[m1].Lo + ( (float)(m_TempRange[m2].Lo - m_TempRange[m1].Lo) ) * (tm->tm_mday - 1.0) / m_TempRange[m1].NDays; DLo = DLo * (1.0 + Fudge); } else { // Carry forward the last temperature DLo = Temp; } DHi = DHi * (1.0 + Fudge); Last_YDay = tm->tm_yday; } // Usually hottest about 2PM if (tm->tm_hour < 14) { Temp = (DLo + (tm->tm_hour / 14.0) * (DHi - DLo)); } else { Temp = (DHi - ((tm->tm_hour - 14.0) / 10.0) * (DHi - DLo)); } // Actual temperature we pick can vary by 5% of range Temp += (VRAND(5.0) - 2.5); return(Temp); } ///////////////////////////////////////////////////////////////////////////// // Convert a Date & Time to its numeric equivalent ///////////////////////////////////////////////////////////////////////////// struct tm* CScrollTimeView::Convert_Time(int y, int m, int d, int h, int mn, int s) { static struct tm ltime; ltime.tm_year = y; ltime.tm_mon = m; ltime.tm_mday = d; ltime.tm_hour = h; ltime.tm_min = mn; ltime.tm_sec = s; ltime.tm_isdst = -1; return(<ime); } ///////////////////////////////////////////////////////////////////////////// // A Random number Generator ///////////////////////////////////////////////////////////////////////////// double CScrollTimeView::VRAND(double Range) { double Answer; Answer = ((Range * (rand() / ((double)RAND_MAX - 1)))); return Answer; } ///////////////////////////////////////////////////////////////////////////// // Figure out the range of data the graph needs to display and display it. // Figure out what the data range is and format a label at the top // of the Chart to reflect the range appropriately. ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::SetDataRange(int First, int Last) { double XMin, XMax; int len; char *Format; char szTitle[80]; CString rFormat; time_t mid_time; struct tm* ptm_s; // Batch all the updates to the Chart m_chart.SetIsBatched(true); // Reset the Axis Min and Max values m_AxisX.GetMin().SetValue(First - 1); m_AxisX.GetMax().SetValue(Last - 1); m_HScrollLargePageValue = Last - First + 1; // Update the Scrollbar range m_hScroll.SetScrollRange(1, (m_TotalPoints - (Last - First)), true); m_hScroll.SetScrollPos(First, true); XMin = m_AxisX.GetMin().GetValue(); XMax = m_AxisX.GetMax().GetValue(); // Set the format of the label shown at the top of the Chart based on // the number of points that are visible len = (int) (Last - First); if (len <= DAY) { Format = "%A %B %d"; } else { if (len <= (2 * WEEK)) { Format = "%B Week # %W"; } else { if (len <= MONTH) { Format = "%B %Y"; } else { Format = "%Y"; } } } // Update the label at the top of the chart mid_time = DataToSeconds((int)First + (len / 2)); ptm_s = localtime(&mid_time); if( ptm_s != NULL ) { strftime(szTitle, 80, Format, ptm_s); rFormat = szTitle; } CChartLabel cLbl(m_chart.GetChartLabels().GetItem(COleVariant("Title"))); cLbl.SetIsBatched(true); cLbl.GetText().SetText(rFormat); cLbl.GetAttachDataCoord().SetX((XMin + XMax) / 2.0); cLbl.GetAttachDataCoord().SetY(m_AxisY.GetMax().GetValue()); cLbl.SetIsBatched(false); // Go back to normal Chart updates m_chart.SetIsBatched(false); } ///////////////////////////////////////////////////////////////////////////// // Convert the passed value to seconds ///////////////////////////////////////////////////////////////////////////// time_t CScrollTimeView::DataToSeconds(int Hours) { return (m_BaseTime + (int)(Hours / SECOND)); } ///////////////////////////////////////////////////////////////////////////// // Set the Zoom Level ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::SetZoom(long Level) { SetDataRange(m_StoredZooms[Level][0], m_StoredZooms[Level][1]); m_CurrentZoom = Level; // Update the Zoom related controls if (m_CurrentZoom == 0) { m_hScroll.EnableScrollBar(ESB_DISABLE_BOTH); m_UpOneZoom.EnableWindow(false); m_ResetZoom.EnableWindow(false); } else { m_hScroll.EnableScrollBar(ESB_ENABLE_BOTH); m_UpOneZoom.EnableWindow(true); m_ResetZoom.EnableWindow(true); } } ///////////////////////////////////////////////////////////////////////////// // Code for dealing the ScrollBar events ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (m_CurrentZoom != 0) { SCROLLINFO si; long MinValue, MaxValue; // Initialize the SCROLLINFO structure ZeroMemory(&si, sizeof(SCROLLINFO)); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_TRACKPOS; // Call GetScrollInfo to get current tracking // position in si.nTrackPos if (!pScrollBar->GetScrollInfo(&si, SIF_ALL) ) { return; // GetScrollInfo failed } switch(nSBCode) { // Move 1 unit to the left case SB_LINELEFT: if ((si.nPos - 1) >= si.nMin) { // Decrement the current Position by 1 unit si.nPos = si.nPos - 1; // Update the ScrollBar with the new Position m_hScroll.SetScrollPos(si.nPos); // Update the Text Box with the new ScrollBar Position } break; // Move 1 unit to the right case SB_LINERIGHT: if ((si.nPos + 1) <= si.nMax) { si.nPos = si.nPos + 1; m_hScroll.SetScrollPos(si.nPos); } break; // Move a page of units to the left case SB_PAGELEFT: si.nPage = m_HScrollLargePageValue; if ((int)(si.nPos - si.nPage) >= si.nMin) { si.nPos = si.nPos - si.nPage; } else { si.nPos = si.nMin; } m_hScroll.SetScrollPos(si.nPos); si.nPage = 0; break; // Move a page of units to the right case SB_PAGERIGHT: si.nPage = m_HScrollLargePageValue; if ((int)(si.nPos + si.nPage) <= si.nMax) { si.nPos = si.nPos + si.nPage; } else { si.nPos = si.nMax; } m_hScroll.SetScrollPos(si.nPos); si.nPage = 0; break; // User is using the 'Thumb' so update dynamically case SB_THUMBTRACK: m_hScroll.SetScrollPos(nPos); break; // The Scroll operation has finished so do one last update case SB_ENDSCROLL: m_hScroll.SetScrollInfo(&si); MinValue = si.nPos; MaxValue = si.nPos + m_HScrollLargePageValue - 1; if (MaxValue > m_TotalPoints) { MaxValue = m_TotalPoints; MinValue = MaxValue - m_HScrollLargePageValue + 1; } if (MinValue < 1) { MinValue = 1; MaxValue = m_HScrollLargePageValue - 1; } SetDataRange(MinValue, MaxValue); break; default: break; } CFormView::OnHScroll(nSBCode, nPos, pScrollBar); } } ///////////////////////////////////////////////////////////////////////////// // The user has pressed a mouse button on the Chart, if it is the left button // then store some information as the user has begun to select an area to zoom // in on. ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::Chart_OnMouseDown(short Button, short Shift, long x, long y) { if ((Button == 1) && !m_bDoubleClickCapture) { if ((x < m_MyRect.left) || (x > m_MyRect.right)) { m_StartPoint.x = -1; m_StartPoint.y = -1; m_EndPoint.x = -1; m_EndPoint.y = -1; return; } if ((y < m_MyRect.top) || (y > m_MyRect.bottom)) { m_StartPoint.x = -1; m_StartPoint.y = -1; m_EndPoint.x = -1; m_EndPoint.y = -1; return; } // If we have reached the maximum number of zooms, let the user know if ((m_CurrentZoom + 1) == MAXSTOREDZOOMS) { m_bMaxZoomsReached = true; m_chart.GetFooter().GetText().SetText("Maximum Zooms Reached!"); MessageBeep(-1); return; } long Row, Col, Distance; // Get the resources needed to draw the highlight CClientDC dcChart( &m_chart ); CPen* ppenOld = (CPen*)dcChart.SelectStockObject( BLACK_PEN ); dcChart.SetROP2(R2_NOTXORPEN); // Set the starting points for the Rubber Band m_StartPoint.x = x; m_StartPoint.y = m_MyRect.top + 1; m_EndPoint.x = x; m_EndPoint.y = m_MyRect.bottom - 1; m_InvRect.left = m_StartPoint.x; m_InvRect.top = m_StartPoint.y; m_InvRect.right = m_EndPoint.x; m_InvRect.bottom = m_EndPoint.y; // Store the start of the zoom location m_CurrentZoom += 1; m_cGroup.CoordToDataIndex(m_StartPoint.x, m_StartPoint.y, oc2dFocusX, &Row, &Col, &Distance); m_StoredZooms[m_CurrentZoom][0] = Col; // Turn the Marker Off m_MarkerX.SetIsShowing(false); // Draw the Rubber Band Rectangle Rectangle(dcChart, m_StartPoint.x, m_StartPoint.y, m_EndPoint.x, m_EndPoint.y); InvertRect(dcChart, &m_InvRect); // Release the Pen resources back to the system dcChart.SelectObject(ppenOld); } } ///////////////////////////////////////////////////////////////////////////// // The user is moving the mouse over the Chart. If there are no buttons // pressed, then update a label at the top with the information from the // point the mouse is currently over, otherwise update the selection rectangle. ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::Chart_OnMouseMove(short Button, short Shift, long x, long y) { long XIndex; double XVal, YVal; COleDateTime XDate; CString csDateTime; CString csTimeZone; CString csLabelText; char szBuffer[80]; // If the left mouse button is not pressed, then have the marker follow the // mouse cursor while it is over the Chart if ((Button == 0) || m_bMaxZoomsReached) { m_cGroup.CoordToDataCoord(x, y, &XVal, &YVal); if (XVal != 1E+308) { XIndex = (int)(XVal - m_cGroup.GetData().GetX(1, 1)) + 1; if ((XIndex >= 1) && (XIndex <= m_cGroup.GetData().GetNumPoints(1))) { // Update the contents of the label in the upper left hand corner of the // window to represent the data value that the mouse is currently over XDate = m_AxisX.GetTimeScale().ValueToDate(XVal); sprintf(szBuffer, " : %.0f\260F", m_cGroup.GetData().GetY(1, XIndex)); csDateTime = m_AxisX.GetTimeScale().FormatDate(XDate, "%b %d %y - %I:00%p "); csTimeZone = m_AxisX.GetTimeScale().FormatDate(XDate, "%Z"); csLabelText = csDateTime + szBuffer + "\n" + csTimeZone; m_lblDateTemp.SetWindowText(csLabelText); } } // Update the location of the marker m_MarkerX.GetValue().SetX(XVal); } // If the left mouse button has been pressed and we are within the confines of the // Chart area then update the values of the Rubber Band rectangle if ((Button == 1) && (m_StartPoint.x > -1) && !m_bDoubleClickCapture && !m_bMaxZoomsReached) { // Get the resources needed to draw the highlight CClientDC dcChart( &m_chart ); CPen* ppenOld = (CPen*)dcChart.SelectStockObject( BLACK_PEN ); dcChart.SetROP2(R2_NOTXORPEN); // Draw the Rubber Band Rectangle InvertRect(dcChart, &m_InvRect); Rectangle(dcChart, m_StartPoint.x, m_StartPoint.y, m_EndPoint.x, m_EndPoint.y); // Make sure we are within the bounds of the Chart and set the m_EndPoint // of the Rubber Band rectangle accordingly if ((y > m_MyRect.top) && (y < m_MyRect.bottom)) { if ((x > m_MyRect.left) && (x < m_MyRect.right)) { m_EndPoint.x = x; } m_EndPoint.y = m_MyRect.bottom - 1; m_InvRect.right = m_EndPoint.x; m_InvRect.bottom = m_EndPoint.y; } // Draw the Rubber Band Rectangle Rectangle(dcChart, m_StartPoint.x, m_StartPoint.y, m_EndPoint.x, m_EndPoint.y); InvertRect(dcChart, &m_InvRect); // Release the Pen resources back to the system dcChart.SelectObject(ppenOld); } } ///////////////////////////////////////////////////////////////////////////// // The user has finished creating the selection rectangle, so do the zoom. ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::Chart_OnMouseUp(short Button, short Shift, long x, long y) { if ((Button == 1) && (m_StartPoint.x > -1) && !m_bDoubleClickCapture && !m_bMaxZoomsReached) { long ZHold; COleDateTime XDate; long Row, Col, Distance; // Get the resources needed to draw the highlight CClientDC dcChart( &m_chart ); CPen* ppenOld = (CPen*)dcChart.SelectStockObject( BLACK_PEN ); dcChart.SetROP2(R2_NOTXORPEN); // Draw the Rubber Band Rectangle InvertRect(dcChart, &m_InvRect); Rectangle(dcChart, m_StartPoint.x, m_StartPoint.y, m_EndPoint.x, m_EndPoint.y); if ((x > m_MyRect.left) && (x < m_MyRect.right)) { m_EndPoint.x = x; } m_EndPoint.y = m_MyRect.bottom - 1; m_InvRect.right = m_EndPoint.x; m_InvRect.bottom = m_EndPoint.y; // Draw the Rubber Band Rectangle Rectangle(dcChart, m_StartPoint.x, m_StartPoint.y, m_EndPoint.x, m_EndPoint.y); InvertRect(dcChart, &m_InvRect); // Store the end of the zoom location m_cGroup.CoordToDataIndex(m_EndPoint.x, m_EndPoint.y, oc2dFocusX, &Row, &Col, &Distance); m_StoredZooms[m_CurrentZoom][1] = Col; if (m_StoredZooms[m_CurrentZoom][0] > m_StoredZooms[m_CurrentZoom][1]) { ZHold = m_StoredZooms[m_CurrentZoom][0]; m_StoredZooms[m_CurrentZoom][0] = m_StoredZooms[m_CurrentZoom][1]; m_StoredZooms[m_CurrentZoom][1] = ZHold; } if ((m_StoredZooms[m_CurrentZoom][1] - m_StoredZooms[m_CurrentZoom][0]) > 1) { // Temporarily turn the Marker Off m_MarkerX.SetIsShowing(false); // Do the Zoom SetZoom(m_CurrentZoom); } else { m_CurrentZoom -= 1; // Draw the Rubber Band Rectangle Rectangle(dcChart, m_StartPoint.x, m_StartPoint.y, m_EndPoint.x, m_EndPoint.y); InvertRect(dcChart, &m_InvRect); } // Make sure the marker is showing m_MarkerX.SetIsShowing(true); // Release the Pen resources back to the system dcChart.SelectObject(ppenOld); } else { // Reset the DoubleClick capture m_bDoubleClickCapture = false; } } ///////////////////////////////////////////////////////////////////////////// // The form is being destroyed, so release some create resources ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::OnDestroy() { CFormView::OnDestroy(); // Release the global variables m_cGroup.DetachDispatch(); m_AxisX.DetachDispatch(); m_AxisY.DetachDispatch(); m_MarkerX.DetachDispatch(); } ///////////////////////////////////////////////////////////////////////////// // Go back one zoom level ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::OnUpOneZoom() { // If we have zoomed in, go back the the previous zoom level if (m_CurrentZoom > 0) { SetZoom(m_CurrentZoom - 1); } if (m_bMaxZoomsReached) { m_bMaxZoomsReached = false; m_chart.GetFooter().GetText().SetText(""); } } ///////////////////////////////////////////////////////////////////////////// // Reset the zoom to where the Chart started ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::OnResetZoom() { // Temporarily turn off the Marker m_MarkerX.SetIsShowing(false); // Reset the graph to where we started SetZoom(0); // Resume drawing the marker m_MarkerX.SetIsShowing(true); if (m_bMaxZoomsReached) { m_bMaxZoomsReached = false; m_chart.GetFooter().GetText().SetText(""); } } ///////////////////////////////////////////////////////////////////////////// // Change the background color of the Window and the Label control ///////////////////////////////////////////////////////////////////////////// HBRUSH CScrollTimeView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if( ( pWnd == this ) || ( pWnd->GetDlgCtrlID() == IDC_DATETEMP ) ) { pDC->SetBkColor( RGB( 0, 128, 128 ) ); pDC->SetTextColor( RGB(255, 255, 0) ); return m_hBackColor; } else { return NULL; } } ///////////////////////////////////////////////////////////////////////////// // Capture the Double-Click event so we can ignore it. ///////////////////////////////////////////////////////////////////////////// void CScrollTimeView::Chart_OnDblClick() { // Let the mouse events know that a Double-Click occured m_bDoubleClickCapture = true; }