📄 chartrx.cpp
字号:
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 + -