Beispiel #1
0
void CChartLineSerie::Draw(CDC* pDC)
{
    if (!m_bIsVisible)
        return;

    // If shadow is enabled, the all series must be redrawn.
    if (m_bShadow)
    {
        DrawAll(pDC);
        return;
    }

    if (pDC->GetSafeHdc())
    {
        CPen NewPen;
        if (m_iPenStyle != PS_SOLID)
        {
            LOGBRUSH lb;
            lb.lbStyle = BS_SOLID;
            lb.lbColor = m_ObjectColor;
            NewPen.CreatePen(PS_GEOMETRIC | m_iPenStyle, m_iLineWidth, &lb);
        }
        else
        {
            NewPen.CreatePen(m_iPenStyle, m_iLineWidth, m_ObjectColor);
        }
        CPen* pOldPen;

        pDC->SetBkMode(TRANSPARENT);
        //To have lines limited in the drawing rectangle :
        pDC->IntersectClipRect(m_ObjectRect);
        pOldPen = pDC->SelectObject(&NewPen);

        //Draw all points that haven't been drawn yet
        for (m_iLastDrawnPoint;m_iLastDrawnPoint<(int)GetPointsCount()-1;m_iLastDrawnPoint++)
        {
            //We don't draw a line between the origin and the first point -> we must have
            // a least 2 points before begining drawing
        //  if (m_vPoints<1)
        //      break;

            CPoint ScreenPoint;
            ValueToScreen(m_vPoints[m_iLastDrawnPoint].X,m_vPoints[m_iLastDrawnPoint].Y,ScreenPoint);
            pDC->MoveTo(ScreenPoint.x,ScreenPoint.y);

            ValueToScreen(m_vPoints[m_iLastDrawnPoint+1].X,m_vPoints[m_iLastDrawnPoint+1].Y,ScreenPoint);
            pDC->LineTo(ScreenPoint.x,ScreenPoint.y);
        }

        pDC->SelectClipRgn(NULL);
        pDC->SelectObject(pOldPen);
        DeleteObject(NewPen);
    }
}
void CChartLineSerie::Draw(CDC* pDC)
{
	if (!m_bIsVisible)
		return;

	// If shadow or smooth is enabled, then the complete series
	// must be redrawn.
	if (m_bShadow || m_bSmooth)
	{
		DrawAll(pDC);
		return;
	}

	if (pDC->GetSafeHdc())
	{
		CPen NewPen;
		if (m_iPenStyle != PS_SOLID)
		{
			LOGBRUSH lb;
			lb.lbStyle = BS_SOLID;
			lb.lbColor = m_SerieColor;
			NewPen.CreatePen(PS_GEOMETRIC | m_iPenStyle, m_iLineWidth, &lb);
		}
		else
		{
			NewPen.CreatePen(m_iPenStyle, m_iLineWidth, m_SerieColor);
		}
		CPen* pOldPen;

		pDC->SetBkMode(TRANSPARENT);
		//To have lines limited in the drawing rectangle :
		pDC->IntersectClipRect(m_pParentCtrl->GetPlottingRect());
		pOldPen = pDC->SelectObject(&NewPen);

		//Draw all points that haven't been drawn yet
		for (m_uLastDrawnPoint;m_uLastDrawnPoint<GetPointsCount()-1;m_uLastDrawnPoint++)
		{
			SChartXYPoint Point = GetPoint(m_uLastDrawnPoint);
			CPoint ScreenPoint;
			ValueToScreen(Point.X, Point.Y, ScreenPoint);
			pDC->MoveTo(ScreenPoint.x,ScreenPoint.y);

			Point = GetPoint(m_uLastDrawnPoint+1);
			ValueToScreen(Point.X, Point.Y, ScreenPoint);
			pDC->LineTo(ScreenPoint.x,ScreenPoint.y);
		}

		pDC->SelectClipRgn(NULL);
		pDC->SelectObject(pOldPen);
		DeleteObject(NewPen);
	}
}
bool CChartLineSerie::IsPointOnSerie(const CPoint& screenPoint, unsigned& uIndex) const
{
	uIndex = INVALID_POINT;
	if (!m_bIsVisible)
        return false;

	unsigned uFirst=0, uLast=0;
	if (!GetVisiblePoints(uFirst, uLast))
		return false;
	if (uFirst>0)
		uFirst--;
	if (uLast<GetPointsCount()-1)
		uLast++;

	bool bResult = false;
	for (unsigned i=uFirst ; i < uLast ; i++)
	{
		SChartXYPoint PointOrig = GetPoint(i);
		SChartXYPoint PointDest = GetPoint(i+1);
		CPoint ScreenPointOrig, ScreenPointDest;
		ValueToScreen(PointOrig.X, PointOrig.Y, ScreenPointOrig);
		ValueToScreen(PointDest.X, PointDest.Y, ScreenPointDest);

		if (IsNearLine(ScreenPointOrig.x, ScreenPointOrig.y, ScreenPointDest.x, ScreenPointDest.y, screenPoint.x, screenPoint.y))
		{
			// Check if the click is close to one of the two points.
			int xDist = abs(screenPoint.x - ScreenPointOrig.x);
			int yDist = abs(screenPoint.y - ScreenPointOrig.y);
			if (xDist<=5 && yDist<=5)
				uIndex = i;
			xDist = abs(screenPoint.x - ScreenPointDest.x);
			yDist = abs(screenPoint.y - ScreenPointDest.y);
			if (xDist<=5 && yDist<=5)
				uIndex = i+1;

			bResult = true;
			break;
		}
    }
    return bResult;
}
bool CChartCandlestickSerie::IsPointOnSerie(const CPoint& screenPoint,
											unsigned& uIndex) const
{
	uIndex = INVALID_POINT;
	if (!m_bIsVisible)
		return false;

	unsigned uFirst=0, uLast=0;
	if (!GetVisiblePoints(uFirst,uLast))
		return false;
	if (uFirst>0)
		uFirst--;
	if (uLast<GetPointsCount())
		uLast++;

	bool bResult = false;
	for (unsigned i=uFirst ; i < uLast ; i++)
	{
		SChartCandlestickPoint Point = GetPoint(i);
		int ScreenXVal = m_pHorizontalAxis->ValueToScreen(Point.XVal);
		int ScreenLow = m_pVerticalAxis->ValueToScreen(Point.Low);
		int ScreenHigh = m_pVerticalAxis->ValueToScreen(Point.High);

		int halfWidth = m_iCandlestickWidth/2;
		CRect Rectangle;
		if (ScreenLow > ScreenHigh)
			Rectangle.SetRect(ScreenXVal-halfWidth, ScreenHigh,
			ScreenXVal+halfWidth+1, ScreenLow+1);
		else
			Rectangle.SetRect(ScreenXVal-halfWidth, ScreenLow,
			ScreenXVal+halfWidth+1, ScreenHigh+1);
		if (Rectangle.PtInRect(screenPoint))
		{
			bResult = true;
			uIndex = i;
			break;
		}
	}
	return bResult;
}
void CChartCandlestickSerie::Draw(CDC* pDC)
{
	if (!m_bIsVisible)
		return;

	unsigned uFirst=0, uLast=0;
	if (!GetVisiblePoints(uFirst,uLast))
		return;

	if (pDC->GetSafeHdc())
	{
		ShadowBrush.CreateSolidBrush(m_ShadowColor);
		NewPen.CreatePen(PS_SOLID,1,m_SerieColor);
		ShadowPen.CreatePen(PS_SOLID,1,m_ShadowColor);
		BrushFill.CreateSolidBrush(m_SerieColor);
		BrushEmpty.CreateSolidBrush(RGB(255,255,255));

		int OldBkMode = pDC->SetBkMode(TRANSPARENT);
		//To have lines limited in the drawing rectangle :
		pDC->IntersectClipRect(m_PlottingRect);

		for (m_uLastDrawnPoint;m_uLastDrawnPoint<GetPointsCount();m_uLastDrawnPoint++)
		{
			SChartCandlestickPoint Point = GetPoint(m_uLastDrawnPoint);
			DrawCandleStick(pDC, Point);
		}

		pDC->SetBkMode(OldBkMode);
		pDC->SelectClipRgn(NULL);
		BrushFill.DeleteObject();
		BrushEmpty.DeleteObject();
		NewPen.DeleteObject();
		ShadowBrush.DeleteObject();
		ShadowPen.DeleteObject();
	}
}
void CChartSurfaceSerie::DrawAll(CDC* pDC)
{
	int iFirst=0, iLast=0;
	GetVisiblePoints(iFirst,iLast);

	if (iFirst>0)
		iFirst--;
	if (iLast<(int)GetPointsCount())
		iLast++;
	int iCount = iLast - iFirst;
	CPoint* pPoints = new CPoint[iCount+2];

	CBrush NewBrush;
	if (m_FillStyle == fsSolid)
		NewBrush.CreateSolidBrush(m_ObjectColor);
	else
	{
		int nIndex = 0;
		switch (m_FillStyle)
		{
		case fsHatchDownDiag:
			nIndex = HS_FDIAGONAL;
			break;
		case fsHatchUpDiag:
			nIndex = HS_BDIAGONAL;
			break;
		case fsHatchCross:
			nIndex = HS_CROSS;
			break;
		case fsHatchDiagCross:
			nIndex = HS_DIAGCROSS;
			break;
		case fsHatchHorizontal:
			nIndex = HS_HORIZONTAL;
			break;
		case fsHatchVertical:
			nIndex = HS_VERTICAL;
			break;
		}
		NewBrush.CreateHatchBrush(nIndex,m_ObjectColor);
	}

	CBrush* pOldBrush = pDC->SelectObject(&NewBrush);

	for (int i=iFirst; i<iLast; i++)
	{
		ValueToScreen(m_vPoints[i].X,m_vPoints[i].Y,pPoints[i-iFirst+1]);
	}

	if (m_bHorizontal)
	{
		pPoints[0].x = pPoints[1].x;
		pPoints[iCount+1].x = pPoints[iCount].x;

		double Position = m_pHorizontalAxis->GetPosition()/100.00;
		int AxisPos = m_ObjectRect.top + (int)(Position * (m_ObjectRect.bottom-m_ObjectRect.top));

		pPoints[0].y = AxisPos;
		pPoints[iCount+1].y = AxisPos;
	}
	else
	{
		pPoints[0].y = pPoints[1].y;
		pPoints[iCount+1].y = pPoints[iCount].y;

		double Position = m_pVerticalAxis->GetPosition()/100.00;
		int AxisPos = m_ObjectRect.left + (int)(Position * (m_ObjectRect.right-m_ObjectRect.left));

		pPoints[0].x = AxisPos;
		pPoints[iCount+1].x = AxisPos;
	}

	pDC->SetBkMode(TRANSPARENT);
	//To have lines limited in the drawing rectangle :
	CRect TempClipRect(m_ObjectRect);
	TempClipRect.DeflateRect(1,1);
	pDC->SetBkMode(TRANSPARENT);
	pDC->IntersectClipRect(TempClipRect);

	pDC->Polygon(pPoints,iCount+2);
	pDC->SelectClipRgn(NULL);
	pDC->SelectObject(pOldBrush);
	DeleteObject(NewBrush);

	delete[] pPoints;
}
void CChartPointsSerie::Draw(CDC *pDC)
{
	if (!m_bIsVisible)
		return;
	if (!pDC->GetSafeHdc())
		return;

	CBrush NewBrush(m_SerieColor);
	CPen BorderPen(PS_SOLID, 1, m_colBorder);
	CBrush ShadowBrush(m_ShadowColor);
	CPen ShadowPen(PS_SOLID, 1, m_ShadowColor);
	CPen* pOldPen = pDC->SelectObject(&BorderPen);
	CBrush* pOldBrush = pDC->SelectObject(&NewBrush);

	pDC->SetBkMode(TRANSPARENT);
	//To have lines limited in the drawing rectangle :
	pDC->IntersectClipRect(m_PlottingRect);

	//Draw all points that haven't been drawn yet
	for (m_uLastDrawnPoint;m_uLastDrawnPoint<(int)GetPointsCount();m_uLastDrawnPoint++)
	{
		SChartXYPoint Point = GetPoint(m_uLastDrawnPoint);
		CPoint ScreenPoint;
		ValueToScreen(Point.X, Point.Y, ScreenPoint);

		CRect PointRect;
		PointRect.SetRect(ScreenPoint.x-m_iXPointSize/2,ScreenPoint.y-m_iYPointSize/2,ScreenPoint.x+m_iXPointSize/2,ScreenPoint.y+m_iYPointSize/2);
		CRect ShadowRect = PointRect + CSize(m_iShadowDepth,m_iShadowDepth);

		switch(m_iPointType)
		{
		case ptEllipse:
			if (m_bShadow)
			{
				pOldPen = pDC->SelectObject(&ShadowPen);
				pDC->SelectObject(&ShadowBrush);
				pDC->Ellipse(ShadowRect);
				pDC->SelectObject(&NewBrush);
				pDC->SelectObject(&BorderPen);
			}
			pDC->Ellipse(PointRect);
			break;

		case ptRectangle:
			if (m_bShadow)
			{
				pOldPen = pDC->SelectObject(&ShadowPen);
				pDC->SelectObject(&ShadowBrush);
				pDC->Rectangle(ShadowRect);
				pDC->SelectObject(&NewBrush);
				pDC->SelectObject(&BorderPen);
			}
			pDC->Rectangle(PointRect);
			break;

		case ptTriangle:
			{
				CPoint TrPoints[3];
				TrPoints[0].x = PointRect.left;
				TrPoints[0].y = PointRect.bottom;
				TrPoints[1].x = PointRect.right;
				TrPoints[1].y = PointRect.bottom;
				TrPoints[2].x = PointRect.left + (int)fabs((PointRect.left-PointRect.right)/2.0);
				TrPoints[2].y = PointRect.top;

				if (m_bShadow)
				{
					CPoint ShadowPoints[3];
					for (int i=0;i<3;i++)
					{
						ShadowPoints[i] = TrPoints[i] + CSize(m_iShadowDepth,m_iShadowDepth);
					}

					pOldPen = pDC->SelectObject(&ShadowPen);
					pDC->SelectObject(&ShadowBrush);
					pDC->Polygon(ShadowPoints,3);
					pDC->SelectObject(&NewBrush);
					pDC->SelectObject(&BorderPen);
				}
				pDC->Polygon(TrPoints,3);
			}
			break;
		}

	}

	pDC->SelectClipRgn(NULL);
	pDC->SelectObject(pOldPen);
	pDC->SelectObject(pOldBrush);
	DeleteObject(BorderPen);
	DeleteObject(NewBrush);
	DeleteObject(ShadowBrush);
	DeleteObject(ShadowPen);
}
void CChartLineSerie::DrawAll(CDC *pDC)
{
	if (!m_bIsVisible)
		return;
	if (!pDC->GetSafeHdc())
		return;

	unsigned uFirst=0, uLast=0;
	if (!GetVisiblePoints(uFirst,uLast))
		return;

	if (uFirst>0)
		uFirst--;
	if (uLast<GetPointsCount()-1)
		uLast++;
	if (uLast-uFirst < 1)
		return;

	CPen NewPen;
	CPen ShadowPen;
	if (m_iPenStyle != PS_SOLID)
	{
		LOGBRUSH lb;
		lb.lbStyle = BS_SOLID;
		lb.lbColor = m_SerieColor;
		NewPen.CreatePen(PS_GEOMETRIC | m_iPenStyle, m_iLineWidth, &lb);
		lb.lbColor = m_ShadowColor;
		ShadowPen.CreatePen(PS_GEOMETRIC | m_iPenStyle, m_iLineWidth, &lb);
	}
	else
	{
		NewPen.CreatePen(m_iPenStyle, m_iLineWidth, m_SerieColor);
		ShadowPen.CreatePen(m_iPenStyle, m_iLineWidth, m_ShadowColor);
	}
	CPen* pOldPen;

	pDC->SetBkMode(TRANSPARENT);
	//To have lines limited in the drawing rectangle :
	pDC->IntersectClipRect(m_PlottingRect);
	pOldPen = pDC->SelectObject(&NewPen);

	if (m_bSmooth)
	{
		// For a Bezier curve, all points must be drawn.
		uFirst = 0;
		uLast = GetPointsCount() - 1;
		SChartXYPoint* pKnots = NULL;
		SChartXYPoint* pFirstControlPts = NULL;
		SChartXYPoint* pSecondControlPts = NULL;
		GetBezierControlPoints(uFirst,uLast,pKnots,pFirstControlPts,pSecondControlPts);

		unsigned Count = uLast - uFirst;
		CPoint* pBezierPts = new CPoint[3*(Count-1)+1];
		CPoint* pShadowPts = NULL;
		if (m_bShadow)
			pShadowPts = new CPoint[3*(Count-1)+1];

		unsigned index = 0;
		for (unsigned n=0; n<Count-1; n++)
		{
			ValueToScreen(pKnots[n].X, pKnots[n].Y, pBezierPts[index]);
			ValueToScreen(pFirstControlPts[n].X, pFirstControlPts[n].Y, pBezierPts[index+1]);
			ValueToScreen(pSecondControlPts[n].X, pSecondControlPts[n].Y, pBezierPts[index+2]);

			if (m_bShadow)
			{
				pShadowPts[index] = pBezierPts[index];
				pShadowPts[index].Offset(m_iShadowDepth,m_iShadowDepth);
				pShadowPts[index+1] = pBezierPts[index+1];
				pShadowPts[index+1].Offset(m_iShadowDepth,m_iShadowDepth);
				pShadowPts[index+2] = pBezierPts[index+2];
				pShadowPts[index+2].Offset(m_iShadowDepth,m_iShadowDepth);
			}
			index += 3;
		}
		ValueToScreen(pKnots[Count-1].X, pKnots[Count-1].Y, pBezierPts[index]);
		if (m_bShadow)
		{
			pShadowPts[index] = pBezierPts[index];
			pShadowPts[index].Offset(m_iShadowDepth,m_iShadowDepth);
			pDC->SelectObject(&ShadowPen);
			pDC->PolyBezier(pShadowPts,3*(Count-1)+1);
			pDC->SelectObject(&NewPen);
			delete[] pShadowPts;
		}
		pDC->PolyBezier(pBezierPts,3*(Count-1)+1);

		delete[] pKnots;
		delete[] pFirstControlPts;
		delete[] pSecondControlPts;
		delete[] pBezierPts;
	}
	else	// Non-smoothed curve
	{
		if (uLast-uFirst >= 1)
		{
			CPoint* pPoints = new CPoint[uLast-uFirst+1];
			CPoint* pShadow = NULL;
			if (m_bShadow)
				pShadow = new CPoint[uLast-uFirst+1];

			unsigned long pointsCount = 0;
			CPoint LastScreenPoint;
			for (m_uLastDrawnPoint=uFirst;m_uLastDrawnPoint<=uLast;m_uLastDrawnPoint++)
			{
				//We don't draw a line between the origin and the first point -> we must have
				// a least 2 points before begining drawing
				SChartXYPoint Point = GetPoint(m_uLastDrawnPoint);
				CPoint ScreenPoint;
				ValueToScreen(Point.X, Point.Y, ScreenPoint);

				if(LastScreenPoint != ScreenPoint)
				{
					//Only collate the unique points
					pPoints[pointsCount] = ScreenPoint;
					LastScreenPoint = ScreenPoint;

					if (m_bShadow)
					{
						ScreenPoint.Offset(m_iShadowDepth,m_iShadowDepth);
						pShadow[pointsCount] = ScreenPoint;
					}
					pointsCount++;
				}
			}

			// We have to do that in order for the Draw function to work properly.
			m_uLastDrawnPoint--;
			if (m_bShadow)
			{
				pDC->SelectObject(&ShadowPen);
				pDC->Polyline(pShadow, pointsCount);
			}
			pDC->SelectObject(&NewPen);
			pDC->Polyline(pPoints, pointsCount);

			delete[] pPoints;
			delete[] pShadow;
		}
	}

	pDC->SelectClipRgn(NULL);
	pDC->SelectObject(pOldPen);
	NewPen.DeleteObject();
	ShadowPen.DeleteObject();
}
BOOL CPolylineCreatorTracker::CreatePolyline(CWnd* pWnd, CDPoint point, CSnapper* pSnapper)
{
	// don't handle if capture already set
	if (::GetCapture() != NULL)
		return FALSE;

	AfxLockTempMaps();  // protect maps while looping

	m_bErase = FALSE;
	m_bFinalErase =  FALSE;

   	// set capture to the window which received this message
	pWnd->SetCapture();
	ASSERT(pWnd == CWnd::GetCapture());
	pWnd->UpdateWindow();

   m_Points.AddTail(new CDPOINT(point));
   CPoint LastPoint(point);

	// get DC for drawing
	CDC* pDrawDC;
		// otherwise, just use normal DC
	pDrawDC = pWnd->GetDC();
	ASSERT_VALID(pDrawDC);

	BOOL bMoved = FALSE;

	// get messages until capture lost or cancelled/accepted
	for (;;)
	{
		MSG msg;
		VERIFY(::GetMessage(&msg, NULL, 0, 0));

		if (CWnd::GetCapture() != pWnd)
			break;

      if(msg.message == WM_MOUSEMOVE)
			DispatchMessage(&msg);

		switch (msg.message)
		{
		// handle movement/accept messages
		case WM_MOUSEMOVE:
         {
			   // handle resize cases (and part of move)
            CPoint point;
            ::GetCursorPos(&point);
            pWnd->ScreenToClient(&point);

            if((::GetKeyState(VK_SHIFT) & 0x8000)!=0)
            {
               CDPoint *pLastPoint = (CDPoint*)m_Points.GetTail();
               if(pLastPoint!=NULL)
               {
                  CDPOINT ppp = CDPoint(point)-(*pLastPoint);
                  if(ABS(ppp.x)>ABS(ppp.y))
                     ppp.y=0;
                  else
                     ppp.x=0;
                  point = *pLastPoint+ppp;
               }
            }

            if(pSnapper!=NULL)
               pSnapper->FixSnapTo(&point);

			   if (LastPoint != point)
			   {
				   m_bErase = FALSE;
               DrawTracker(point, pDrawDC, pWnd);
               bMoved = TRUE;
			   }

            LastPoint = point;
         }
			break;

      case WM_LBUTTONDOWN:
         {
			   // handle resize cases (and part of move)
            CPoint point;
            ::GetCursorPos(&point);
            pWnd->ScreenToClient(&point);

            CDPoint dpoint(point);
            if((::GetKeyState(VK_SHIFT) & 0x8000)!=0)
            {
               CDPoint *pLastPoint = (CDPoint*)m_Points.GetTail();
               if(pLastPoint!=NULL)
               {
                  CDPOINT ppp = dpoint-(*pLastPoint);
                  if(ABS(ppp.x)>ABS(ppp.y))
                     ppp.y=0;
                  else
                     ppp.x=0;
                  dpoint = *pLastPoint+ppp;
               }
            }

            if(pSnapper!=NULL)
               pSnapper->FixSnapTo(&dpoint);
            point = dpoint;

			   if (LastPoint != dpoint)
			   {
				   m_bErase = FALSE;
               DrawTracker(point, pDrawDC, pWnd);
			   }

            m_Points.AddTail(new CDPoint(dpoint));

            //the tracker will not erease the last line
            if(m_PointsLast!=NULL)
               delete []m_PointsLast;
            bMoved = FALSE;

            m_PointsLast = NULL;

            LastPoint = point;
         }
         break;
		// handle cancel messages
		case WM_KEYDOWN:
			if (msg.wParam != VK_ESCAPE)
				break;
      case WM_LBUTTONDBLCLK:
      case WM_RBUTTONDOWN:
         {
			   if (bMoved)
			   {
				   m_bErase = m_bFinalErase = TRUE;
               DrawTracker(point, pDrawDC, pWnd);
			   }
            UINT uiCount = GetPointsCount();
            if(uiCount>1)//erace all the line
            {
               LPPOINT lpPoints = new POINT[uiCount];
               LPCDPOINT lpDPoints = new CDPOINT[uiCount];
               GetPoints(lpDPoints);
               for(UINT ui=0; ui<uiCount; ui++)
                  lpPoints[ui] = lpDPoints[ui];
               CLineTracker::DrawDragPolyLine(pDrawDC, lpPoints, 1, NULL, 1, uiCount);
               delete []lpPoints;
               delete []lpDPoints;
            }
         }
			goto ExitLoop;

		// just dispatch rest of the messages
		default:
			DispatchMessage(&msg);
			break;
		}
	}

ExitLoop:
	pWnd->ReleaseDC(pDrawDC);
	ReleaseCapture();

	AfxUnlockTempMaps(FALSE);

	// restore rect in case bMoved is still FALSE
	m_bFinalErase = FALSE;
	m_bErase = FALSE;

   // return TRUE only if rect has changed
	return GetPointsCount()>1;
}
Beispiel #10
0
void CChartLineSerie::DrawAll(CDC *pDC)
{
    if (!m_bIsVisible)
        return;

    int iFirst=0, iLast=0;
    GetVisiblePoints(iFirst,iLast);

    if (iFirst>0)
        iFirst--;
    if (iLast<(int)GetPointsCount()-1)
        iLast++;
    if (pDC->GetSafeHdc())
    {
        CPen NewPen;
        CPen ShadowPen;
        if (m_iPenStyle != PS_SOLID)
        {
            LOGBRUSH lb;
            lb.lbStyle = BS_SOLID;
            lb.lbColor = m_ObjectColor;
            NewPen.CreatePen(PS_GEOMETRIC | m_iPenStyle, m_iLineWidth, &lb);
            lb.lbColor = m_ShadowColor;
            ShadowPen.CreatePen(PS_GEOMETRIC | m_iPenStyle, m_iLineWidth, &lb);
        }
        else
        {
            NewPen.CreatePen(m_iPenStyle, m_iLineWidth, m_ObjectColor);
            ShadowPen.CreatePen(m_iPenStyle, m_iLineWidth, m_ShadowColor);
        }
        CPen* pOldPen;

        pDC->SetBkMode(TRANSPARENT);
        //To have lines limited in the drawing rectangle :
        pDC->IntersectClipRect(m_ObjectRect);
        pOldPen = pDC->SelectObject(&NewPen);

        for (m_iLastDrawnPoint=iFirst;m_iLastDrawnPoint<iLast;m_iLastDrawnPoint++)
        {
            //We don't draw a line between the origin and the first point -> we must have
            // a least 2 points before begining drawing

            CPoint ScreenPoint;

            if (m_bShadow)
            {
                pDC->SelectObject(&ShadowPen);
                ValueToScreen(m_vPoints[m_iLastDrawnPoint].X,m_vPoints[m_iLastDrawnPoint].Y,ScreenPoint);
                pDC->MoveTo(ScreenPoint.x+m_iShadowDepth,ScreenPoint.y+m_iShadowDepth);
                ValueToScreen(m_vPoints[m_iLastDrawnPoint+1].X,m_vPoints[m_iLastDrawnPoint+1].Y,ScreenPoint);
                pDC->LineTo(ScreenPoint.x+m_iShadowDepth,ScreenPoint.y+m_iShadowDepth);

                pDC->SelectObject(&NewPen);
            }

            ValueToScreen(m_vPoints[m_iLastDrawnPoint].X,m_vPoints[m_iLastDrawnPoint].Y,ScreenPoint);
            pDC->MoveTo(ScreenPoint.x,ScreenPoint.y);
            ValueToScreen(m_vPoints[m_iLastDrawnPoint+1].X,m_vPoints[m_iLastDrawnPoint+1].Y,ScreenPoint);
            pDC->LineTo(ScreenPoint.x,ScreenPoint.y);
        }

        pDC->SelectClipRgn(NULL);
        pDC->SelectObject(pOldPen);
        NewPen.DeleteObject();
        ShadowPen.DeleteObject();
    }
}