⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oscopectrl.cpp

📁 非常难得的eMule(电骡) V0.45b 源码下载 值得研究
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	
	m_brushBack.DeleteObject();
	m_brushBack.CreateSolidBrush(m_crBackColor);
	
	// clear out the existing garbage, re-start with a clean plot
	InvalidateCtrl();
}  // SetBackgroundColor

/////////////////////////////////////////////////////////////////////////////
void COScopeCtrl::InvalidateCtrl(bool deleteGraph)
{
	// There is a lot of drawing going on here - particularly in terms of 
	// drawing the grid.  Don't panic, this is all being drawn (only once)
	// to a bitmap.  The result is then BitBlt'd to the control whenever needed.
	int i, j, GridPos;
	int nCharacters;
	
	CPen *oldPen;
	CPen solidPen(PS_SOLID, 0, m_crGridColor);
	CFont axisFont, yUnitFont, *oldFont, LegendFont;
	CString strTemp;
	
	// in case we haven't established the memory dc's
	CClientDC dc(this);  
	
	// if we don't have one yet, set up a memory dc for the grid
	if(m_dcGrid.GetSafeHdc() == NULL)
	{
		m_dcGrid.CreateCompatibleDC(&dc);
		m_bitmapGrid.DeleteObject();
		m_bitmapGrid.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight);
		m_pbitmapOldGrid = m_dcGrid.SelectObject(&m_bitmapGrid);
	}
	
	m_dcGrid.SetBkColor(m_crBackColor);
	
	// fill the grid background
	m_dcGrid.FillRect(m_rectClient, &m_brushBack);
	
	// draw the plot rectangle:
	// determine how wide the y axis scaling values are
	double fAbsUpperLimit = fabs(m_PlotData[0].dUpperLimit);
	if (fAbsUpperLimit > 0.0)
		nCharacters = abs((int)log10(fAbsUpperLimit));
	else
		nCharacters = 0;

	double fAbsLowerLimit = fabs(m_PlotData[0].dLowerLimit);
	if (fAbsLowerLimit > 0.0)
		nCharacters = max(nCharacters, abs((int)log10(fAbsLowerLimit)));
	
	// add the units digit, decimal point and a minus sign, and an extra space
	// as well as the number of decimal places to display
	nCharacters = nCharacters + 4 + m_nYDecimals;  
	
	// adjust the plot rectangle dimensions
	// assume 6 pixels per character (this may need to be adjusted)
	// Changed this so that the Y-Units wouldn't overlap the Y-Scale.
	m_rectPlot.left = m_rectClient.left + 8*7+4;//(nCharacters) ;
	m_nPlotWidth    = m_rectPlot.Width();
	
	// draw the plot rectangle
	oldPen = m_dcGrid.SelectObject(&solidPen); 
	m_dcGrid.MoveTo(m_rectPlot.left, m_rectPlot.top);
	m_dcGrid.LineTo(m_rectPlot.right + 1, m_rectPlot.top);
	m_dcGrid.LineTo(m_rectPlot.right + 1, m_rectPlot.bottom + 1);
	m_dcGrid.LineTo(m_rectPlot.left, m_rectPlot.bottom + 1);
	m_dcGrid.LineTo(m_rectPlot.left, m_rectPlot.top);
	m_dcGrid.SelectObject(oldPen); 
	
	// draw the dotted lines, 
	// use SetPixel instead of a dotted pen - this allows for a 
	// finer dotted line and a more "technical" look
	// G.Hayduk: added configurable number of grids
	for(j = 1; j < (m_nYGrids + 1); j++)
	{
		GridPos = m_rectPlot.Height()*j/ (m_nYGrids + 1) + m_rectPlot.top;
		for(i = m_rectPlot.left; i < m_rectPlot.right; i += 4)
			m_dcGrid.SetPixel(i, GridPos, m_crGridColor);
	}
	
	if (thePrefs.m_bShowVerticalHourMarkers) {
		// CB Mod ---> Vertical lines
		  
		// Add vertical reference lines in the graphs. Each line indicates an elapsed hour from the current
		// time (extreme right of the graph).
		// Lines are always right aligned and the gap scales accordingly to the user horizontal scale.
		// Intervals of 10 hours are marked with slightly stronger lines that go beyond the bottom border.
		int hourSize, partialSize, surplus=0, extra=0;

		if (m_nXGrids > 0) {
			hourSize = (3600*m_rectPlot.Width())/(3600*m_nXGrids + m_nXPartial); // Size of an hour in pixels
			partialSize = m_rectPlot.Width() - hourSize*m_nXGrids;
			if (partialSize >= hourSize) {
			partialSize = (hourSize*m_nXPartial)/3600; // real partial size
			surplus = m_rectPlot.Width() - hourSize*m_nXGrids - partialSize; // Pixel surplus
			}

			GridPos = 0;
			for(j = 1; j <= m_nXGrids; j++) {
			extra = 0;
			if (surplus) {
				surplus--;
				extra=1;
			}
			GridPos += (hourSize+extra);
			if ((m_nXGrids-j+1)%10 == 0) {
				for(i = m_rectPlot.top; i < m_rectPlot.bottom; i += 2)
				m_dcGrid.SetPixel(m_rectPlot.left + GridPos - hourSize + partialSize, i, m_crGridColor);
			} else {
				for(i = m_rectPlot.top; i < m_rectPlot.bottom; i += 4)
				m_dcGrid.SetPixel(m_rectPlot.left + GridPos - hourSize + partialSize, i, m_crGridColor);
			}
			}
		}
		// CB Mod <---
	}

	// create some fonts (horizontal and vertical)
	// ---
	//  *)	Using "Arial" or "MS Sans Serif" gives a more accurate small font,
	//		but does not work for Korean fonts.
	//	*)	Using "MS Shell Dlg" gives somewhat less accurate small fonts, but
	//		does work for all languages which are currently supported by eMule.
	axisFont.CreatePointFont(8*10, _T("MS Shell Dlg")); // 8pt 'MS Shell Dlg' -- this shall be available on all Windows systems..
	yUnitFont.CreateFont(FontPointSizeToLogUnits(8*10), 0, 900, 900, FW_NORMAL, FALSE, FALSE, 0, DEFAULT_CHARSET,
						 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("MS Shell Dlg"));

	// grab the horizontal font
	oldFont = m_dcGrid.SelectObject(&axisFont);
	
	// y max
	m_dcGrid.SetTextColor(m_crGridColor);
	m_dcGrid.SetTextAlign(TA_RIGHT | TA_TOP);
	if(m_str.YMax.IsEmpty())
		strTemp.Format(_T("%.*lf"), m_nYDecimals, m_PlotData[0].dUpperLimit);
	else
		strTemp = m_str.YMax;
	m_dcGrid.TextOut(m_rectPlot.left - 4, m_rectPlot.top - 7, strTemp);
	
    if(m_rectPlot.Height()/(m_nYGrids+1) >= 14) {
	    for(j = 1; j < (m_nYGrids + 1); j++) {
		    GridPos = m_rectPlot.Height()*j/ (m_nYGrids + 1) + m_rectPlot.top;

    	    strTemp.Format(_T("%.*lf"), m_nYDecimals, m_PlotData[0].dUpperLimit*(m_nYGrids-j+1)/(m_nYGrids+1));
    	    m_dcGrid.TextOut(m_rectPlot.left - 4, GridPos-7, strTemp);
        }
    } else {
	    // y/2
	    strTemp.Format(_T("%.*lf"), m_nYDecimals, m_PlotData[0].dUpperLimit / 2);
	    m_dcGrid.TextOut(m_rectPlot.left - 2, m_rectPlot.bottom+ ((m_rectPlot.top - m_rectPlot.bottom)/2) - 7 , strTemp);
    }	
	
	// y min
	if(m_str.YMin.IsEmpty())
		strTemp.Format(_T("%.*lf"), m_nYDecimals, m_PlotData[0].dLowerLimit);
	else
		strTemp = m_str.YMin;
	m_dcGrid.TextOut(m_rectPlot.left - 4, m_rectPlot.bottom-7, strTemp);

	// x units
	m_dcGrid.SetTextAlign(TA_RIGHT | TA_BOTTOM);
	m_dcGrid.TextOut (m_rectClient.right-2,m_rectClient.bottom-2,m_str.XUnits);

	// restore the font
	m_dcGrid.SelectObject(oldFont);
	
	// y units
	oldFont = m_dcGrid.SelectObject(&yUnitFont);
	m_dcGrid.SetTextAlign(TA_CENTER | TA_BASELINE);
	
	CRect rText(0,0,0,0);
	m_dcGrid.DrawText(m_str.YUnits, rText, DT_CALCRECT);
	m_dcGrid.TextOut ((m_rectClient.left+m_rectPlot.left+4)/2-rText.Height() / 2, 
		((m_rectPlot.bottom+m_rectPlot.top)/2)-rText.Height()/2, m_str.YUnits) ;
	m_dcGrid.SelectObject(oldFont);

	//  *)	Using "Arial" or "MS Sans Serif" gives a more accurate small font,
	//		but does not work for Korean fonts.
	//	*)	Using "MS Shell Dlg" gives somewhat less accurate small fonts, but
	//		does work for all languages which are currently supported by eMule.
	LegendFont.CreatePointFont(8*10, _T("MS Shell Dlg")); // 8pt 'MS Shell Dlg' -- this shall be available on all Windows systems..
	oldFont = m_dcGrid.SelectObject(&LegendFont);
	m_dcGrid.SetTextAlign(TA_LEFT | TA_TOP);

	int xpos = m_rectPlot.left + 2;
	int ypos = m_rectPlot.bottom + 2;
	for (i = 0; i < m_NTrends; i++){
		CSize sizeLabel = m_dcGrid.GetTextExtent(m_PlotData[i].LegendLabel);
		if (xpos + 12 + sizeLabel.cx + 12 > m_rectPlot.right){
			xpos = m_rectPlot.left + 2;
			ypos = m_rectPlot.bottom + sizeLabel.cy;
		}
		CPen LegendPen(PS_SOLID, 3, m_PlotData[i].crPlotColor);
		oldPen = m_dcGrid.SelectObject(&LegendPen);
		m_dcGrid.MoveTo(xpos, ypos + 8);
		m_dcGrid.LineTo(xpos + 8, ypos + 4);
		m_dcGrid.TextOut(xpos + 12, ypos, m_PlotData[i].LegendLabel);
		xpos += 12 + sizeLabel.cx + 12;
		m_dcGrid.SelectObject(oldPen);
	}

	m_dcGrid.SelectObject(oldFont);
	
	// at this point we are done filling the the grid bitmap, 
	// no more drawing to this bitmap is needed until the setting are changed
	
	// if we don't have one yet, set up a memory dc for the plot
	if (m_dcPlot.GetSafeHdc() == NULL)
	{
		m_dcPlot.CreateCompatibleDC(&dc);
		m_bitmapPlot.DeleteObject();
		m_bitmapPlot.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight);
		m_pbitmapOldPlot = m_dcPlot.SelectObject(&m_bitmapPlot);
	}
	
	// make sure the plot bitmap is cleared
	if (deleteGraph)
	{
		m_dcPlot.SetBkColor(m_crBackColor);
		m_dcPlot.FillRect(m_rectClient, &m_brushBack);
	}

	int iNewSize = m_rectClient.Width() / m_nShiftPixels + 10;		// +10 just in case :)
	if (m_nMaxPointCnt < iNewSize)
		m_nMaxPointCnt = iNewSize;									// keep the bigest value

	if (theApp.emuledlg->IsRunning()) 
	{
		if (thePrefs.IsGraphRecreateDisabled() == false) {
			// The timer will redraw the previous points in 200ms
			m_bDoUpdate = false;
			if(m_nRedrawTimer)
				KillTimer(m_nRedrawTimer);
			VERIFY( (m_nRedrawTimer = SetTimer(1612, 200, NULL)) != NULL ); // reduce flickering
		}
	}

	// finally, force the plot area to redraw
	InvalidateRect(m_rectClient);
} // InvalidateCtrl


/////////////////////////////////////////////////////////////////////////////
// G.Hayduk: now, there are two methods: AppendPoints and AppendEmptyPoints

// Added new parameter: bool bUseTrendRatio (TRUE by default)
void COScopeCtrl::AppendPoints(double dNewPoint[], bool bInvalidate, bool bAdd2List, bool bUseTrendRatio)
{
	int iTrend;
	
	// append a data point to the plot
	for(iTrend = 0; iTrend < m_NTrends; iTrend ++)
	{
		// Changed this to support the new TrendRatio var
		if (bUseTrendRatio)
			m_PlotData[iTrend].dCurrentPosition = (double) dNewPoint[iTrend] / m_PlotData[iTrend].iTrendRatio;
		else
			m_PlotData[iTrend].dCurrentPosition = dNewPoint[iTrend];
		if(bAdd2List)
		{
			m_PlotData[iTrend].lstPoints.AddTail(m_PlotData[iTrend].dCurrentPosition);
			while(m_PlotData[iTrend].lstPoints.GetCount() > m_nMaxPointCnt)
				m_PlotData[iTrend].lstPoints.RemoveHead();
		}
	}
	
	// Sometime responsible for 'ghost' point on the left after a resize
	if(m_bDoUpdate == false)		
		return;

	if(m_nTrendPoints > 0)
	{
		if(CustShift.m_nPointsToDo == 0)
		{
			CustShift.m_nPointsToDo = m_nTrendPoints - 1;
			CustShift.m_nWidthToDo = m_nPlotWidth;
			CustShift.m_nRmndr = 0;
		}
		
		// a little bit tricky setting m_nShiftPixels in "fixed number of points through plot width" mode
		m_nShiftPixels = (CustShift.m_nWidthToDo + CustShift.m_nRmndr) / CustShift.m_nPointsToDo;
		CustShift.m_nRmndr = (CustShift.m_nWidthToDo + CustShift.m_nRmndr) % CustShift.m_nPointsToDo;
		if(CustShift.m_nPointsToDo == 1)
			m_nShiftPixels = CustShift.m_nWidthToDo;
		CustShift.m_nWidthToDo -= m_nShiftPixels;
		CustShift.m_nPointsToDo--;
	}
	DrawPoint();
	
	if(bInvalidate && ready && m_bDoUpdate)
		Invalidate();
	
	return;
} // AppendPoint

/////////////////////////////////////////////////////////////////////////////
// G.Hayduk:
// AppendEmptyPoints adds a vector of data points, without drawing them
// (but shifting the plot), this way you can do a "hole" (space) in the plot
// i.e. indicating "no data here". When points are available, call AppendEmptyPoints
// for first valid vector of data points, and then call AppendPoints again and again 
// for valid points

// Added parameter: bool bUseTrendRatio (TRUE by default)
void COScopeCtrl::AppendEmptyPoints(double dNewPoint[], bool bInvalidate, bool bAdd2List, bool bUseTrendRatio)
{
	int iTrend, currY;
	CRect ScrollRect, rectCleanUp;
	// append a data point to the plot
	// return the previous point
	for(iTrend = 0; iTrend < m_NTrends; iTrend ++)
	{
		// Changed to support new Trend Ratio var and bUseTrendRatio parameter.
		if (bUseTrendRatio)
			m_PlotData[iTrend].dCurrentPosition = (double) dNewPoint[iTrend] / m_PlotData[iTrend].iTrendRatio;
		else
			m_PlotData[iTrend].dCurrentPosition = dNewPoint[iTrend];
		if(bAdd2List)
			m_PlotData[iTrend].lstPoints.AddTail(m_PlotData[iTrend].dCurrentPosition);
	}
	if(m_nTrendPoints > 0)
	{
		if(CustShift.m_nPointsToDo == 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -