这是一个实时曲线的全部代码,可以绘制实时传过来的数据(硬件),第一次做,还有很多不足,希望有兴趣的朋友一起探讨一下.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Drawing2D;
using System.Data.SqlClient;
using System.Drawing.Imaging;
namespace DrawLine
{
public partial class DrawLine : UserControl
{
#region 构造函数
public DrawLine()
{
InitializeComponent();
//每屏显示时间可以被6(分钟)整除
if (picDrawLine.Width % 6 != 0)
pnlY1.Width += picDrawLine.Width % 6;
//读取配置文件设置 标注选项
string strPath = Application.StartupPath + "//Lable.lsa";
if (File.Exists(strPath))
{
using (StreamReader sr = new StreamReader(strPath))
{
try
{
int intLableNum = int.Parse(sr.ReadLine());
for (int i = 0; i < intLableNum; i++)
{
cmbLable.Items.Add(sr.ReadLine());
}
}
catch
{
MessageBox.Show("读取文件失败,标注配置文件'Lable.lsa'格式不正确", "提示信息");
}
sr.Close();
}
}
//重新设置 位置实时数据排列位置
int intSpace = pnlData.Width / 6;
lbl1.Location = new Point(20, 15);
lbl2.Location = new Point(20 + intSpace, 15);
lbl3.Location = new Point(20 + intSpace * 2, 15);
lbl4.Location = new Point(20 + intSpace * 3, 15);
lbl5.Location = new Point(20 + intSpace * 4, 15);
lbl6.Location = new Point(20 + intSpace * 5, 15);
lbl7.Location = new Point(20 + intSpace * 6, 15);
lblData1.Location = new Point(20, 30);
lblData2.Location = new Point(20 + intSpace, 30);
lblData3.Location = new Point(20 + intSpace * 2, 30);
lblData4.Location = new Point(20 + intSpace * 3, 30);
lblData5.Location = new Point(20 + intSpace * 4, 30);
lblData6.Location = new Point(20 + intSpace * 5, 30);
lblData7.Location = new Point(20 + intSpace * 6, 30);
}
#endregion
#region 相关属性设置
#region 基础变量声明与属性设置
#region 基础信息变量
private string strTitleName = "施工实时曲线";
private string strPartyCompany = "";//甲方公司名称
private string strPartyDeputy = "";//甲方代表
private string strOilfieldName = "";//油田名称
private string strServiceCompany = "";//服务公司
private string strServiceDeputy = "";//服务公司代表
private string strWellName = "";//井名称
private string strPosition = "";//层位
private DateTime dtConstructionDate = new DateTime();//施工时间
private string strPartyCompanyPicPath = ""; //甲方单位图标
private string strServiceCompanyPicPath = "";//乙方单位图标
private int intDate = 30; //每屏显示的时间 时间单位为分钟
private SqlConnection my_Conn = new SqlConnection(); //数据库连接 标注数据入库
#endregion
#region 基础信息属性
/// <summary>
/// 设置甲方名称
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置甲方名称")]
public string My_strPartyCompany
{
set
{
strPartyCompany = value;
lblCompany.Text = "甲方名称:" + strPartyCompany;
}
get { return strPartyCompany; }
}
/// <summary>
/// 设置甲方代表
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置甲方代表")]
public string My_strPartyDeputy
{
set
{
strPartyDeputy = value;
lblDB.Text = "甲方代表:" + strPartyDeputy;
}
get { return strPartyDeputy; }
}
/// <summary>
/// 设置油田名称
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置油田名称")]
public string My_strOilfieldName
{
set
{
strOilfieldName = value;
lblYTMC.Text = "油田名称:" + strOilfieldName;
}
get { return strOilfieldName; }
}
/// <summary>
/// 设置服务公司名称
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置服务公司名称")]
public string My_strServiceCompany
{
set
{
strServiceCompany = value;
lblServiseCompany.Text = "服务公司名称:" + strServiceCompany;
}
get { return strServiceCompany; }
}
/// <summary>
/// 设置服务公司代表
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置服务公司代表")]
public string My_strServiceDeputy
{
set
{
strServiceDeputy = value;
lblFUDB.Text = "服务公司代表:" + strServiceDeputy;
}
get { return strServiceDeputy; }
}
/// <summary>
/// 设置井名
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置井名")]
public string My_strWellName
{
set
{
strWellName = value;
lblJM.Text = "井名:" + strWellName;
}
get { return strWellName; }
}
/// <summary>
/// 设置层位
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置层位")]
public string My_strPosition
{
set
{
strPosition = value;
lblCW.Text = "层位:" + strPosition;
}
get { return strPosition; }
}
/// <summary>
/// 设置施工时间 如果施工时间格式不正确,则系统默认本地时间
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(typeof(DateTime), "2008-8-8"), Description("设置施工时间")]
public DateTime My_dtConstructionDate
{
set
{
if (value != Convert.ToDateTime("0001-1-1 0:00:00"))
dtConstructionDate = value;
else
dtConstructionDate = DateTime.Now;
lblDate.Text = "施工日期:" + dtConstructionDate.ToShortDateString();
}
get
{
return dtConstructionDate;
}
}
/// <summary>
/// 设置甲方图标
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置甲方图标")]
public string My_strPartyCompanyPicFullPath
{
set
{
strPartyCompanyPicPath = value;
try
{
picPartyCompany.ImageLocation = strPartyCompanyPicPath;
}
catch
{
picPartyCompany.ImageLocation = "";
}
}
get
{
return strPartyCompanyPicPath;
}
}
/// <summary>
/// 设置服务公司图标
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(""), Description("设置服务公司图标")]
public string My_strServiceCompanyPicFullPath
{
set
{
strServiceCompanyPicPath = value;
try
{
picServiceCompany.ImageLocation = strServiceCompanyPicPath;
}
catch
{
picServiceCompany.ImageLocation = "";
}
}
get
{
return strServiceCompanyPicPath;
}
}
/// <summary>
/// 设置实时显示初始时间 时间单位为分钟
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(0), Description("设置实时显示初始时间")]
public int My_intDate
{
set
{
intDate = value;
fltCurrentSection[0] = 0;
fltCurrentSection[1] = float.Parse(intDate.ToString());
//if (intDate != 30)
DrawXCoordinate();
//SetPnlRealTimeLineScrollPosition(0);
}
get { return intDate; }
}
/// <summary>
/// 设置标题
/// </summary>
[Bindable(true), Category("基础信息属性设置"), DefaultValue(0), Description("设置标题")]
public string My_strTitleName
{
set
{
strTitleName = value;
lblTitle.Text = strTitleName;
}
get { return strTitleName; }
}
/// <summary>
/// 数据库连接
/// </summary>
public SqlConnection My_Conn
{
get { return my_Conn; }
set { my_Conn = value; }
}
#endregion
#endregion
#region 图表变量声明与属性设置
/*
* ArrayList 中的每个通道详细参数
* 每个通道各个参数,通过ArrayList数组,统一发送
* array[0]=通道名称 string
* array[1]=曲线颜色 string ColorName
* array[2]=曲线粗细 float
* array[3]=最大值 float
* array[4]=最小值 float
* array[5]=曲线报警最大值 float
* array[6]=曲线报警最小值 float
* array[7]=是否显示 bool
* array[8]=硬件通道名称 string
*/
private ArrayList alChannelBaseData = new ArrayList();
/// <summary>
/// 通道模式
/// </summary>
[Bindable(true), Category("图标显示设置"), DefaultValue(""), Description("通道模式")]
public ArrayList My_alChannelBaseData
{
set
{
alChannelBaseData = value;
//初始化通道模式时 更新图标模板数据
int intCounter = 0;
cmbChannel.Items.Clear();
cmbChannel.Items.Add("");
for (int i = 0; i < alChannelBaseData.Count; i++)
{
ArrayList al = new ArrayList();
alAllHistoryData.Add(al);
ArrayList alTemp = new ArrayList();
alTemp = alChannelBaseData[i] as ArrayList;
switch (i)
{
case 0:
lbl1.Text = alTemp[0].ToString();
lbl1.Tag = 0;
break;
case 1:
lbl2.Text = alTemp[0].ToString();
lbl2.Tag = 1;
break;
case 2:
lbl3.Text = alTemp[0].ToString();
lbl3.Tag = 2;
break;
case 3:
lbl4.Text = alTemp[0].ToString();
lbl4.Tag = 3;
break;
case 4:
lbl5.Text = alTemp[0].ToString();
lbl5.Tag = 4;
break;
case 5:
lbl6.Text = alTemp[0].ToString();
lbl6.Tag = 5;
break;
case 6:
lbl7.Text = alTemp[0].ToString();
lbl7.Tag = 6;
break;
default:
cmbChannel.Items.Add(alTemp[0].ToString());
break;
}
if (intCounter > 5)
continue;
if (bool.Parse(alTemp[7].ToString()))
{
DrawLineColor(alTemp, intCounter + 1);
SetTag(intCounter, i);
switch (intCounter)
{
case 0:
chk1.Enabled = true;
chk1.Checked = true;
intCurrentChannelNum++;
break;
case 1:
chk2.Enabled = true;
chk2.Checked = true;
intCurrentChannelNum++;
break;
case 2:
chk3.Enabled = true;
chk3.Checked = true;
intCurrentChannelNum++;
break;
case 3:
chk4.Enabled = true;
chk4.Checked = true;
intCurrentChannelNum++;
break;
case 4:
chk5.Enabled = true;
chk5.Checked = true;
intCurrentChannelNum++;
break;
case 5:
chk6.Enabled = true;
chk6.Checked = true;
intCurrentChannelNum++;
break;
default:
break;
}
intCounter++;
}
}
SetDropDownListValue();//设置dropdwonlist值
}
get { return alChannelBaseData; }
}
#endregion
#region 实时曲线变量与属性设置
private float[] fltChannelRealTimeDataForTeam = new float[] { };
/// <summary>
/// 施工期间的实时数据,有多少路通道就传入多少路数据
/// </summary>
[Bindable(true), Category("实时曲线数据"), DefaultValue(""), Description("所有通道数据")]
public float[] My_fltChannelRealTimeDataForTeam
{
set
{
fltChannelRealTimeDataForTeam = value;
intCounter++;
//画实时数据曲线
if (fltChannelRealTimeDataForTeam.Length != 0)
{
//float[] ff = new float[6];
float[] ff = new float[intCurrentChannelNum];//获取当前6(最多)路实时数据
if (intCounter % ((intDate - (intC == 0 ? 0 : (intDate / 6))) * 60) == 0)
{
if (!hsbar.Visible)
SetShowScroll(true);//显示滚动轴
intCounter = 0;//计数器清零
intTime = (intDate / 6) * 60;//时间计时器清零=换屏后初始时间
intC++;//计数器开始技术
float fltt = (intDate / 6) * 5.0F;
fltCurrentSection[0] = fltCurrentSection[0] + fltt;
fltCurrentSection[1] = fltCurrentSection[1] + fltt;
SetPnlRealTimeLineScrollPosition(picDrawLine.Width * 5 / 6);//重设滚动轴位置
DrawGridding(); //重绘网格
DrawHistoryLines();//重绘1/6
ReSetXLable(fltCurrentSection[0], fltCurrentSection[1]);
//ptOldPoint = new PointF[0];
ReSetOldPointF();
}
//保存历史数据
lock (alAllHistoryData)
{
for (int i = 0; i < fltChannelRealTimeDataForTeam.Length; i++)
{
ArrayList alTemp = new ArrayList();
alTemp = alAllHistoryData[i] as ArrayList;
alTemp.Add(fltChannelRealTimeDataForTeam[i]);
alAllHistoryData[i] = alTemp;
}
}
for (int i = 0; i < ff.Length; i++)
{
switch (i)
{
case 0:
ff[i] = fltChannelRealTimeDataForTeam[(int)chk1.Tag];
break;
case 1:
ff[i] = fltChannelRealTimeDataForTeam[(int)chk2.Tag];
break;
case 2:
ff[i] = fltChannelRealTimeDataForTeam[(int)chk3.Tag];
break;
case 3:
ff[i] = fltChannelRealTimeDataForTeam[(int)chk4.Tag];
break;
case 4:
ff[i] = fltChannelRealTimeDataForTeam[(int)chk5.Tag];
break;
case 5:
ff[i] = fltChannelRealTimeDataForTeam[(int)chk6.Tag];
break;
default:
break;
}
}
//绘制曲线
ptD = GetThePointFromPhysicsData(ff);
if (ptOldPoint.Length == 0)
ptOldPoint = ptD;
DrawChartLine();
//设置实时数据
if (lbl1.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl1.Tag].ToString(), lblData1);
if (lbl2.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl2.Tag].ToString(), lblData2);
if (lbl3.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl3.Tag].ToString(), lblData3);
if (lbl4.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl4.Tag].ToString(), lblData4);
if (lbl5.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl5.Tag].ToString(), lblData5);
if (lbl6.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl6.Tag].ToString(), lblData6);
if (lbl7.Text != "")
SetString(fltChannelRealTimeDataForTeam[(int)lbl7.Tag].ToString(), lblData7);
intTime++;
}
}
get
{
return fltChannelRealTimeDataForTeam;
}
}
#endregion
#region 历史曲线回放相关属性设置
private int intWorkHoursStyle = 0;
/// <summary>
/// 设置横坐标显示模式 工作时刻或工作时长 默认工作时刻
/// </summary>
[Bindable(true), Category("历史曲线绘制"), DefaultValue(0), Description("时间显示模式")]
public int My_WorkHoursStyle
{
set
{
intWorkHoursStyle = value;
ReSetXLable(fltCurrentSection[0], fltCurrentSection[1]);
}
get { return intWorkHoursStyle; }
}
private string strStartTime = "2008-8-8 10:20:20";
[Bindable(true), Category("历史曲线绘制"), DefaultValue("10:20:20"), Description("开始时间")]
public string My_StartTime
{
set { strStartTime = value; }
get { return strStartTime; }
}
private ArrayList alSingal = new ArrayList();//所有标注 坐标x,坐标y,标注,屏幕
[Bindable(true), Category("历史曲线绘制"), DefaultValue(""), Description("历史数据的所有标注")]
public ArrayList My_AlSingal
{
get { return alSingal; }
set { alSingal = value; }
}
#endregion
#endregion
#region 私有变量
private Pen[] CurrentPen = new Pen[6];//当前画笔
private Point[] ptChannelX = new Point[6];//存储双击位置X 图示部分
private Point[] ptChannelY = new Point[6];//Y
private int intChk = -1;//定位 重新选择Channel时 位于那个CheckBox
private int intChkData = -1;
private delegate void SetImageToPic(Image img1, Control ctl);//委托方法
private delegate void SetImageToPic1(int intWidth);//委托方法
private delegate void SetScrollState(bool bolIsShow);//设置是否显示滚动条
private delegate void SetRealData(string strRealTimeData, Control ctl);//设置实时数据
private float[] fltCurrentSection = new float[2] { 0F, 30F };//当前显示时间段
private ArrayList alAllHistoryData = new ArrayList();//所有历史数据
private int intCounter = 0;//当前接收的数据条数
private int intC = 0;//当前分屏次数
private PointF[] ptOldPoint = new PointF[] { };//6个通道的旧坐标
private BitArray bitCheckBox = new BitArray(6, true);//设置某个通道是否绘制实时曲线,默认为TRUE
private int intTime = 0;//记录工作时间
//竖线 画异或曲线时存储旧坐标
private Point pxold = new Point(0, 0);
private Point pyold = new Point(0, 0);
//横线
private Point pxxold = new Point(0, 0);
private Point pyyold = new Point(0, 0);
private bool IsLabel = false; //是否可以标记
private bool IsReadData = false; //是否可以读值
PointF[] ptD; //实时数据坐标数组
private float fltSection = 0;//滚动条用 滚动后 当前屏幕的起始时间
private bool IsEditData = false;//编辑曲线时用
private bool IsCross = false;//编辑曲线用 确定鼠标进入本状态前的状态 否决的
float fltSecond = 0;//编辑曲线时用 编辑曲线的入口时间
private bool IsQualityFirst = true;//实时绘图方式 true 质量优先;false 速度优先
private int intCurrentChannelNum = 0;//当前显示的通道数量
#endregion
#region 私有方法
#region 画示例图示
/// <summary>
/// 画图例部分 是否显示某条曲线
/// </summary>
/// <param name="al">相关通道设置</param>
/// <param name="intChannel">通道号</param>
private void DrawLineColor(ArrayList al, int intChannel)
{
string strName = "";
Color PenColor = Color.White;
float fltThickness = 0;
Image img;
cmbSelectChannel.Visible = false;
if (pnlLineColor.BackgroundImage == null)
{
img = new Bitmap(pnlLineColor.Width, pnlLineColor.Height);
pnlLineColor.BackgroundImage = img;
}
else
img = pnlLineColor.BackgroundImage;
try
{
using (Graphics g = Graphics.FromImage(img))
{
lock (g)
{
if (al.Count != 0)
{
Point px, py;
Pen p = new Pen(Brushes.Wheat);
switch (intChannel)
{
case 1:
strName = al[0].ToString();
PenColor = ColorTranslator.FromOle((int)al[1]);
fltThickness = (float)al[2];
//划线 固定点 chk1.Location.X+chk1.Size.Width+5
px = new Point(chk1.Location.X + chk1.Size.Width + 5, chk1.Location.Y + 7);
py = new Point(chk1.Location.X + chk1.Size.Width + 35, chk1.Location.Y + 7);
p = new Pen(PenColor, fltThickness);
CurrentPen[0] = p;
ptChannelX[0] = new Point(chk1.Location.X + chk1.Size.Width + 35, chk1.Location.X + chk1.Size.Width + 35 + Convert.ToInt32(g.MeasureString(strName, new Font("宋体", 9)).Width));
ptChannelY[0] = new Point(chk1.Location.Y, chk1.Location.Y + 10);
g.DrawLine(p, px, py);
//标记
g.DrawString(strName, new Font("宋体", 10), Brushes.Black, new PointF(float.Parse(Convert.ToString(chk1.Location.X + chk1.Size.Width + 35)), float.Parse(Convert.ToString(chk1.Location.Y))));
break;
case 2:
strName = al[0].ToString();
PenColor = ColorTranslator.FromOle((int)al[1]);
fltThickness = (float)al[2];
//划线 固定点
px = new Point(chk2.Location.X + chk2.Size.Width + 5, chk2.Location.Y + 7);
py = new Point(chk2.Location.X + chk2.Size.Width + 35, chk2.Location.Y + 7);
p = new Pen(PenColor, fltThickness);
g.DrawLine(p, px, py);
CurrentPen[1] = p;
ptChannelX[1] = new Point(chk2.Location.X + chk2.Size.Width + 35, chk2.Location.X + chk2.Size.Width + 35 + Convert.ToInt32(g.MeasureString(strName, new Font("宋体", 9)).Width));
ptChannelY[1] = new Point(chk2.Location.Y, chk2.Location.Y + 10);
g.DrawString(strName, new Font("宋体", 10), Brushes.Black, new PointF(float.Parse(Convert.ToString(chk2.Location.X + chk2.Size.Width + 35)), float.Parse(Convert.ToString(chk2.Location.Y))));
break;
case 3:
strName = al[0].ToString();
PenColor = ColorTranslator.FromOle((int)al[1]);
fltThickness = (float)al[2];
//划线 固定点
px = new Point(chk3.Location.X + chk3.Size.Width + 5, chk3.Location.Y + 7);
py = new Point(chk3.Location.X + chk3.Size.Width + 35, chk3.Location.Y + 7);
p = new Pen(PenColor, fltThickness);
g.DrawLine(p, px, py);
CurrentPen[2] = p;
ptChannelX[2] = new Point(chk3.Location.X + chk3.Size.Width + 35, chk3.Location.X + chk3.Size.Width + 35 + Convert.ToInt32(g.MeasureString(strName, new Font("宋体", 9)).Width));
ptChannelY[2] = new Point(chk3.Location.Y, chk3.Location.Y + 10);
g.DrawString(strName, new Font("宋体", 10), Brushes.Black, new PointF(float.Parse(Convert.ToString(chk3.Location.X + chk3.Size.Width + 35)), float.Parse(Con