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

📄 chartrx.cpp

📁 实现波形的显示,可以作为示波器的一个模块
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	CChartSerial * serial;
	if (this->SerialCount > 0)
	{
		for (int i=0; i<SerialCount; i++)
		{
			serial = GetSerial(i);
			delete serial;
		}
		this->Serials.RemoveAll();
	}
//	this->Serials.SetSize(0, 5);
	this->SerialCount = count;
	int index;
	for (int j=0; j<SerialCount; j++)
	{
		serial = new CChartSerial();
		index = this->Serials.Add(serial);
	}
}


void CChartRx::SetSerialColor(int index, COLORREF cr)
{
	CChartSerial * serial = GetSerial(index);
	if (serial)
	{
		serial->crSerial = cr;
	}
}

CChartSerial * CChartRx::GetSerial(int index)
{
	if (index > (SerialCount-1))
	{
		return NULL;
	}
	return (CChartSerial *)(this->Serials.GetAt(index));
}

// 画线图,在前景图上画好后,贴到背景上去,
void CChartRx::DrawLineChart()
{
	CBitmap   *pOldBit = pMemDC->SelectObject(m_pBackGround); 
	pTempDC->SelectObject(m_pForeGround);
	pTempDC->FillSolidRect(rt_Back, RGB(255, 255, 255));
	pTempDC->BitBlt(rt_Plot.left, rt_Plot.top, rt_Plot.Width(), rt_Plot.Height(),
		pMemDC, rt_Plot.left, rt_Plot.top, SRCCOPY);

	CChartSerial *pSerial = NULL;
	double x, y;
	LPPOINTDATA datapoint;

#ifdef DEBUG_OUTPUT
		///
		CStdioFile mFile;
		mFile.Open("f:\\rx.txt", CFile::modeCreate | CFile::modeWrite, NULL);
		char buffer[1024];
		CTime t = CTime::GetCurrentTime();
		CString text = t.Format( "%y-%m-%d %H:%M:%S\r\n");
		mFile.WriteString(text);
#endif

	for (int i=0; i<this->SerialCount; i++)
	{
		pSerial = this->GetSerial(i);
		if (pSerial == NULL)     // 出错了,返回
		{	
			MessageBox("得到线条信息");
			return;          
		}

		CPen * pPenSerial = new CPen();
		pPenSerial->CreatePen(PS_SOLID, 1, pSerial->crSerial);

		HGDIOBJ pObj = pTempDC->SelectObject(pPenSerial);

		if (pSerial->GetPointCount() > 0)
		{

#ifdef DEBUG_OUTPUT
				text.Format("### 通道%2d ###\r\n", i);
				mFile.WriteString(text);
#endif
				
			datapoint = pSerial->GetPoint(0);
			x = GetPixFromValue1(0, datapoint->x);          // 这里使用新的函数,否则,在越界时候失真
			y = GetPixFromValue1(1, datapoint->y);
			pTempDC->MoveTo(x, y);
			for (int j=1; j<pSerial->GetPointCount(); j++)
			{
				datapoint = pSerial->GetPoint(j);
				x = GetPixFromValue1(0, datapoint->x);
				y = GetPixFromValue1(1, datapoint->y);
				pTempDC->LineTo(x, y);
			
#ifdef DEBUG_OUTPUT
				text.Format("%5d: %f %f\r\n", j,datapoint->x, datapoint->y);
				mFile.WriteString(text);
#endif
			}
		}

		pMemDC->BitBlt(rt_Plot.left, rt_Plot.top, rt_Plot.Width(), rt_Plot.Height(),
			pTempDC, rt_Plot.left, rt_Plot.top, SRCCOPY);

		pTempDC->SelectObject(pObj);
		pPenSerial->DeleteObject();
		delete pPenSerial;

	}

#ifdef DEBUG_OUTPUT
	mFile.Close();
#endif

}

// 画直方图,在前景图上画好后,贴到背景上去,
void CChartRx::DrawChartHistogram()
{
	CBitmap   *pOldBit = pMemDC->SelectObject(m_pBackGround); 
	pTempDC->SelectObject(m_pForeGround);
	pTempDC->FillSolidRect(rt_Back, RGB(255, 255, 255));
	pTempDC->BitBlt(rt_Plot.left, rt_Plot.top, rt_Plot.Width(), rt_Plot.Height(),
		pMemDC, rt_Plot.left, rt_Plot.top, SRCCOPY);

	CChartSerial *pSerial = NULL;
	double x, y, y0;
	LPPOINTDATA datapoint;
	for (int i=0; i<this->SerialCount; i++)
	{
		pSerial = this->GetSerial(i);
		if (pSerial == NULL)     // 出错了,返回
		{	
			MessageBox("程序内部错误:得到线条信息出错");
			return;          
		}
		CPen * pPenSerial = new CPen();
		pPenSerial->CreatePen(PS_SOLID, 1, pSerial->crSerial);

		HGDIOBJ pObj = pTempDC->SelectObject(pPenSerial);

		if (pSerial->GetPointCount() > 0)
		{
			double addPix = (float)rt_Plot.Width() / (float)(x_Divisions);  // x方向,图上的增量
			double addPix1;
			CRect rt;

			for (int j=0; j<pSerial->GetPointCount(); j++)
			{
				datapoint = pSerial->GetPoint(j);
				x = GetPixFromValue1(0, datapoint->x);   // 中轴
				y = GetPixFromValue1(1, datapoint->y);   // 高度
				y0 = GetPixFromValue1(1, 0);             // 底
				addPix1 = addPix * (datapoint->data) / 2;
				rt.left = x - addPix1;
				rt.right = x + addPix1;
				rt.top = y;
				rt.bottom = y0;
				pTempDC->FillSolidRect(rt, pSerial->crSerial);
			}
		}
		pMemDC->BitBlt(rt_Plot.left, rt_Plot.top, rt_Plot.Width(), rt_Plot.Height(),
			pTempDC, rt_Plot.left, rt_Plot.top, SRCCOPY);

		pTempDC->SelectObject(pObj);
		pPenSerial->DeleteObject();
		delete pPenSerial;

	}
}

// 画点,线的时候使用
double CChartRx::GetPixFromValue1(int nAxis, double value)
{	
	double pix = 0;
	if (nAxis == 0)
	{
		pix = rt_Plot.Width() * (value - x_minSel) / (x_maxSel - x_minSel) + rt_Plot.left;
	}
	else
	{
		pix = rt_Plot.top + rt_Plot.Height() * (y_maxSel - value) / (y_maxSel - y_minSel);
	}
	return pix;

}

// 设置类型,并刷新
void CChartRx::SetChartType(int type)
{
	if (type == 1)
	{
		bVGrid = TRUE;
		bCanMagnify = TRUE;
	}
	if (type == 2)
	{
		bVGrid = FALSE;
		bCanMagnify = FALSE;      // 不让放大
	}
	else
	{
	}
	
	this->nChartType = type;
	userPoints.Clear();   // 清除用户标记的点
	shouldReDrawChart = TRUE;
	InitChart();
	y_AxisLabel.text = "1234.678";
	DrawPlot();

	this->Invalidate();
	this->SetFocus();
}

void CChartRx::SetXScale(double min, double max)
{
	this->x_max = this->x_maxSel = max;
	this->x_min = this->x_minSel = min;
}

void CChartRx::SetYScale(double min, double max)
{
	this->y_max = this->y_maxSel = max;
	this->y_min = this->y_minSel = min;
}

void CChartRx::SetXDivision(int major, int mini)
{
	x_Divisions = major;
	x_miniPerSec = mini;

}

void CChartRx::SetYDivision(int major, int mini)
{
	y_Divisions = major;
	y_miniPerSec = mini;
}

void CChartRx::SetTickFormat(CString x, CString y)
{
	x_LabelFormatSel = x_LabelFormat = x;   // x轴标签的格式化字符串 
	y_LabelFormatSel = y_LabelFormat = y;   // y轴标签的格式化字符串
}




void CChartRx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	if (!bShowTip)
		return;
	if (nChar != VK_SPACE)
		return;
	POINT point;
	BOOL ret = GetCursorPos(&point);
	::ScreenToClient(this->m_hWnd, &point);
	// 如果位置不在范围内就返回,
	if ((point.x <= rt_Plot.left) || (point.y <= rt_Plot.top) || (point.x >= rt_Plot.right) || (point.y >= rt_Plot.bottom))
		return;

	double x1, y1;
	x1 = GetValueFormPix(0, point.x);
	y1 = GetValueFormPix(1, point.y);

	// 加一个点,重新;如果加那个坐标,当移动时候会有问题,可以解决,但是窗口变形就很麻烦
	this->userPoints.AddPoint(x1, y1, 0);
	shouldReDrawChart = TRUE;
	Invalidate();
	return;

	// 以下为测试使用


	CString temp;
	//temp.Format("%d, %d", point.x, point.y);
	CString format = x_LabelFormat + ", " + y_LabelFormat;
	temp.Format(format, x1, y1);

	MessageBox(temp);

	
//	CStatic::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CChartRx::DrawUserPoint()
{
	CBitmap   *pOldBit = pMemDC->SelectObject(m_pBackGround); 

	CString strFormat = AddFormat(x_LabelFormat) + ", " + AddFormat(y_LabelFormat);
	CString str;
	SIZE size;

	int x1, y1;
	LPPOINTDATA   pPoint;

	for (int i=0; i<userPoints.GetPointCount(); i++)
	{
		pPoint = userPoints.GetPoint(i);
		x1 = (int)GetPixFromValue1(0, pPoint->x);
		y1 = (int)GetPixFromValue1(1, pPoint->y);
		str.Format(strFormat, pPoint->x, pPoint->y);
		pMemDC->SelectObject(uptLine.pen);
		pMemDC->MoveTo(x1-4, y1);
		pMemDC->LineTo(x1+5, y1);
		pMemDC->MoveTo(x1, y1-4);
		pMemDC->LineTo(x1, y1+5);

			
	 // 临时借用一下这个类
		userPointsLabel.GetStringSize(pMemDC->m_hDC, str, str.GetLength(), &size);
		userPointsLabel.rt = CRect(x1, y1, x1 + size.cx, y1 + size.cy);
		userPointsLabel.ShowText(pMemDC->m_hDC, str,  DT_CENTER | DT_VCENTER | DT_SINGLELINE);	
	}
}

// 更换一个图显示的时候,清理资源
void CChartRx::ClearPlot()
{

}

// 清理x轴的指定标志,不均匀的情况
void CChartRx::ClearXLabels()
{
	// 清理后,根据最大最小值计算标签
	xLabelPoints.Clear();
	bShowTip = TRUE;

}

// 添加一个x轴上的指定标签
void CChartRx::AddXLabel(double xVal)
{
	// 不为空时候,使用这个计算标签,从左到右,
	xLabelPoints.AddPoint(xVal, 0, 0);
	bShowTip = FALSE;
}

void CChartRx::SetTitleText(int index, CString str)
{
	if (index == 0)
	{
		TitleLabel.SetText(str);
	
	}
	else if (index == 1)
	{
		x_AxisTitle.SetText(str);      // x轴标题
	}
	else
	{
		y_AxisTitle.SetText(str); 
	}
}

void CChartRx::Updata()
{
	SetChartType(this->nChartType);
}

// 清除线条中的点
void CChartRx::ClearSerialPoints(int i)
{
	CChartSerial * serial;
	if (i < 0)
	{
		if (this->SerialCount > 0)
		{
			for (int ch=0; ch<SerialCount; ch++)
			{
				serial = GetSerial(ch);
				if (serial)
					serial->Clear();
			}	
		}
		return;
	}

	if (this->SerialCount > i)      // i>=0, 至少有一个通道 
	{
		serial = GetSerial(i);
		serial->Clear();
	}
}
// 根据数值的大小确定分辨率
CString CChartRx::GetFormatFormVal(double val)
{
	CString data;
	data.Format("%f", val);
	int i = data.Find('.', 0);
	int len = data.GetLength();
	LPCTSTR p = (LPCTSTR)data;
	for (int j=i; j<len; j++)
	{
		if (p[j] == '0')
			break;
	}
	if (j == len)
		j = 6;
	else
		j = j - i - 1;
	n_x_Format = j;
	data.Format(".%df", j);
	data = "%" + data;
	return data;
}

CString CChartRx::AddFormat(CString data)
{
	int len = data.GetLength();
	int i = data.Find('.', 0);
	LPCTSTR p = (LPCTSTR)data;

	int k = 0;
	if ((-1 < i) && (i < len))
	{
		if ((p[i + 1] == 0) || (p[i + 1] == 'f'))
		{
			k = 1;
		}
		else
		{
			k = p[i + 1] - '0';
			k ++;
		}	
	}
	else
	{
		k = 1;
	}
	
	if (k > 6)
		k = 6;

	CString str;
	str.Format(".%df", k);
	str = "%" + str;
	return str;
}

CString CChartRx::AddFormat(CString data, double val1, double val2)
{
	CString str;
	double ret = val1 / val2;
	str.Format("%.0f", ret);
	int t = str.GetLength();

	int k = 0;
//	int len = data.GetLength();
//	int i = data.Find('.', 0);
//	LPCTSTR p = (LPCTSTR)data;
//
//
//	if ((-1 < i) && (i < len))
//	{
//		if ((p[i + 1] == 0) || (p[i + 1] == 'f'))
//		{
//			k = t;
//		}
//		else
//		{
//			k = p[i + 1] - '0';
//			k += t;
//		}	
//	}
//	else
//	{
//		k = t;
//	}
	k += t;

	if (k > 6)
		k = 6;

	str.Format(".%df", k);
	str = "%" + str;
	return str;
}

// 用于其中的类设置字体大小
HDC CChartRx::GetDC()
{
	if (pMemDC)
	return pMemDC->m_hDC;

	return NULL;
}

void CChartRx::SetNTickOneLabel(int x, int y)
{
	n_x_TickOneLabel = x;      // 几个大刻度一个标签
	n_y_TickOneLabel = y;
	if (n_x_TickOneLabel > x_Divisions)
		n_x_TickOneLabel = x_Divisions;
	if (n_y_TickOneLabel > y_Divisions)
		n_y_TickOneLabel = y_Divisions;
	Updata();
}

double CChartRx::ABS(double val)
{
	if (val < 0)
		return -val;

	return val;
}

⌨️ 快捷键说明

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