当前位置: 首页 > news >正文

做ktv的网站产品设计作品

做ktv的网站,产品设计作品,苏州手机app开发,老网站绑定新网站如何做本代码调用ZedGraph绘图框架#xff0c;自己先安装好ZedGraph环境#xff0c;然后拖一个zedGraphControl控件就行了#xff0c;直接黏贴下面代码 基本代码显示 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public…本代码调用ZedGraph绘图框架自己先安装好ZedGraph环境然后拖一个zedGraphControl控件就行了直接黏贴下面代码 基本代码显示 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 150; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataLists;private LineItem[] _curves;// 定时器用于模拟ECG信号数据更新private System.Timers.Timer _timer;private int _currentIndex 0;private int _maxPoints 500;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time;myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataLists new PointPairList[ChannelCount];_curves new LineItem[ChannelCount];_yValues new double[ChannelCount][];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataLists[i] new PointPairList();_curves[i] myPane.AddCurve($ECG Channel {i 1}, _dataLists[i], GetColor(i), SymbolType.None);_yValues[i] new double[_maxPoints];}// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints * _timeIncrement;myPane.YAxis.Scale.Min -600;myPane.YAxis.Scale.Max 600 VoltageOffset * (ChannelCount - 1);// 显示网格线myPane.XAxis.MajorGrid.IsVisible true;myPane.YAxis.MajorGrid.IsVisible true;// 应用更改并刷新图表zedGraphControl1.AxisChange();}private System.Drawing.Color GetColor(int index){// 定义一组颜色用于不同导联的曲线System.Drawing.Color[] colors {System.Drawing.Color.Black,System.Drawing.Color.Red,System.Drawing.Color.Blue,System.Drawing.Color.Green,System.Drawing.Color.Purple,System.Drawing.Color.Orange,System.Drawing.Color.Brown,System.Drawing.Color.Magenta};// 根据索引返回颜色return colors[index % colors.Length];}private void StartTimer(){// 创建并配置定时器_timer new System.Timers.Timer(100); // 100毫秒的更新频率_timer.Elapsed OnTimedEvent; // 绑定定时器事件_timer.AutoReset true; // 自动重置_timer.Enabled true; // 启用定时器}private void OnTimedEvent(Object source, ElapsedEventArgs e){// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-400, 400) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataLists[i].Count _maxPoints){// 添加新的数据点_dataLists[i].Add(_currentTime, voltage);}else{// 更新现有数据点_dataLists[i][_currentIndex].Y voltage;}}// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} }注释解释 全局变量定义定义导联数量、每个导联的电压偏移量以及存储数据和曲线的变量。构造函数调用 InitializeGraph 和 StartTimer 方法初始化图表和启动定时器。InitializeGraph 方法初始化图表区域设置标题和轴标题创建每个导联的曲线对象并设置轴的范围和网格。GetColor 方法定义一组颜色根据索引返回颜色用于不同导联的曲线。StartTimer 方法创建并配置定时器设置定时器事件处理方法。OnTimedEvent 方法在定时器触发时生成模拟ECG信号数据为每个导联添加或更新数据点并刷新图表。Form1_Load 方法窗体加载事件处理方法目前为空。 添加了y轴方向的导联标签 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 500; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataLists;private LineItem[] _curves;// 定时器用于模拟ECG信号数据更新private System.Timers.Timer _timer;private int _currentIndex 0;private int _maxPoints 500;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time (s);myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataLists new PointPairList[ChannelCount];_curves new LineItem[ChannelCount];_yValues new double[ChannelCount][];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataLists[i] new PointPairList();_curves[i] myPane.AddCurve(, _dataLists[i], GetColor(i), SymbolType.None);_yValues[i] new double[_maxPoints];}// 移除图例myPane.Legend.IsVisible false;// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints * _timeIncrement;myPane.YAxis.Scale.Min -800;myPane.YAxis.Scale.Max 800 VoltageOffset * (ChannelCount - 1);// 显示网格线myPane.XAxis.MajorGrid.IsVisible true;myPane.YAxis.MajorGrid.IsVisible true;// 隐藏Y0的实线myPane.YAxis.MajorGrid.IsZeroLine false;// 自定义Y轴刻度标注Scale yScale myPane.YAxis.Scale;yScale.MajorStep VoltageOffset;yScale.MinorStep VoltageOffset;yScale.MajorStepAuto false;yScale.MinorStepAuto false;myPane.YAxis.ScaleFormatEvent new Axis.ScaleFormatHandler(FormatYScale);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private string FormatYScale(GraphPane pane, Axis axis, double val, int index){// 自定义Y轴刻度标注int leadIndex (int)Math.Round(val / VoltageOffset);if (leadIndex 0 leadIndex ChannelCount){return $Lead {leadIndex 1};}return ;}private System.Drawing.Color GetColor(int index){// 定义一组颜色用于不同导联的曲线System.Drawing.Color[] colors {System.Drawing.Color.Black,System.Drawing.Color.Red,System.Drawing.Color.Blue,System.Drawing.Color.Green,System.Drawing.Color.Purple,System.Drawing.Color.Orange,System.Drawing.Color.Brown,System.Drawing.Color.Magenta};// 根据索引返回颜色return colors[index % colors.Length];}private void StartTimer(){// 创建并配置定时器_timer new System.Timers.Timer(10); // 100毫秒的更新频率_timer.Elapsed OnTimedEvent; // 绑定定时器事件_timer.AutoReset true; // 自动重置_timer.Enabled true; // 启用定时器}private void OnTimedEvent(Object source, ElapsedEventArgs e){// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-200, 200) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataLists[i].Count _maxPoints){// 添加新的数据点_dataLists[i].Add(_currentTime, voltage);}else{// 更新现有数据点_dataLists[i][_currentIndex].Y voltage;}}// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 更新X轴刻度显示zedGraphControl1.GraphPane.XAxis.Scale.TextLabels GenerateTimeLabels(_currentTime, _timeIncrement, _maxPoints);// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private string[] GenerateTimeLabels(double currentTime, double increment, int maxPoints){string[] labels new string[maxPoints];double startTime currentTime - (maxPoints * increment);for (int i 0; i maxPoints; i){labels[i] (startTime i * increment).ToString(0.0);}return labels;}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} } 添加了时间刻度跟随时间扫描变化 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 700; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataLists;private LineItem[] _curves;// 定时器用于模拟ECG信号数据更新private System.Timers.Timer _timer;private int _currentIndex 0;private int _maxPoints 800;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();private DateTime[] _timeLabels;public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time;myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataLists new PointPairList[ChannelCount];_curves new LineItem[ChannelCount];_yValues new double[ChannelCount][];_timeLabels new DateTime[_maxPoints];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataLists[i] new PointPairList();_curves[i] myPane.AddCurve(, _dataLists[i], GetColor(i), SymbolType.None);_yValues[i] new double[_maxPoints];}// 移除图例myPane.Legend.IsVisible false;// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints;myPane.YAxis.Scale.Min -800;myPane.YAxis.Scale.Max 800 VoltageOffset * (ChannelCount - 1);// 显示网格线myPane.XAxis.MajorGrid.IsVisible true;myPane.YAxis.MajorGrid.IsVisible true;// 隐藏Y0的实线myPane.YAxis.MajorGrid.IsZeroLine false;// 自定义Y轴刻度标注Scale yScale myPane.YAxis.Scale;yScale.MajorStep VoltageOffset;yScale.MinorStep VoltageOffset;yScale.MajorStepAuto false;yScale.MinorStepAuto false;myPane.YAxis.ScaleFormatEvent new Axis.ScaleFormatHandler(FormatYScale);// 设置X轴为文本类型myPane.XAxis.Type AxisType.Text;// 设置X轴刻度字体大小myPane.XAxis.Scale.FontSpec.Size 7; // 可以根据需要调整字体大小myPane.XAxis.Scale.FontSpec.FontColor System.Drawing.Color.Black;// 初始化时间标签DateTime startTime DateTime.Now;for (int i 0; i _maxPoints; i){_timeLabels[i] startTime;}// 应用更改并刷新图表zedGraphControl1.AxisChange();}private string FormatYScale(GraphPane pane, Axis axis, double val, int index){// 自定义Y轴刻度标注int leadIndex (int)Math.Round(val / VoltageOffset);if (leadIndex 0 leadIndex ChannelCount){return $Lead {leadIndex 1};}return ;}private System.Drawing.Color GetColor(int index){// 定义一组颜色用于不同导联的曲线System.Drawing.Color[] colors {//System.Drawing.Color.Black,//System.Drawing.Color.Red,//System.Drawing.Color.Blue,//System.Drawing.Color.Green,//System.Drawing.Color.Purple,//System.Drawing.Color.Orange,//System.Drawing.Color.Brown,//System.Drawing.Color.MagentaSystem.Drawing.Color.Black,System.Drawing.Color.Black,System.Drawing.Color.Black,System.Drawing.Color.Black,System.Drawing.Color.Black,System.Drawing.Color.Black,System.Drawing.Color.Black,System.Drawing.Color.Black};// 根据索引返回颜色return colors[index % colors.Length];}private void StartTimer(){// 创建并配置定时器_timer new System.Timers.Timer(1); // 100毫秒的更新频率_timer.Elapsed OnTimedEvent; // 绑定定时器事件_timer.AutoReset true; // 自动重置_timer.Enabled true; // 启用定时器}private void OnTimedEvent(Object source, ElapsedEventArgs e){// 记录当前时间DateTime currentTime DateTime.Now;// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-200, 200) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataLists[i].Count _maxPoints){// 添加新的数据点_dataLists[i].Add(_currentIndex, voltage);}else{// 更新现有数据点_dataLists[i][_currentIndex].Y voltage;}}// 更新时间标签_timeLabels[_currentIndex] currentTime;// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 更新X轴刻度显示zedGraphControl1.GraphPane.XAxis.Scale.TextLabels GenerateTimeLabels();// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private string[] GenerateTimeLabels(){string[] labels new string[_maxPoints];for (int i 0; i _maxPoints; i){labels[i] _timeLabels[i].ToString(HH:mm:ss.fff);}return labels;}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} } 添加了个竖线扫描分界线 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 500; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataLists;private LineItem[] _curves;// 定时器用于模拟ECG信号数据更新private System.Timers.Timer _timer;private int _currentIndex 0;private int _maxPoints 500;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();private DateTime[] _timeLabels;private LineObj _scanLine;public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time (hh:mm:ss.fff);myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataLists new PointPairList[ChannelCount];_curves new LineItem[ChannelCount];_yValues new double[ChannelCount][];_timeLabels new DateTime[_maxPoints];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataLists[i] new PointPairList();_curves[i] myPane.AddCurve(, _dataLists[i], GetColor(i), SymbolType.None);_yValues[i] new double[_maxPoints];}// 移除图例myPane.Legend.IsVisible false;// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints;myPane.YAxis.Scale.Min -800;myPane.YAxis.Scale.Max 800 VoltageOffset * (ChannelCount - 1);// 显示网格线myPane.XAxis.MajorGrid.IsVisible true;myPane.YAxis.MajorGrid.IsVisible true;// 隐藏Y0的实线myPane.YAxis.MajorGrid.IsZeroLine false;// 自定义Y轴刻度标注Scale yScale myPane.YAxis.Scale;yScale.MajorStep VoltageOffset;yScale.MinorStep VoltageOffset;yScale.MajorStepAuto false;yScale.MinorStepAuto false;myPane.YAxis.ScaleFormatEvent new Axis.ScaleFormatHandler(FormatYScale);// 设置X轴为文本类型myPane.XAxis.Type AxisType.Text;// 设置X轴刻度字体大小myPane.XAxis.Scale.FontSpec.Size 10; // 可以根据需要调整字体大小// 初始化时间标签DateTime startTime DateTime.Now;for (int i 0; i _maxPoints; i){_timeLabels[i] startTime;}// 初始化扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, 0, -800, 0, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Dash;_scanLine.IsClippedToChartRect true;myPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private string FormatYScale(GraphPane pane, Axis axis, double val, int index){// 自定义Y轴刻度标注int leadIndex (int)Math.Round(val / VoltageOffset);if (leadIndex 0 leadIndex ChannelCount){return $Lead {leadIndex 1};}return ;}private System.Drawing.Color GetColor(int index){// 定义一组颜色用于不同导联的曲线System.Drawing.Color[] colors {System.Drawing.Color.Gray,System.Drawing.Color.Gray,System.Drawing.Color.Gray,System.Drawing.Color.Gray,System.Drawing.Color.Gray,System.Drawing.Color.Gray,System.Drawing.Color.Gray,System.Drawing.Color.Gray,};// 根据索引返回颜色return colors[index % colors.Length];}private void StartTimer(){// 创建并配置定时器_timer new System.Timers.Timer(50); // 100毫秒的更新频率_timer.Elapsed OnTimedEvent; // 绑定定时器事件_timer.AutoReset true; // 自动重置_timer.Enabled true; // 启用定时器}private void OnTimedEvent(Object source, ElapsedEventArgs e){// 记录当前时间DateTime currentTime DateTime.Now;// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-200, 200) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataLists[i].Count _maxPoints){// 添加新的数据点_dataLists[i].Add(_currentIndex, voltage);}else{// 更新现有数据点_dataLists[i][_currentIndex].Y voltage;}}// 更新时间标签_timeLabels[_currentIndex] currentTime;// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 更新X轴刻度显示zedGraphControl1.GraphPane.XAxis.Scale.TextLabels GenerateTimeLabels();// 更新扫描竖线位置UpdateScanLine();// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private string[] GenerateTimeLabels(){string[] labels new string[_maxPoints];for (int i 0; i _maxPoints; i){labels[i] _timeLabels[i].ToString(HH:mm:ss.fff);}return labels;}private void UpdateScanLine(){// 移除旧的扫描竖线zedGraphControl1.GraphPane.GraphObjList.Remove(_scanLine);// 添加新的扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, _currentIndex, -800, _currentIndex, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Dash;_scanLine.IsClippedToChartRect true;zedGraphControl1.GraphPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} } 我修改了扫描线左边和右边是不同颜色 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 500; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataListsLeft;private PointPairList[] _dataListsRight;private LineItem[] _curvesLeft;private LineItem[] _curvesRight;// 定时器用于模拟ECG信号数据更新private System.Timers.Timer _timer;private int _currentIndex 0;private int _maxPoints 500;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();private DateTime[] _timeLabels;private LineObj _scanLine;public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time;myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataListsLeft new PointPairList[ChannelCount];_dataListsRight new PointPairList[ChannelCount];_curvesLeft new LineItem[ChannelCount];_curvesRight new LineItem[ChannelCount];_yValues new double[ChannelCount][];_timeLabels new DateTime[_maxPoints];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataListsLeft[i] new PointPairList();_dataListsRight[i] new PointPairList();_curvesLeft[i] myPane.AddCurve(, _dataListsLeft[i], System.Drawing.Color.Black, SymbolType.None);_curvesRight[i] myPane.AddCurve(, _dataListsRight[i], System.Drawing.ColorTranslator.FromHtml(#CCCCCC), SymbolType.None);_yValues[i] new double[_maxPoints];// 初始化右边灰色波形for (int j 0; j _maxPoints; j){_dataListsRight[i].Add(j, double.NaN); // 初始化为NaN表示没有数据}}// 移除图例myPane.Legend.IsVisible false;// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints;myPane.YAxis.Scale.Min -800;myPane.YAxis.Scale.Max 800 VoltageOffset * (ChannelCount - 1);// 显示网格线myPane.XAxis.MajorGrid.IsVisible true;myPane.YAxis.MajorGrid.IsVisible true;// 隐藏Y0的实线myPane.YAxis.MajorGrid.IsZeroLine false;// 自定义Y轴刻度标注Scale yScale myPane.YAxis.Scale;yScale.MajorStep VoltageOffset;yScale.MinorStep VoltageOffset;yScale.MajorStepAuto false;yScale.MinorStepAuto false;myPane.YAxis.ScaleFormatEvent new Axis.ScaleFormatHandler(FormatYScale);// 设置X轴为文本类型myPane.XAxis.Type AxisType.Text;// 设置X轴刻度字体大小myPane.XAxis.Scale.FontSpec.Size 4; // 可以根据需要调整字体大小// 初始化时间标签DateTime startTime DateTime.Now;for (int i 0; i _maxPoints; i){_timeLabels[i] startTime;}// 初始化扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, 0, -800, 0, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Dash;_scanLine.IsClippedToChartRect true;myPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private string FormatYScale(GraphPane pane, Axis axis, double val, int index){// 自定义Y轴刻度标注int leadIndex (int)Math.Round(val / VoltageOffset);if (leadIndex 0 leadIndex ChannelCount){return $Lead {leadIndex 1};}return ;}private void StartTimer(){// 创建并配置定时器_timer new System.Timers.Timer(50); // 50毫秒的更新频率_timer.Elapsed OnTimedEvent; // 绑定定时器事件_timer.AutoReset true; // 自动重置_timer.Enabled true; // 启用定时器}private void OnTimedEvent(Object source, ElapsedEventArgs e){// 记录当前时间DateTime currentTime DateTime.Now;// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-200, 200) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataListsLeft[i].Count _maxPoints){// 添加新的数据点_dataListsLeft[i].Add(_currentIndex, voltage);}else{// 更新现有数据点_dataListsLeft[i][_currentIndex].Y voltage;}// 更新右边灰色波形数据点_dataListsRight[i][_currentIndex].Y voltage;}// 更新时间标签_timeLabels[_currentIndex] currentTime;// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 更新曲线数据UpdateCurves();// 更新X轴刻度显示zedGraphControl1.GraphPane.XAxis.Scale.TextLabels GenerateTimeLabels();// 更新扫描竖线位置UpdateScanLine();// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private void UpdateCurves(){for (int i 0; i ChannelCount; i){// 更新左边黑色部分PointPairList leftPoints _curvesLeft[i].Points as PointPairList;leftPoints.Clear();for (int j 0; j _maxPoints; j){if (j _currentIndex){leftPoints.Add(j, _yValues[i][j]);}else{leftPoints.Add(j, double.NaN);}}}}private string[] GenerateTimeLabels(){string[] labels new string[_maxPoints];for (int i 0; i _maxPoints; i){labels[i] _timeLabels[i].ToString(HH:mm:ss.fff);}return labels;}private void UpdateScanLine(){// 移除旧的扫描竖线zedGraphControl1.GraphPane.GraphObjList.Remove(_scanLine);// 添加新的扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, _currentIndex, -800, _currentIndex, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Dash;_scanLine.IsClippedToChartRect true;zedGraphControl1.GraphPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} } 第一次扫描时间刻度的设置 using System; using System.Windows.Forms; using ZedGraph; using System.Timers; using System.Drawing; using System.IO;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 500; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataListsLeft;private PointPairList[] _dataListsRight;private LineItem[] _curvesLeft;private LineItem[] _curvesRight;// 定时器用于模拟ECG信号数据更新private System.Timers.Timer _timer;private int _currentIndex 0;private int _maxPoints 1000;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();private DateTime[] _timeLabels;private LineObj _scanLine;private bool _firstScan true;public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表InitializeDataFile(); // 初始化数据文件StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time;myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataListsLeft new PointPairList[ChannelCount];_dataListsRight new PointPairList[ChannelCount];_curvesLeft new LineItem[ChannelCount];_curvesRight new LineItem[ChannelCount];_yValues new double[ChannelCount][];_timeLabels new DateTime[_maxPoints];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataListsLeft[i] new PointPairList();_dataListsRight[i] new PointPairList();_curvesLeft[i] myPane.AddCurve(, _dataListsLeft[i], System.Drawing.Color.Black, SymbolType.None);_curvesRight[i] myPane.AddCurve(, _dataListsRight[i], Color.FromArgb(100, Color.Black), SymbolType.None);_yValues[i] new double[_maxPoints];// 初始化右边灰色波形for (int j 0; j _maxPoints; j){_dataListsRight[i].Add(j, double.NaN); // 初始化为NaN表示没有数据}}// 移除图例myPane.Legend.IsVisible false;// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints;myPane.YAxis.Scale.Min -800;myPane.YAxis.Scale.Max 800 VoltageOffset * (ChannelCount - 1);// 网格线myPane.XAxis.MajorGrid.IsVisible false; // 关闭纵向主要网格线myPane.XAxis.MinorGrid.IsVisible false; // 关闭纵向次要网格线myPane.YAxis.MajorGrid.IsVisible true;// 隐藏Y0的实线myPane.YAxis.MajorGrid.IsZeroLine false;// 自定义Y轴刻度标注Scale yScale myPane.YAxis.Scale;yScale.MajorStep VoltageOffset;yScale.MinorStep VoltageOffset;yScale.MajorStepAuto false;yScale.MinorStepAuto false;myPane.YAxis.ScaleFormatEvent new Axis.ScaleFormatHandler(FormatYScale);myPane.YAxis.Scale.FontSpec.Size 8;myPane.YAxis.Scale.FontSpec.Family Times New Roman; // 设置字体为// 设置X轴为文本类型myPane.XAxis.Type AxisType.Text;// 设置X轴刻度字体大小myPane.XAxis.Scale.FontSpec.Size 5; // 可以根据需要调整字体大小myPane.XAxis.Scale.FontSpec.Family Times New Roman; // 设置字体为// 初始化时间标签DateTime startTime DateTime.Now;for (int i 0; i _maxPoints; i){_timeLabels[i] startTime;}// 初始化扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, 0, -800, 0, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Dash;_scanLine.IsClippedToChartRect true;myPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private string FormatYScale(GraphPane pane, Axis axis, double val, int index){// 自定义Y轴刻度标注int leadIndex (int)Math.Round(val / VoltageOffset);if (leadIndex 0 leadIndex ChannelCount){return $Lead {leadIndex 1};}return ;}private void StartTimer(){// 创建并配置定时器_timer new System.Timers.Timer(50); // 50毫秒的更新频率_timer.Elapsed OnTimedEvent; // 绑定定时器事件_timer.AutoReset true; // 自动重置_timer.Enabled true; // 启用定时器}private void OnTimedEvent(Object source, ElapsedEventArgs e){// 记录当前时间DateTime currentTime DateTime.Now;// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-200, 200) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataListsLeft[i].Count _maxPoints){// 添加新的数据点_dataListsLeft[i].Add(_currentIndex, voltage);}else{// 更新现有数据点_dataListsLeft[i][_currentIndex].Y voltage;}// 更新右边灰色波形数据点_dataListsRight[i][_currentIndex].Y voltage;}// 更新时间标签_timeLabels[_currentIndex] currentTime;// 实时保存数据到文件SaveCurrentDataToFile(_currentIndex, currentTime);// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 更新曲线数据UpdateCurves();// 更新X轴刻度显示zedGraphControl1.GraphPane.XAxis.Scale.TextLabels GeneratePartialTimeLabels();// 更新扫描竖线位置UpdateScanLine();// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private void UpdateCurves(){for (int i 0; i ChannelCount; i){// 更新左边黑色部分PointPairList leftPoints _curvesLeft[i].Points as PointPairList;leftPoints.Clear();for (int j 0; j _maxPoints; j){if (j _currentIndex){leftPoints.Add(j, _yValues[i][j]);}else{leftPoints.Add(j, double.NaN);}}}}private string[] GeneratePartialTimeLabels(){string[] labels new string[_maxPoints];for (int i 0; i _maxPoints; i){if (i _currentIndex || !_firstScan){labels[i] _timeLabels[i].ToString(HH:mm:ss.fff);}else{labels[i] ; // 未扫描到的位置使用空字符串}}// 仅在第一次扫描后将_firstScan设为falseif (_currentIndex _maxPoints - 1){_firstScan false;}return labels;}private void UpdateScanLine(){// 移除旧的扫描竖线zedGraphControl1.GraphPane.GraphObjList.Remove(_scanLine);// 添加新的扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, _currentIndex, -800, _currentIndex, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Solid;_scanLine.IsClippedToChartRect true;zedGraphControl1.GraphPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private void SaveCurrentDataToFile(int index, DateTime time){string filePath ECGData.txt; // 可以修改为需要保存的文件路径try{using (StreamWriter writer new StreamWriter(filePath, true)) // 以追加模式打开文件{// 写入索引writer.Write(${index},);// 写入8个导联的数据for (int j 0; j ChannelCount; j){writer.Write(${_yValues[j][index]},);}// 写入时间writer.WriteLine(time.ToString(HH:mm:ss.fff));}}catch (Exception ex){MessageBox.Show($Error saving data: {ex.Message}, Error, MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void InitializeDataFile(){string filePath ECGData.txt; // 可以修改为需要保存的文件路径try{using (StreamWriter writer new StreamWriter(filePath, false)) // 以覆盖模式打开文件{// 写入表头writer.WriteLine(Index,Lead1,Lead2,Lead3,Lead4,Lead5,Lead6,Lead7,Lead8,Time);}}catch (Exception ex){MessageBox.Show($Error initializing data file: {ex.Message}, Error, MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void btnSaveData_Click(object sender, EventArgs e){using (SaveFileDialog saveFileDialog new SaveFileDialog()){saveFileDialog.Filter Text files (*.txt)|*.txt;saveFileDialog.Title Save ECG Data;if (saveFileDialog.ShowDialog() DialogResult.OK){SaveDataToFile(saveFileDialog.FileName);}}}private void SaveDataToFile(string filePath){try{using (StreamWriter writer new StreamWriter(filePath)){// 写入表头writer.WriteLine(Index,Lead1,Lead2,Lead3,Lead4,Lead5,Lead6,Lead7,Lead8,Time);for (int i 0; i _maxPoints; i){// 写入索引writer.Write(${i},);// 写入8个导联的数据for (int j 0; j ChannelCount; j){writer.Write(${_yValues[j][i]},);}// 写入时间writer.WriteLine(_timeLabels[i].ToString(HH:mm:ss.fff));}}MessageBox.Show(Data saved successfully., Success, MessageBoxButtons.OK, MessageBoxIcon.Information);}catch (Exception ex){MessageBox.Show($Error saving data: {ex.Message}, Error, MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} } 提高响应速度 在Windows窗体应用程序中使用System.Timers.Timer其回调在不同于UI线程的线程上运行。如果你要更新UI控件如ZedGraphControl最好使用System.Windows.Forms.Timer因为它在UI线程上执行。下面是你如何改进代码以使用System.Windows.Forms.Timer来避免线程间的调度问题并提高响应速度。 此外确保图表在更新时不会频繁刷新这样可以减少卡顿。 修改后的代码 using System; using System.Windows.Forms; using ZedGraph; using System.Drawing; using System.IO;namespace ECGPlot {public partial class Form1 : Form{// 定义导联数量和每个导联的电压偏移量private const int ChannelCount 8;private const int VoltageOffset 500; // 每个导联的偏移量// 用于存储每个导联的数据点列表和曲线对象private PointPairList[] _dataListsLeft;private PointPairList[] _dataListsRight;private LineItem[] _curvesLeft;private LineItem[] _curvesRight;// 定时器用于模拟ECG信号数据更新private System.Windows.Forms.Timer _timer;private int _currentIndex 0;private int _maxPoints 1101;private double[][] _yValues;private double _timeIncrement 0.1;private double _currentTime 0;private Random _random new Random();private DateTime[] _timeLabels;private LineObj _scanLine;private bool _firstScan true;public Form1(){InitializeComponent();InitializeGraph(); // 初始化图表InitializeDataFile(); // 初始化数据文件StartTimer(); // 启动定时器}private void InitializeGraph(){// 获取图表区域对象GraphPane myPane zedGraphControl1.GraphPane;// 设置图表标题和轴标题myPane.Title.Text ECG Data;myPane.XAxis.Title.Text Time;myPane.YAxis.Title.Text Voltage;// 初始化数据点列表和曲线数组_dataListsLeft new PointPairList[ChannelCount];_dataListsRight new PointPairList[ChannelCount];_curvesLeft new LineItem[ChannelCount];_curvesRight new LineItem[ChannelCount];_yValues new double[ChannelCount][];_timeLabels new DateTime[_maxPoints];for (int i 0; i ChannelCount; i){// 为每个导联创建数据点列表和曲线对象并添加到图表中_dataListsLeft[i] new PointPairList();_dataListsRight[i] new PointPairList();_curvesLeft[i] myPane.AddCurve(, _dataListsLeft[i], System.Drawing.Color.Black, SymbolType.None);_curvesRight[i] myPane.AddCurve(, _dataListsRight[i], Color.FromArgb(100, Color.Black), SymbolType.None);_yValues[i] new double[_maxPoints];// 初始化右边灰色波形for (int j 0; j _maxPoints; j){_dataListsRight[i].Add(j, double.NaN); // 初始化为NaN表示没有数据}}// 移除图例myPane.Legend.IsVisible false;// 设置X轴和Y轴的范围myPane.XAxis.Scale.Min 0;myPane.XAxis.Scale.Max _maxPoints;myPane.YAxis.Scale.Min -800;myPane.YAxis.Scale.Max 800 VoltageOffset * (ChannelCount - 1);// 设置X轴主刻度步长使刻度标签不那么密集myPane.XAxis.Scale.MajorStep 100; // 可以根据需要调整这个值// 网格线myPane.XAxis.MajorGrid.IsVisible false; // 关闭纵向主要网格线myPane.XAxis.MinorGrid.IsVisible false; // 关闭纵向次要网格线myPane.YAxis.MajorGrid.IsVisible true;// 隐藏Y0的实线myPane.YAxis.MajorGrid.IsZeroLine false;// 自定义Y轴刻度标注Scale yScale myPane.YAxis.Scale;yScale.MajorStep VoltageOffset;yScale.MinorStep VoltageOffset;yScale.MajorStepAuto false;yScale.MinorStepAuto false;myPane.YAxis.ScaleFormatEvent new Axis.ScaleFormatHandler(FormatYScale);myPane.YAxis.Scale.FontSpec.Size 8;myPane.YAxis.Scale.FontSpec.Family Times New Roman; // 设置字体为// 设置X轴为文本类型myPane.XAxis.Type AxisType.Text;// 设置X轴刻度字体大小myPane.XAxis.Scale.FontSpec.Size 8; // 可以根据需要调整字体大小myPane.XAxis.Scale.FontSpec.Family Times New Roman; // 设置字体为// 初始化时间标签DateTime startTime DateTime.Now;for (int i 0; i _maxPoints; i){_timeLabels[i] startTime;}// 初始化扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, 0, -800, 0, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Dash;_scanLine.IsClippedToChartRect true;myPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private string FormatYScale(GraphPane pane, Axis axis, double val, int index){// 自定义Y轴刻度标注int leadIndex (int)Math.Round(val / VoltageOffset);if (leadIndex 0 leadIndex ChannelCount){return $Lead {leadIndex 1};}return ;}private void StartTimer(){// 创建并配置定时器_timer new System.Windows.Forms.Timer();_timer.Interval 50; // 50毫秒的更新频率_timer.Tick OnTimedEvent; // 绑定定时器事件_timer.Start(); // 启用定时器}private void OnTimedEvent(Object source, EventArgs e){// 记录当前时间DateTime currentTime DateTime.Now;// 为每个导联生成模拟ECG信号数据并更新曲线for (int i 0; i ChannelCount; i){double voltage _random.Next(-200, 200) i * VoltageOffset; // 生成带偏移量的电压数据_yValues[i][_currentIndex] voltage;if (_dataListsLeft[i].Count _maxPoints){// 添加新的数据点_dataListsLeft[i].Add(_currentIndex, voltage);}else{// 更新现有数据点_dataListsLeft[i][_currentIndex].Y voltage;}// 更新右边灰色波形数据点_dataListsRight[i][_currentIndex].Y voltage;}// 更新时间标签_timeLabels[_currentIndex] currentTime;// 实时保存数据到文件SaveCurrentDataToFile(_currentIndex, currentTime);// 更新时间和当前索引_currentTime _timeIncrement;_currentIndex (_currentIndex 1) % _maxPoints;// 更新曲线数据UpdateCurves();// 更新X轴刻度显示zedGraphControl1.GraphPane.XAxis.Scale.TextLabels GeneratePartialTimeLabels();// 更新扫描竖线位置UpdateScanLine();// 使图表无效以触发重绘zedGraphControl1.Invalidate();}private void UpdateCurves(){for (int i 0; i ChannelCount; i){// 更新左边黑色部分PointPairList leftPoints _curvesLeft[i].Points as PointPairList;leftPoints.Clear();for (int j 0; j _maxPoints; j){if (j _currentIndex){leftPoints.Add(j, _yValues[i][j]);}else{leftPoints.Add(j, double.NaN);}}}}private string[] GeneratePartialTimeLabels(){string[] labels new string[_maxPoints];for (int i 0; i _maxPoints; i){if (i _currentIndex || !_firstScan){labels[i] _timeLabels[i].ToString(HH:mm:ss.fff);}else{labels[i] ; // 未扫描到的位置使用空字符串}}// 仅在第一次扫描后将_firstScan设为falseif (_currentIndex _maxPoints - 1){_firstScan false;}return labels;}private void UpdateScanLine(){// 移除旧的扫描竖线zedGraphControl1.GraphPane.GraphObjList.Remove(_scanLine);// 添加新的扫描竖线_scanLine new LineObj(System.Drawing.Color.Black, _currentIndex, -800, _currentIndex, 800 VoltageOffset * (ChannelCount - 1));_scanLine.Line.Style System.Drawing.Drawing2D.DashStyle.Solid;_scanLine.IsClippedToChartRect true;zedGraphControl1.GraphPane.GraphObjList.Add(_scanLine);// 应用更改并刷新图表zedGraphControl1.AxisChange();}private void SaveCurrentDataToFile(int index, DateTime time){string filePath ECGData.txt; // 可以修改为需要保存的文件路径try{using (StreamWriter writer new StreamWriter(filePath, true)) // 以追加模式打开文件{// 写入索引writer.Write(${index},);// 写入8个导联的数据for (int j 0; j ChannelCount; j){writer.Write(${_yValues[j][index]},);}// 写入时间writer.WriteLine(time.ToString(HH:mm:ss.fff));}}catch (Exception ex){MessageBox.Show($Error saving data: {ex.Message}, Error, MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void InitializeDataFile(){string filePath ECGData.txt; // 可以修改为需要保存的文件路径try{using (StreamWriter writer new StreamWriter(filePath, false)) // 以覆盖模式打开文件{// 写入表头writer.WriteLine(Index,Lead1,Lead2,Lead3,Lead4,Lead5,Lead6,Lead7,Lead8,Time);}}catch (Exception ex){MessageBox.Show($Error initializing data file: {ex.Message}, Error, MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void btnSaveData_Click(object sender, EventArgs e){using (SaveFileDialog saveFileDialog new SaveFileDialog()){saveFileDialog.Filter Text files (*.txt)|*.txt;saveFileDialog.Title Save ECG Data;if (saveFileDialog.ShowDialog() DialogResult.OK){SaveDataToFile(saveFileDialog.FileName);}}}private void SaveDataToFile(string filePath){try{using (StreamWriter writer new StreamWriter(filePath)){// 写入表头writer.WriteLine(Index,Lead1,Lead2,Lead3,Lead4,Lead5,Lead6,Lead7,Lead8,Time);for (int i 0; i _maxPoints; i){// 写入索引writer.Write(${i},);// 写入8个导联的数据for (int j 0; j ChannelCount; j){writer.Write(${_yValues[j][i]},);}// 写入时间writer.WriteLine(_timeLabels[i].ToString(HH:mm:ss.fff));}}MessageBox.Show(Data saved successfully., Success, MessageBoxButtons.OK, MessageBoxIcon.Information);}catch (Exception ex){MessageBox.Show($Error saving data: {ex.Message}, Error, MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void Form1_Load(object sender, EventArgs e){// 窗体加载事件处理方法目前为空}} }解释 将定时器从System.Timers.Timer更改为System.Windows.Forms.Timer使其在UI线程上执行更新操作。System.Windows.Forms.Timer的回调在UI线程上运行消除了跨线程更新控件的问题。调整_timer.Interval来控制刷新频率这里设置为50毫秒。在OnTimedEvent方法中直接更新UI消除了跨线程调用的开销。 能够改善响应速度和卡顿问题。
http://www.hkea.cn/news/14393582/

相关文章:

  • 免费申请网站永久wordpress 企业小程序
  • 上海网站建设官网dw网页制作成品代码加图片
  • 创业公司做网站郑州网站推
  • 做网站都是怎么收费aspaccess做网站
  • 怎么为一个网站做外链做网站的硬件和软件环境
  • 内蒙古建设厅官网站做原型网站
  • 订制型网站费用做设计下素材有比较好的网站
  • 企业网站建设合作协议范文做旅游项目用哪家网站好
  • 上海 餐饮网站建设 会员系统免费装修设计图app
  • 织梦网站响应式模板免费下载视频在线制作免费生成
  • 运营好的网站制作中心全椒做网站
  • 做网站需要找人优化吗软件定制开发公司在哪里
  • 空白网站怎么建网页设计代码模板html静态
  • 养生网站源码西昌市做网站的
  • 建设部建造师强制注销网站小辉seo
  • seo公司网站推广全国建筑企业资质查询系统官网
  • 佛山网站建设优化制作公司长春网站制作网页
  • 深圳网站关键词推广贵阳app定制开发
  • 长治市城乡建设局网站个人做网站怎么备案
  • 做机器人的网站关键词快速上首页排名
  • 网站后台上传软件北京app开发公司排名
  • 个人做跨境电商网站有哪些易支付对接WordPress
  • 如何创新网站建设模式网络网站建
  • 网站引入百度地图互联网的推广
  • 怎么联系网站管理员营销网络平台
  • 建设工程施工员考试在哪个网站官方网站建设 磐石网络多少费用
  • 企业网站界面 优帮云注册小规模公司需要什么资料
  • 做宣传网站需要多少钱网络平台制作软件教程
  • 做网站送推广永久免费crm客户管理系统
  • 网站模板之家免费模板哈尔滨网站建设30t