常用的工业触摸屏数据框能具备显示、修改、显示加修改,本文重点是将TextBox控件具备工业屏的显示加修改的能力。
第一步:建立C# 和PLC的通讯链接,因为通讯方式太多,本文只黏贴代码,不做介绍,详情请看其他文章
private void BtnS7OpenLink_Click(object sender, EventArgs e)
{
S71200 = new Plc(CpuType.S71200, txtAddress.Text, Convert.ToInt16(txtRack.Text), Convert.ToInt16(txtSlot.Text));
if (!S71200.IsConnected)
{
try { S71200.Open(); }
catch (Exception ex)
{ MessageBox.Show(ex.Message); }
}
if (S71200.IsConnected)//通讯建立,建立多线程交互数据
{
btnS7OpenLink.Enabled = false;
btnS7CloseLink.Enabled = true;
groupBoxLink.Visible = false;
try
{
Task.Run(() =>
{
while (true)
{
/*以下属性值受 属性改变通知 影响,会改变主线程的UI。
* 多线程运行的程序是不能直接修改主线程UI的
*/
this.Invoke(new Action(() => // 调用 this.Invoke(new Action(() => {******})); 可以修改主线程UI
{
if (S71200.IsConnected)
{
// S71200.ReadClass(plcDate, 61);
//S71200.ReadClass(xy_ControlDate, 63);
S71200.ReadClass(weightDate, 21);
}
}));
Thread.Sleep(200);
}
});
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
MessageBox.Show("通讯成功" + S71200.IP);
}
else { MessageBox.Show("连接失败"); }
}
第二步:数据显示
本文的数据显示需要调用配置好DB快,上述代码的DB块是DB21
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using S7.Net;//西门子通讯驱动包
using S7.Net.Types;
namespace S7LinkTest
{
internal class WeightDate : INotifyPropertyChanged
{
private float i_SetRation;
public float I_SetRation
{ get { return i_SetRation; } set { if (value != i_SetRation) { i_SetRation = value; Change(nameof(I_SetRation)); } } }
private float i_AdjPosition;
public float I_AdjPosition
{ get { return i_AdjPosition; }set { if (value != i_AdjPosition) { i_AdjPosition = value; Change(nameof(I_AdjPosition)); } }}
private float i_AdjPosSpeed;
public float I_AdjPosSpeed
{ get { return i_AdjPosSpeed; } set { if (value != i_AdjPosSpeed) { i_AdjPosSpeed = value; Change(nameof(I_AdjPosSpeed)); } } }
private float i_DeadCount;
public float I_DeadCount
{ get { return i_DeadCount; } set { if (value != i_DeadCount) { i_DeadCount = value; Change(nameof(I_DeadCount)); } } }
private float i_I_OriPos;
public float I_I_OriPos
{ get { return i_I_OriPos; } set { if (value != i_I_OriPos) { i_I_OriPos = value; Change(nameof(I_I_OriPos)); } } }
private float i_HPos1;
public float I_HPos1
{ get { return i_HPos1; } set { if (value != i_HPos1) { i_HPos1 = value; Change(nameof(I_HPos1)); } } }
private float i_HPos2;
public float I_HPos2
{ get { return i_HPos2; } set { if (value != i_HPos2) { i_HPos2 = value; Change(nameof(I_HPos2)); } } }
private float i_HPos3;
public float I_HPos3
{ get { return i_HPos3; } set { if (value != i_HPos3) { i_HPos3 = value; Change(nameof(I_HPos3)); } } }
private float i_LPos1;
public float I_LPos1
{ get { return i_LPos1; } set { if (value != i_LPos1) { i_LPos1 = value; Change(nameof(I_LPos1)); } } }
private float i_LPos2;
public float I_LPos2
{ get { return i_LPos2; } set { if (value != i_LPos2) { i_LPos2 = value; Change(nameof(I_LPos2)); } } }
private float i_LPos3;
public float I_LPos3
{ get { return i_LPos3; } set { if (value != i_LPos3) { i_LPos3 = value; Change(nameof(I_LPos3)); } } }
private float i_CycleSpeed1;
public float I_CycleSpeed1
{ get { return i_CycleSpeed1; } set { if (value != i_CycleSpeed1) { i_CycleSpeed1 = value; Change(nameof(I_CycleSpeed1)); } } }
private float i_CycleSpeed2;
public float I_CycleSpeed2
{ get { return i_CycleSpeed2; } set { if (value != i_CycleSpeed2) { i_CycleSpeed2 = value; Change(nameof(I_CycleSpeed2)); } } }
private float i_CycleSpeed3;
public float I_CycleSpeed3
{ get { return i_CycleSpeed3; } set { if (value != i_CycleSpeed3) { i_CycleSpeed3 = value; Change(nameof(I_CycleSpeed3)); } } }
private float i_AngularSpeed1;
public float I_AngularSpeed1
{ get { return i_AngularSpeed1; } set { if (value != i_AngularSpeed1) { i_AngularSpeed1 = value; Change(nameof(I_AngularSpeed1)); } } }
private float i_AngularSpeed2;
public float I_AngularSpeed2
{ get { return i_AngularSpeed2; } set { if (value != i_AngularSpeed2) { i_AngularSpeed2 = value; Change(nameof(I_AngularSpeed2)); } } }
private float i_AngularSpeed3;
public float I_AngularSpeed3
{ get { return i_AngularSpeed3; } set { if (value != i_AngularSpeed3) { i_AngularSpeed3 = value; Change(nameof(I_AngularSpeed3)); } } }
private float i_Allowance2;
public float I_Allowance2
{ get { return i_Allowance2; } set { if (value != i_Allowance2) { i_Allowance2 = value; Change(nameof(I_Allowance2)); } } }
private float i_Allowance3;
public float I_Allowance3
{ get { return i_Allowance3; } set { if (value != i_Allowance3) { i_Allowance3 = value; Change(nameof(I_Allowance3)); } } }
private float w_CurrentQuality;
public float W_CurrentQuality
{ get { return w_CurrentQuality; } set { if (value != w_CurrentQuality) { w_CurrentQuality = value; Change(nameof(W_CurrentQuality)); } } }
private float w_OverTime1;
public float W_OverTime1
{ get { return w_OverTime1; } set { if (value != w_OverTime1) { w_OverTime1 = value; Change(nameof(W_OverTime1)); } } }
private byte w_ControlByte1;
public byte W_ControlByte1
{ get { return w_ControlByte1; } set { if (value != w_ControlByte1) { w_ControlByte1 = value; My_ValueChanged.Invoke(); } } }
private float i_AdjRation;
public float I_AdjRation
{ get { return i_AdjRation; } set { if (value != I_AdjRation) { w_OverTime1 = value; Change(nameof(I_AdjRation)); } } }
private float i_Ration;
public float I_Ration
{ get { return i_Ration; } set { if (value != I_Ration) { i_Ration = value; Change(nameof(I_Ration)); } } }
private float w_OverTime2;
public float W_OverTime2
{ get { return w_OverTime2; } set { if (value != w_OverTime2) { w_OverTime2 = value; Change(nameof(W_OverTime2)); } } }
private float w_OverTime3;
public float W_OverTime3
{ get { return w_OverTime3; } set { if (value != w_OverTime3) { w_OverTime3 = value; Change(nameof(W_OverTime3)); } } }
#region 方法:属性改变通知
/*
*internal class PlcDate: INotifyPropertyChanged //INotifyPropertyChanged 通知客户端属性值已更改
* 建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
*/
public event PropertyChangedEventHandler? PropertyChanged;//建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
public void Change(string PropertyName)
{
if (PropertyChanged != null)
{ PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); }
}
#endregion 方法:属性改变通知
public event Action My_ValueChanged;//定义一个基于Action委托的事件My_ValueChange;
/* private bool bool_Value;
public bool Bool_Value
{
get { return bool_Value; }
set { bool_Value = value; My_ValueChanged?.Invoke(); }
}*/
//public event Action My_ValueChanged;
}
}
以上的而代码需要注意的是以下几种
internal class WeightDate : INotifyPropertyChanged
这段代码是给这个class分配了一个接口属性 INotifyPropertyChanged
private float i_SetRation;
public float I_SetRation
{ get { return i_SetRation; } set { if (value != i_SetRation) { i_SetRation = value; Change(nameof(I_SetRation)); } } }
定义了一个变量类型,使用了一个Change函数,函数的定义子啊下面
#region 方法:属性改变通知
/*
*internal class PlcDate: INotifyPropertyChanged //INotifyPropertyChanged 通知客户端属性值已更改
* 建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
*/
public event PropertyChangedEventHandler? PropertyChanged;//建立委托:表示将处理 PropertyChanged 事件的方法,该事件在更改组件上的属性时引发。
public void Change(string PropertyName)
{
if (PropertyChanged != null)
{ PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); }
}
#endregion 方法:属性改变通知
public event Action My_ValueChanged;//定义一个基于Action委托的事件My_ValueChange;
上述是给接口配置了一个委托,并定义了函数功能。
为什么要定义这个接口和委托呢?
TextBox的数据值是Text的,plc那边的数据是浮点数,这两者数据不一致,需要转换,因此需要一个接口帮助我们实现这个转换功能。
textBoxSetMeasure.DataBindings.Add("Text", weightDate, "I_SetRation");
然后用上数据绑定,将PLC读取的数据绑定给TextBox,再加上上文的接口功能,程序代码就不会报错。
第三步:数据更改
private void TextBox2_KeyPress(object sender, KeyPressEventArgs e)//按键输入控制
{
if ((e.KeyChar >= '0' && e.KeyChar <= '9') || e.KeyChar == '.' || e.KeyChar == 8)
{
if (textBoxSetMeasure.Text.Contains('.') && e.KeyChar == '.')
{ e.Handled = true; ; }
}
else { e.Handled = true; }//取消输入
if (e.KeyChar == 13)
{
S71200.Write("DB21.DBW0", (float)Convert.ToDouble(textBoxSetMeasure.Text));
this.tabPage8.Focus();
}
if (e.KeyChar == 27)
{ this.tabPage8.Focus(); }
}
再数据更改中,我们得调用事件功能 KeyPress
在KeyPress中我们得做几件事情
1)你想键入那些数据,是字符串还是数值,如果是数值,不允许非数值数据输入
2)键入数据完成后,指定回车被按下,则传输数据给PLC完成数据输入
3)不想输入时,指定ESC退出
要相做这些事情,我们得清楚电脑案件被按下也是一个ascii码,其中回车码是 e.KeyChar == 13
然后还得清楚A~Z 、a~~z 、0~~9 对应的 e.KeyChar 值,确定好后,可以控制键入数据是否有效,有效的则允许,否则拒绝。
判断下回车键是否被激活,激活后按照指定地址传输数据,并将焦点切换到默认位置。