Hi all,
So, here's the problem I have:
I have a screen (let's call it Screen1), which contains different controls (buttons, charts, text). What I'm trying to do here is to interact with these controls from a scriptmodule, which contains a function that is run in set intervals via the scheduler. The main control I want to manipulate is the chart (the Windows.Forms one, not a trend viewer).
However, Globals.Screen1 only has one function - Show(), with no access to the controls inside.
Anyone have any good suggestions on how to interact with these controls across modules/screens? Alternatively, is there some way I can call a function located in the screen code from a scheduler?
Thanks in advance.
Accessing screen controls from scriptmodules
-
- Posts: 137
- Joined: Mon Jun 11, 2012 2:10 pm
Re: Accessing screen controls from scriptmodules
Hi liestol,
The biggest issue you have is the screen does not necessarily exist in memory until you call the Show method. That being said, you cannot directly hook anything in your ScriptModule back to the screen.
Based on the fact that you said you are using iX's scheduler, I'm assuming you aren't doing any multithreading to run your script, which simplifies things. What you want to do is create a structure inside your script module which contains all the stuff you want to control from your script. For example, if you wanted to control a button, textbox, and chart you could use
In your script module, you would create a publicly accessible implementation of this structure
and update values in it to update the screen. When the object is null you know the screen is closed. To implement on the screen side you would do the following
If you needed to initialize the screen you could add more components to the structure for the screen to read and populate when it opens.
The biggest issue you have is the screen does not necessarily exist in memory until you call the Show method. That being said, you cannot directly hook anything in your ScriptModule back to the screen.
Based on the fact that you said you are using iX's scheduler, I'm assuming you aren't doing any multithreading to run your script, which simplifies things. What you want to do is create a structure inside your script module which contains all the stuff you want to control from your script. For example, if you wanted to control a button, textbox, and chart you could use
Code: Select all
public struct ScreenData
{
public Button btn;
public Textbox tb;
public Chart crt;
public ScreenData()
{
btn = null;
tb = null;
crt = null;
}
}
Code: Select all
public ScreenData screenData = new ScreenData();
Code: Select all
public partial class Screen1
{
void Screen1_Opened(System.Object sender, System.EventArgs e)
{
// indicate screen is open
Globals.scriptModule.screenData.btn = button1;
Globals.scriptModule.screenData.tb = textbox1;
Globals.scriptModule.screenData.crt = chart1;
}
void Screen1_Closing(System.Object sender, System.ComponentModel.CancelEventArgs e)
{
// indicate screen is closed
Globals.scriptModule.screenData.btn = null;
Globals.scriptModule.screenData.tb = null;
Globals.scriptModule.screenData.crt = null;
}
}
Adam M.
Controls Engineer
FlexEnergy
Controls Engineer
FlexEnergy
Re: Accessing screen controls from scriptmodules
Adam,
Thanks a lot for your input. I've successfully managed to interact with the screen controls from the script module. However, there's a few follow up questions I have:
- Setting the control values (Globals.scriptModule.screenData.btn = button1; / Globals.scriptModule.screenData.btn = null;) in screen opened/closed gives me a CS1690 warning: Accessing a member on Neo.ApplicationFramework.Generated.scriptModule.screenData may cause a runtime exception because it is a field of a marshal-by-reference class. Any idea how to solve this?
- Forcing the screen to not be cached (for testing purposes) causes a crash when exiting the screen, throwing a System.Reflection.TargetInvocationException --> System.NullReferenceException error. This happens after Screen_Closing, but before Screen_Closed.
Any input would be greatly appreciated. Thanks again.
edit: With regards to the TargetInvocationException, this seems to happen at System.Windows.Forms.DataVisualization.Charting.Chart.get_Series().
edit2: I solved the crash. I had a lot of chart initialization in Screen_Opened(), moved all this to the scriptmodule and refered to the struct, and left only Globals.scriptModule.screenData.crt = chart1; and a newly created initialize function in the scriptmodule (containing the stuff I moved from Screen_Opened). Works like a charm now.
With regards to my first question, I assume this is something that will never generate an error as long as the struct objects are set to null every time I close the screen.
Thanks a lot for your input. I've successfully managed to interact with the screen controls from the script module. However, there's a few follow up questions I have:
- Setting the control values (Globals.scriptModule.screenData.btn = button1; / Globals.scriptModule.screenData.btn = null;) in screen opened/closed gives me a CS1690 warning: Accessing a member on Neo.ApplicationFramework.Generated.scriptModule.screenData may cause a runtime exception because it is a field of a marshal-by-reference class. Any idea how to solve this?
- Forcing the screen to not be cached (for testing purposes) causes a crash when exiting the screen, throwing a System.Reflection.TargetInvocationException --> System.NullReferenceException error. This happens after Screen_Closing, but before Screen_Closed.
Any input would be greatly appreciated. Thanks again.
edit: With regards to the TargetInvocationException, this seems to happen at System.Windows.Forms.DataVisualization.Charting.Chart.get_Series().
edit2: I solved the crash. I had a lot of chart initialization in Screen_Opened(), moved all this to the scriptmodule and refered to the struct, and left only Globals.scriptModule.screenData.crt = chart1; and a newly created initialize function in the scriptmodule (containing the stuff I moved from Screen_Opened). Works like a charm now.
With regards to my first question, I assume this is something that will never generate an error as long as the struct objects are set to null every time I close the screen.
-
- Posts: 137
- Joined: Mon Jun 11, 2012 2:10 pm
Re: Accessing screen controls from scriptmodules
liestol,
Correct, as long as you don't keep the reference when the window closes and you don't use multithreading you should not get an exception.
If you don't want the warning when you compile, instead of passing entire controls between your screen and the scriptmodule you can pass the underlying information you want displayed and use an event to let the screen know to update the information. To do this you could either create an event or just use a boolean type tag. With the tag, you would call the tag's toggle function within the scriptmodule every time you update the structure and the screen would catch the tag changed event.
This method is a little cleaner as it doesn't require you to pass displayed controls between a screen and background script, but it doesn't give your script the direct control you were looking for.
Correct, as long as you don't keep the reference when the window closes and you don't use multithreading you should not get an exception.
If you don't want the warning when you compile, instead of passing entire controls between your screen and the scriptmodule you can pass the underlying information you want displayed and use an event to let the screen know to update the information. To do this you could either create an event or just use a boolean type tag. With the tag, you would call the tag's toggle function within the scriptmodule every time you update the structure and the screen would catch the tag changed event.
Code: Select all
void Screen1_Opened(System.Object sender, System.EventArgs e)
{
Globals.Tags.ToggleTag.ValueChange += Update_Display;
Update_Display(sender, e); // initialize display
}
void bckgnd_Closing(System.Object sender, System.ComponentModel.CancelEventArgs e)
{
Globals.Tags.ToggleTag.ValueChange -= Update_Display;
}
private void Update_Display(System.Object sender, System.EventArgs e)
{
// read structure and update display
}
Adam M.
Controls Engineer
FlexEnergy
Controls Engineer
FlexEnergy
Re: Accessing screen controls from scriptmodules
Adam,
Thanks for the insight. The warning isn't really much of a concern, as I suppose I shouldn't run into issues as long as the objects are nulled and disposed of when closing the screen.
Good to see that there's a bit of a community emerging here on the forums. Thanks again, I greatly appreciate it!
Thanks for the insight. The warning isn't really much of a concern, as I suppose I shouldn't run into issues as long as the objects are nulled and disposed of when closing the screen.
Good to see that there's a bit of a community emerging here on the forums. Thanks again, I greatly appreciate it!