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

📄 oscopectrl.cpp

📁 非常出名开源客户端下载的程序emule
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// OScopeCtrl.cpp : implementation file//

#include "stdafx.h"
#include "math.h"

#include "OScopeCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// COScopeCtrl
COScopeCtrl::COScopeCtrl(int NTrends)
{
	int i;
	COLORREF PresetColor[16] = 
	{
		RGB(0xFF, 0x00, 0x00),
			RGB(0xFF, 0xC0, 0xC0),
			
			RGB(0xFF, 0xFF, 0x00),
			RGB(0xFF, 0xA0, 0x00),
			RGB(0xA0, 0x60, 0x00),
			
			RGB(0x00, 0xFF, 0x00),
			RGB(0x00, 0xA0, 0x00),
			
			RGB(0x00, 0x00, 0xFF),
			RGB(0x00, 0xA0, 0xFF),
			RGB(0x00, 0xFF, 0xFF),
			RGB(0x00, 0xA0, 0xA0),
			
			RGB(0xC0, 0xC0, 0xFF),
			RGB(0xFF, 0x00, 0xFF),
			RGB(0xA0, 0x00, 0xA0),
			
			RGB(0xFF, 0xFF, 0xFF),
			RGB(0x80, 0x80, 0x80)
	};
	// since plotting is based on a LineTo for each new point
	// we need a starting point (i.e. a "previous" point)
	// use 0.0 as the default first point.
	// these are public member variables, and can be changed outside
	// (after construction).  
	// G.Hayduk: NTrends is the number of trends that will be drawn on
	// the plot. First 15 plots have predefined colors, but others will
	// be drawn with white, unless you call SetPlotColor
	m_PlotData = new PlotData_t[NTrends];
	m_NTrends = NTrends;
	
	for(i = 0; i < m_NTrends; i++)
	{
		if(i < 15)
			m_PlotData[i].crPlotColor  = PresetColor[i];  // see also SetPlotColor
		else
			m_PlotData[i].crPlotColor  = RGB(255, 255, 255);  // see also SetPlotColor
		m_PlotData[i].penPlot.CreatePen(PS_SOLID, 0, m_PlotData[i].crPlotColor);
		m_PlotData[i].dPreviousPosition = 0.0;
		m_PlotData[i].nPrevY = -1;
		m_PlotData[i].dLowerLimit = -10.0;
		m_PlotData[i].dUpperLimit =  10.0;
		m_PlotData[i].dRange      =   m_PlotData[i].dUpperLimit - 
			m_PlotData[i].dLowerLimit;   // protected member variable
		m_PlotData[i].lstPoints.AddTail(0.0);
	}
	
	// public variable for the number of decimal places on the y axis
	// G.Hayduk: I've deleted the possibility of changing this parameter
	// in SetRange, so change it after constructing the plot
	m_nYDecimals = 1;
	
	// set some initial values for the scaling until "SetRange" is called.
	// these are protected varaibles and must be set with SetRange
	// in order to ensure that m_dRange is updated accordingly
	
	// m_nShiftPixels determines how much the plot shifts (in terms of pixels) 
	// with the addition of a new data point
	drawBars = false;
	autofitYscale = false;
	m_nShiftPixels = 1;
	m_nTrendPoints = 0;
	m_nMaxPointCnt = 1024;
	CustShift.m_nPointsToDo = 0;
	// G.Hayduk: actually I needed an OScopeCtrl to draw specific number of
	// data samples and stretch them on the plot ctrl. Now, OScopeCtrl has
	// two modes of operation: fixed Shift (when m_nTrendPoints=0, 
	// m_nShiftPixels is in use), or fixed number of Points in the plot width
	// (when m_nTrendPoints>0)
	// When m_nTrendPoints>0, CustShift structure is in use
	
	// background, grid and data colors
	// these are public variables and can be set directly
	m_crBackColor  = RGB(0,   0,   0);  // see also SetBackgroundColor
	m_crGridColor  = RGB(0, 255, 255);  // see also SetGridColor
	
	// protected variables
	m_brushBack.CreateSolidBrush(m_crBackColor);
	
	// public member variables, can be set directly 
	m_str.XUnits.Format("Samples");  // can also be set with SetXUnits
	m_str.YUnits.Format("Y units");  // can also be set with SetYUnits
	
	// protected bitmaps to restore the memory DC's
	m_pbitmapOldGrid = NULL;
	m_pbitmapOldPlot = NULL;
	
	// G.Hayduk: configurable number of grids init
	// you are free to change those between contructing the object 
	// and calling Create
	m_nXGrids = 6;
	m_nYGrids = 5;
	m_nTrendPoints = -1;

	m_bDoUpdate = true;
	m_nRedrawTimer = 0;
}  // COScopeCtrl

/////////////////////////////////////////////////////////////////////////////
COScopeCtrl::~COScopeCtrl()
{
	// just to be picky restore the bitmaps for the two memory dc's
	// (these dc's are being destroyed so there shouldn't be any leaks)
	if(m_pbitmapOldGrid != NULL)
		m_dcGrid.SelectObject(m_pbitmapOldGrid);  
	if(m_pbitmapOldPlot != NULL)
		m_dcPlot.SelectObject(m_pbitmapOldPlot);  
	delete[] m_PlotData;
	// G.Hayduk: If anyone notices that I'm not freeing or deleting
	// something, please let me know: hayduk@hello.to
} // ~COScopeCtrl


BEGIN_MESSAGE_MAP(COScopeCtrl, CWnd)
	//{{AFX_MSG_MAP(COScopeCtrl)
	ON_WM_PAINT()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_WM_TIMER()
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// COScopeCtrl message handlers

/////////////////////////////////////////////////////////////////////////////
BOOL COScopeCtrl::Create(DWORD dwStyle, const RECT& rect, 
		                     CWnd* pParentWnd, UINT nID) 
{
	BOOL result;
	static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
	
	result = CWnd::CreateEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, 
		className, NULL, dwStyle, 
		rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(), (HMENU)nID);
	if(result != 0)
		InvalidateCtrl();
	
	return result;
} // Create

/////////////////////////////////////////////////////////////////////////////
void COScopeCtrl::SetRange(double dLower, double dUpper, int iTrend)
{
	ASSERT(dUpper > dLower);
	
	m_PlotData[iTrend].dLowerLimit     = dLower;
	m_PlotData[iTrend].dUpperLimit     = dUpper;
	m_PlotData[iTrend].dRange          = m_PlotData[iTrend].dUpperLimit - m_PlotData[iTrend].dLowerLimit;
	m_PlotData[iTrend].dVerticalFactor = (double)m_nPlotHeight / m_PlotData[iTrend].dRange; 
	
	// clear out the existing garbage, re-start with a clean plot
	InvalidateCtrl();
}  // SetRange

void COScopeCtrl::SetRanges(double dLower, double dUpper)
{
	int iTrend;
	ASSERT(dUpper > dLower);
	
	for(iTrend = 0; iTrend < m_NTrends; iTrend ++)
	{
		m_PlotData[iTrend].dLowerLimit     = dLower;
		m_PlotData[iTrend].dUpperLimit     = dUpper;
		m_PlotData[iTrend].dRange          = m_PlotData[iTrend].dUpperLimit - m_PlotData[iTrend].dLowerLimit;
		m_PlotData[iTrend].dVerticalFactor = (double)m_nPlotHeight / m_PlotData[iTrend].dRange; 
	}
	
	// clear out the existing garbage, re-start with a clean plot
	InvalidateCtrl();
}  // SetRange
/////////////////////////////////////////////////////////////////////////////
// G.Hayduk: Apart from setting title of axis, now you can optionally set 
// the limits strings
// (string which will be placed on the left and right of axis)
void COScopeCtrl::SetXUnits(CString string, CString XMin, CString XMax)
{
	m_str.XUnits = string;
	m_str.XMin = XMin;
	m_str.XMax = XMax;
	
	InvalidateCtrl(false);
}  // SetXUnits


/////////////////////////////////////////////////////////////////////////////
// G.Hayduk: Apart from setting title of axis, now you can optionally set 
// the limits strings
// (string which will be placed on the bottom and top of axis)
void COScopeCtrl::SetYUnits(CString string, CString YMin, CString YMax)
{
	m_str.YUnits = string;
	m_str.YMin = YMin;
	m_str.YMax = YMax;
	
	// clear out the existing garbage, re-start with a clean plot
	InvalidateCtrl();
}  // SetYUnits

/////////////////////////////////////////////////////////////////////////////
void COScopeCtrl::SetGridColor(COLORREF color)
{
	m_crGridColor = color;
	
	// clear out the existing garbage, re-start with a clean plot
	InvalidateCtrl();
}  // SetGridColor


/////////////////////////////////////////////////////////////////////////////
void COScopeCtrl::SetPlotColor(COLORREF color, int iTrend)
{
	m_PlotData[iTrend].crPlotColor = color;
	
	m_PlotData[iTrend].penPlot.DeleteObject();
	m_PlotData[iTrend].penPlot.CreatePen(PS_SOLID, 0, m_PlotData[iTrend].crPlotColor);
	
	// clear out the existing garbage, re-start with a clean plot
	//	InvalidateCtrl() ;
}  // SetPlotColor

COLORREF COScopeCtrl::GetPlotColor(int iTrend)
{
	return m_PlotData[iTrend].crPlotColor;
}  // GetPlotColor

/////////////////////////////////////////////////////////////////////////////
void COScopeCtrl::SetBackgroundColor(COLORREF color)
{
	m_crBackColor = color;
	
	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;
	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
	nCharacters = abs((int)log10(fabs(m_PlotData[0].dUpperLimit)));
	nCharacters = max(nCharacters, abs((int)log10(fabs(m_PlotData[0].dLowerLimit))));
	
	// 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)
	m_rectPlot.left = m_rectClient.left + 6*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);
	}
	
	/*
	for(j = 1; j < (m_nXGrids + 1); j++)
	{
	GridPos = m_rectPlot.Width()*j/ (m_nXGrids + 1) + m_rectPlot.left;
	for(i = m_rectPlot.top; i < m_rectPlot.bottom; i += 4)
	m_dcGrid.SetPixel(GridPos, i, m_crGridColor);
	}
	*/
	
	// create some fonts (horizontal and vertical)
	// use a height of 14 pixels and 300 weight 
	// (these may need to be adjusted depending on the display)
	axisFont.CreateFont(14, 0, 0, 0, 300,
		//FALSE, FALSE, 0, ANSI_CHARSET,
		FALSE, FALSE, 0, DEFAULT_CHARSET, // EC
		OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS,
		DEFAULT_QUALITY, 
		DEFAULT_PITCH | FF_SWISS, "Arial");
	yUnitFont.CreateFont(14, 0, 900, 0, 300,
		//FALSE, FALSE, 0, ANSI_CHARSET,
		FALSE, FALSE, 0, DEFAULT_CHARSET, // EC
		OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS,
		DEFAULT_QUALITY, 
		DEFAULT_PITCH | FF_SWISS, "Arial");
	
	// 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("%.*lf", m_nYDecimals, m_PlotData[0].dUpperLimit);
	else
		strTemp = m_str.YMax;
	m_dcGrid.TextOut(m_rectPlot.left - 4, m_rectPlot.top - 7, strTemp);
	
	// y/2
	strTemp.Format("%.*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
	m_dcGrid.SetTextAlign(TA_RIGHT | TA_BASELINE);
	if(m_str.YMin.IsEmpty())
		strTemp.Format("%.*lf", m_nYDecimals, m_PlotData[0].dLowerLimit);
	else
		strTemp = m_str.YMin;
	m_dcGrid.TextOut(m_rectPlot.left - 4, m_rectPlot.bottom, strTemp);
	/*
	// x min
	m_dcGrid.SetTextAlign(TA_LEFT | TA_TOP);
	if(m_str.XMin.IsEmpty())
	m_dcGrid.TextOut(m_rectPlot.left, m_rectPlot.bottom + 4, "0");
	else
	m_dcGrid.TextOut(m_rectPlot.left, m_rectPlot.bottom + 4, (LPCTSTR)m_str.XMin);
	
	  // x max
	  m_dcGrid.SetTextAlign(TA_RIGHT | TA_TOP);
	  if(m_str.XMax.IsEmpty())
	  {
	  if(m_nTrendPoints < 0)
	  strTemp.Format("%d", m_nPlotWidth/m_nShiftPixels); 
	  else
	  strTemp.Format("%d", m_nTrendPoints - 1); 
	  }
	  else
	  strTemp = m_str.XMax;
	  m_dcGrid.TextOut(m_rectPlot.right, m_rectPlot.bottom + 4, strTemp);
	*/
	// x units
	m_dcGrid.SetTextAlign(TA_CENTER | TA_TOP);
	m_dcGrid.TextOut((m_rectPlot.left + m_rectPlot.right)/2, 
		m_rectPlot.bottom + 4, m_str.XUnits);
	
	// restore the font

⌨️ 快捷键说明

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