Screen Script User Manual

Screen Script User Manual

The SCADA screen script has a .NET-based C# class structure. It can also be designed as a VB Script; the examples in this document use C#.
The code within the script is located in a class named MainClass. SCADA tag access, screen events, and operations on objects on the screen can be performed within this structure.

1. Screen Script Structure

The created screen script basically has a standard C# class structure.

C#
public class MainClass
{
public void Main()
{
// Code to be executed when the script starts
}
}

The Main() method is the primary method called by SCADA when starting the script. If no operation is required inside, it can be left empty, but since it is a part of SCADA’s script structure, it must not be deleted.
Event methods on the screen are generated by SCADA. The names or signatures of the event methods should not be changed, and the methods should not be deleted.
Events on the screen are defined in separate methods:

C#
public void Button_0_MouseDown(Object sender, EventArgs e)
{
// Code to run when the button is clicked
}

2. Required Libraries

The basic libraries used when working with screen objects are as follows:

C#
using System;
using System.IO;
using System.Collections;
using System.ComponentModel;
using Microsoft.CSharp;
using System.Drawing;
using System.Windows.Forms;
  • System.Windows.Forms: Used for objects like Form, Button, CheckBox, Panel, Control, etc.
  • System.Drawing: Used for visual properties like Color, Point, Size.

For example:

C#
Button_1.BackColor = Color.Green;

3. Object Types and Casting

When accessing objects on the screen, it is important to use the object in the correct C# type.
The base class for objects in Windows Forms is the Control class. Some SCADA-specific screen objects can also be accessed via the Control type.
Common properties can be accessed through an object defined as Control:

C#
Control TargetControl;
TargetControl.Width = 100;
TargetControl.Visible = true;
TargetControl.Enabled = false;

However, if object-specific properties or methods are to be accessed, the object must be cast to its actual type. For example:

C#
Button Button_0 = ScreenForm.Controls["Button_0"] as Button;
if (Button_0 != null)
{
Button_0.Text = "New Text";
Button_0.BackColor = Color.Green;
}

The as Button expression here casts the object to the Button type. If the cast fails, it returns null. Therefore, it is recommended to perform a null check before use.

4. Object Access Methods

The method of accessing objects varies depending on the object’s location on the screen and its intended use within the event.

Method 1: Direct via Form (Controls)

Used if a control is added directly to the main Form.

C#
public void Screen_Load(Object sender, EventArgs e)
{
Form ScreenForm = sender as Form;
Button Button_0 = ScreenForm.Controls["Button_0"] as Button;
if (Button_0 != null)
{
Button_0.Text = "New Text";
}
}

Warning: ScreenForm.Controls[“Button_0”] only works if Button_0 is located directly under ScreenForm.
For example:

ScreenForm
├── Button_0
└── Panel_0

In this structure, Button_0 can be found.
However:

ScreenForm
└── Panel_0
└── Button_0

In this structure, Button_0 cannot be found using ScreenForm.Controls[“Button_0”].

Method 2: Access via Container (Panel)

If an object is inside another control like a Panel, you can first access the container, then the target object.
For example:

ScreenForm
└── Panel_0
└── Button_0

C#
Control Panel_0 = ScreenForm.Controls["Panel_0"];
if (Panel_0 != null)
{
Button Button_0 = Panel_0.Controls["Button_0"] as Button;
if (Button_0 != null)
{
Button_0.Text = "New Text";
}
}

In this method, the container in which the object is located is known.

Method 3: Access via sender

When an event is triggered, the sender parameter represents the object itself that triggered the event.

C#
public void Button_0_MouseDown(Object sender, EventArgs e)
{
Control triggeredControl = (Control)sender;
// The triggeredControl variable represents
// the Button_0 object that triggered the event.
}

This method eliminates the need to access the triggering object again via Controls.

Method 4: Reaching the Main Form with FindForm()

Within an event, the FindForm() method can be used on the triggering object to reach the main Form it is located in.

C#
public void Button_1_MouseDown(Object sender, EventArgs e)
{
Control clickedButton = (Control)sender;
Form mainForm = clickedButton.FindForm();
if (mainForm != null)
{
mainForm.BackColor = Color.LightBlue;
}
}

FindForm() is especially useful when the object is located inside one or more containers.
For example:

ScreenForm
└── Panel_0
└── Panel_1
└── Button_0

Over Button_0 in this structure:

C#
Form ScreenForm = Button_0.FindForm();

the main Form can be reached.

Method 5: Deep Search with Controls.Find()

If the container of an object on the screen is unknown or if a search needs to be performed within child controls as well, Controls.Find() can be used.
Setting the second parameter to true ensures that the search is also performed within child controls.

C#
Control[] FoundControls = ScreenForm.Controls.Find("Button_0", true);
Button TargetControl = FoundControls.Length > 0 ? FoundControls[0] as Button : null;
if (TargetControl != null)
{
TargetControl.Text = "New Text";
}

For example:

ScreenForm
├── Panel_0
│ └── Button_0
└── Panel_1
└── Button_1

In this structure:

C#
ScreenForm.Controls.Find("Button_0", true);

Button_0 inside Panel_0 can be found by using this method.

Find() Result

Controls.Find() returns a Control[] array. Therefore, before using the object:

C#
FoundControls.Length > 0

a check must be performed.

Additionally, if there are multiple controls with the same name, multiple results may be returned. FoundControls[0] represents only the first found object. For this reason, it is recommended that control names on the screen be as unique as possible.

5. Comprehensive Example: Accessing a Button from Another Button

In the following example, when Button_0 is clicked, Button_1 at any level of the screen (including panels) is searched for and its color is changed.

C#
public void Button_0_MouseDown(Object sender, EventArgs e)
{
Control triggeredControl = (Control)sender;
Form mainForm = triggeredControl.FindForm();
if (mainForm != null)
{
Control[] foundControls = mainForm.Controls.Find("Button_1", true);
if (foundControls.Length > 0)
{
Button Button_1 = foundControls[0] as Button;
if (Button_1 != null)
{
Button_1.BackColor = Color.Green;
}
}
}
}

General execution order of this structure:

Event
↓
Get the triggering control via sender
↓
Reach the main Form via FindForm()
↓
Search for the target object via Controls.Find()
↓
Cast the found object to its actual type
↓
Use the object’s property or method

6. SCADA Tag Access

SCADA tags can be accessed in two basic ways.

1. Defining as a Field

Tags can be defined as fields within the class.

C#
public BOOL Beep;

In this method, tag values are read before the script runs, and the changed values are written back to the SCADA system after the script completes.

2. Dynamic Read/Write (TagRead and TagSet)

Tag values can be read or written dynamically while the script is running.
Reading:

C#
INT Value = (INT)TagRead("Tag_0");

If the tag specified with TagRead() is not found, it may return null. The returned value must be compatible with the expected data type.
Writing:

C#
BOOL Result = TagSet("Tag_0", 123);

Whether the TagSet() operation is successful can be checked via the returned result.

C#
if (Result)
{
// Tag writing operation successful
}

Warning: Ensure that the tag name is correct and the data type used is compatible with the tag.

7. Global and Local Variable Usage

If an object is to be used in multiple events, it can be defined as a field at the class level:

C#
public class MainClass
{
Form ScreenForm;
Button Button_0;
Control AlarmView_1;
}

These objects can be used from different event methods.
If an object is to be used in only a single event, it is sufficient to define it as a local variable within the method:

C#
public void Button_0_MouseDown(Object sender, EventArgs e)
{
Control triggeredControl = (Control)sender;
// Only used within this event.
}

8. Summary and Rules Table

Condition / TopicRecommended Usage / Rule
Object is directly on the FormScreenForm.Controls[“Button_0”]
Object is inside a specific PanelPanel_0.Controls[“Button_0”]
Accessing the object that triggered the event(Control)sender
Accessing the Main Form.FindForm() via the sender object
Object location is unknownControls.Find(“ObjectName”, true)
Searching within child controlsControls.Find(“ObjectName”, true)
Find() resultA Length > 0 check must be made first.
Multiple resultsFoundControls[0] is only the first found object. It is recommended that control names be unique.
CastingThe object must be cast to its actual type to access its specific properties.
Use of ‘as’If the cast fails, it returns null; it must be checked before use.
SCADA specific objectsThe Control type can be used for general properties. Casting to the appropriate type should be done for specific properties.
Global / Local variableObjects to be used in multiple events can be defined as class-level fields, while objects used in a single event can be defined locally.
Event MethodsEvent names and signatures created by SCADA should not be changed or deleted.
Tag accessThe tag name and the data type used must be correct. TagRead and TagSet results should be checked appropriately.

Leave a Reply