1

I'm trying to resize an open window and as there seems to be no way to do this in Wonderware Application Server I thought maybe a .Net function may work. I've used the System.Windows.Forms.MessageBox.Show script below in the Wonderware Application Server with a button activation script. Is there a similar function to simple change the Hight and Width of the currently active window?

The message box is just an example that the Wonderware Application Server application can access some System.Windows.Forms functions in it's QuickScript.NET scripting. The Windows Forms library (system.windows.forms.dll) was imported into the Wonderware Application Server application. The script would be running on an open window and I'd like to resize it but I can't get the .Net size function to work in QuickScript.NET.


Found this System Platform DLL example http://www.plctalk.net/qanda/showthread.php?t=114301 but Visual Studio has like 20 different Class Library templates. If I try the Class Library (.Net Framework) - C# template I get a dll and can import it into System Platform, I can then find the function in the Function Browser but nothing happens in runtime when the script is run and I get this error in the SMC log: Script execution exception.Message: Non-static method requires a target..

Demo - Visual Studio 2019 and the Class Library (.Net Framework) - C# template code:

namespace ClassLibraryDemo
{
    public class DemoClass
    {
        public int GetAdd(int a, int b)
        {
            return a + b;
        }
    }
}

Demo - System Platform Button Script - For this demo code it now works with the cls = new line added.

dim cls as ClassLibraryDemo.DemoClass;
cls = new ClassLibraryDemo.DemoClass();
Me.°Test = cls.GetAdd(Me.°Test,3);

Unfortunately, the resize code that I need still has the Non-static error and it already has the object equals new line.

ResizableForm - Visual Studio 2019 and the Class Library (.Net Framework) - C# template code:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ClassLibraryROB4
{
    public class ResizableForm
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();

        public Form GetCurrentWindow()
        {
            IntPtr activeWindowHandle = GetForegroundWindow();
            Form f = Control.FromHandle(activeWindowHandle) as Form;
            return f;
        }
    }
}

ResizableForm - System Platform Button Script. Now with Try-Catch

Try

Dim myLib As ClassLibraryROB4.ResizableForm;
Dim myGfc As System.Windows.Forms.Form;

myLib = new ClassLibraryROB4.ResizableForm();
myGfc = myLib.GetCurrentWindow();

myGfc.Width = 10;
myGfc.Height = 10;

catch LogError(error); endtry;

SMC Error - Try-Catch


A900.Faceplate1_Control.BUTTON2: System.Reflection.TargetException: Non-static method requires a target.
   at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at ArchestrA.QuickScript.EvaluateFunction.Evaluate(IReferenceManagerRuntime rmr)
   at ArchestrA.QuickScript.RunExpressionStatement.Run(RuntimeContext context)
   at ArchestrA.QuickScript.RunStatements.Run(RuntimeContext context)
   at ArchestrA.QuickScript.RunTryCatch.Run(RuntimeContext context)
Tanquen
  • 11
  • 4

2 Answers2

1

create custom form and set properties as you want :

static CustomMsgBox MsgBox; static DialogResult result = DialogResult.No;
////////////////////////////////////////////////////////////////////////////////
public static DialogResult Show(string Text, string Caption, string btnOK, string btnCancel)
{
     MsgBox = new CustomMsgBox();
     MsgBox.label1.Text = Text;
     MsgBox.button1.Text = btnOK;
     MsgBox.button2.Text = btnCancel;
     MsgBox.Text = Caption;
     result = DialogResult.No;
     MsgBox.ShowDialog();
     return result;
}
////////////////////////////////////////////////////////////////////////////////
result = DialogResult.Yes; MsgBox.Close();

This tutorial may helpful for you

And this link for resizing and positioning for windows form

  • The message box was just an example that the Wonderware Application Server application can access some System.Windows.Forms functions in it's QuickScript.NET scripting. The Windows Forms library (system.windows.forms.dll) was imported into the Wonderware Application Server application. The script would be running on an open window and I'd like to resize it but I can't get the .Net size function to work in QuickScript.NET. – Tanquen Apr 21 '21 at 16:06
  • Okey, Let me think something else. – Krishna Bankar Apr 21 '21 at 16:50
0

If you're willing to dabble in using Script Function libraries you can write a utility to make graphics expandable.

I got the original tutorial from this site if you search for "Expandable Popups in Wonderware ArchestrA" but it looks like they're moving their tutorials behind a signup page.

#1 - Create your Script Function library.
I wrote very basic Class library in Visual Studio using C# which looks like this:

public class ResizableForm
{
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();

    public Form GetCurrentWindow()
    {
        IntPtr activeWindowHandle = GetForegroundWindow();
        Form f = Control.FromHandle(activeWindowHandle) as Form;
        return f;
    }
}

#2 - Import to ArchestrA
From the IDE main window: Galaxy -> Import -> Script Function Library...
Then select the .dll that you built from #1

#3 - ArchestrA Graphic Script
When calling the graphic you want to resize, make sure you're setting an explicit Width/Height on it, then you can dynamically resize it by putting something to trigger a script like this:

Dim myLib As ResizableForm;
Dim myGfc As System.Windows.Forms.Form;

myLib = new ResizableForm();
myGfc = myLib.GetCurrentWindow();

myGfc.Width = #;
myGfc.Height = #;

...and I think that's it. Hopefully that gets you far enough along that you can toy with the rest. I do recommend going through the EverDyn site's tutorial for better examples/details.

EDIT: I guess I should just mention that the GetCurrentWindow() call is super powerful to have in ArchestrA graphics. I use another Script to get a handle of the current graphic and call some .NET functions to print the current window to a dynamically chosen printer so my clients can create labels to stick to things. Basically if you can get the Form handle from this function you can use most .NET libraries to manipulate it how you're wanting. Good luck!


CODE EDIT AS PER COMMENT:

try
  dim formID as System.IntPtr;
  dim currentForm as System.Windows.Forms.Form;

  formID = ClassLibraryROB4.ResizableForm.GetForegroundWindow();
  currentForm = System.Windows.Forms.Control.FromHandle(formID);

  currentForm.Width = #;
  currentForm.Height = #;
catch
  LogError(error);
endtry;

  
Grambot
  • 4,370
  • 5
  • 28
  • 43
  • 1
    I'll take a look as soon as I can and this sounds good but it may not work. To add to the complexity this is a System Platform 2020 R2 OMI application and a number of things don't work in the OMI. The ShowGraphic command should be able to simply replace the open window with the same one at a new size but the Identity property no longer works and you can't close the window with script. They need to fix it. Other functions like the GetCurrentWindow() I think are also not supported in InTouch OMI. :( That is why I was hoping the .Net Size function may work. – Tanquen Apr 23 '21 at 19:58
  • Oof, those are both big issues that'll prevent me from going from 2017u2 to 2020. Have you talked with any AVEVA tech support folks yet to see if they have solutions? – Grambot Apr 27 '21 at 18:11
  • 1
    It's mostly because they are tying to go OMI only. It was not until 2020R2 that OMI could even access the logged in users role and access level. :) I can't find the guide on the Everdyn site. I have MS Visual Studio but no clue how to use it, what type of library and how to make the DLL. Our local rep support don't want to even look at it. Still like to give it a shot if you have any pointers. – Tanquen Apr 28 '21 at 20:19
  • If you go to my link on the answer above, scroll to the bottom then jump to page #4 and you'll find the article linked there. Direct link: https://www.everdyn.com/single-post/2013/03/21/expandable-popups-in-wonderware-archestra If you google creating a Class Library in Visual Studio you'll get a better guide than anything I can write up on StackOverflow. You're basically just generating a .dll file that you can import with Archestra – Grambot May 03 '21 at 18:20
  • Ok, Visual Studio has like 20 different Class Library templates. You said C# so I did the Class library with the C# logo. Then the .Net Core 3.1 Long-term support. But I get errors, added info to my OP. – Tanquen May 06 '21 at 00:10
  • The code in step 3 fails. "Unknown type: ResizableForm" – Tanquen May 06 '21 at 16:25
  • You'll likely need to address it as `WinFormsLibraryRB.ResizableForm` since you have it in the namespace `WinFormsLibraryRB`. See if that works? – Grambot May 06 '21 at 17:14
  • Can I remove the NameSpace from the DLL code? The everdyn example don't cover much about the DLL. They use "Dim MyWindowManipulation AS Everdyn.WindowManipulation;", so the Namespace is Everdyn but WindowManipulatio is not in their DLL code. After the Dim they do use the MyWindowManipulation.GetCurrentWindow. "WinFormsLibraryRB.ResizableForm" still says Unknown Type. Maybe Windows Forms Class Library is the wrong template, – Tanquen May 06 '21 at 18:40
  • I think you can remove the namespace. I honestly don't know. The other part to check is in your Project Properties, I bet there's a "Default Namespace" entry there. I don't think you want a "Windows Forms Class Library", the only option in my Visual Studio (2019) is for "Class Library". Check out this tutorial on creating Class Libraries, it might help you out: Tutorial: https://learn.microsoft.com/en-us/dotnet/core/tutorials/library-with-visual-studio – Grambot May 06 '21 at 20:33
  • 1
    Current issue is what Visual Studio (2019) template to use? I see pages of options. You said there is just one, are you starting with Create a new project? Pic of part of the list added to OP. I tried I think, just a C# Class Library but it would not let me add the "using System.Windows.Forms;" and without it you get errors. The "Windows Forms Class Library" template lets me add the Win Forms using so no errors creating the dll but no function is added in System Platform. – Tanquen May 06 '21 at 21:00
  • 1
    http://www.plctalk.net/qanda/showthread.php?t=114301 I found this thread about getting a function into System platform and it worked using a Class Library (.NET Framework) but it also can't use the "using System.Windows.Forms;" line in the code. But it does add a function into System Platform. – Tanquen May 06 '21 at 21:01
  • 1
    I found you can add a reference to the System.Windows.Forms in the Class Library (.NET Framework) template. So, get a dll that I can import into System Platform and it is listed under the Script Function Browser and the script has no errors but in runtime nothing happens when the button with the script is used and this is in the SMC log: Script execution exception.Message: Non-static method requires a target.. System.Reflection.TargetException: Non-static method requires a target. – Tanquen May 06 '21 at 22:55
  • 1
    I got this example http://www.plctalk.net/qanda/showthread.php?t=114301 to work but only after making the class and int static in Visual Stuido. Like "static public class DemoClass" But the DIM in the System Platform script no longer works. So this works: Me.intTest = demo.DemoClass.GetAdd( 2, 3 ); But this has an error saying cls has no GetAdd function. dim cls as demo.DemoClass; Me.intTest = cls.GetAdd(2,3); – Tanquen May 07 '21 at 01:35
  • I think you're getting close but went down the wrong path using the `static` class identifier. Once you get it compiling, you'd go back to using `DIM varname AS ClassName; varname = new ClassName(); varname.function();` The `static` identifier makes it so you get to skip the class instantiation (the `dim` and `= new Class();` lines but I've never toyed with static functions in Wonderware to help. One thing you can try is wrapping your code in `try catch LogError(error); endtry;` to see if SMC logs why it doesn't like your code – Grambot May 07 '21 at 17:18
  • I'm am getting close but it is odd that your code and the very simple example I found cause the "Non-static method requires a target" error. Googling that it seems to be when you have an empty parameter or function but I don't know. As the error mentions static I tried adding that to the code but neither of you two talk about it. So am I using the wrong library template in Visual Studio or did something in System Platform change? Big shock I know but I can not add the try-catch without errors in Visual Studio. :( Or is it meant to be in the System Platform script? – Tanquen May 08 '21 at 15:42
  • Ok, removed the static identifiers in Visual Studio and I added the try function to the test button script in System Platform and it's same error in the SMC but it is now red error and without the Try-Catch function it is a warring. I've added the full errors to the OP, – Tanquen May 08 '21 at 15:58
  • I think you're getting very close! You need to add `cls = new ClassLibraryDemo.DemoClass();` after your declaration (the line starting `dim cls`). – Grambot May 11 '21 at 14:33
  • Thanks for sticking with this. The demo example now works but it is odd as the thread with the example even has a screen shot of the code working and changing a value but it don't have the cls = new line. ??? Unfortunately, your code that I need still has the same Non-static error and it already has the new line after the Dim "myLib = new ResizableForm();". Aren't computers fun? :( – Tanquen May 11 '21 at 15:34
  • I tried adding new to the 'myGfc = myLib.GetCurrentWindow();' line but System Platform just gives a Type Not Found error. – Tanquen May 11 '21 at 16:02
  • Have you imported the `System.Windows.Forms.dll` as a Script Function Library? It should already exist on your computer (it comes with the .NET installation) but you'll have to import it as part of the Galaxy for that to work. Its easy to miss, but its mentioned in that EverDyn tutorial. – Grambot May 11 '21 at 19:14
  • Yes, I imported it some time ago to use the message box in the application. Hmm... I have be doing all this on a test VM, maybe I did not import the System.Windows.Forms.dll, I'll check in the morning. – Tanquen May 12 '21 at 00:50
  • I might be hitting the end of my ability to help. If you wrap your entire script with the `try-catch` block (including the variable declarations) you'd hopefully get a real error in the SMC log before it hits that exception (which looks more like an issue within the ArchestrA system instead of something in your code). Can you post your full button script in the question? I worry that we've run into one of Wonderware's classic gremlins – Grambot May 12 '21 at 13:15
  • But this is something that you are using or have used before? I did update the OP the other day and it has the Visual Studio code and System Platform script for the simple demo and the code you posted. I'm sure System.Windows.Forms.dll had been imported as System Platform auto fills in the "System.Windows.Forms.Form;" as I type it out. I'll try the Try-Catch again. – Tanquen May 12 '21 at 15:30
  • I added the try-catch to the button script and the resulting error in the question. – Tanquen May 12 '21 at 15:42
  • Last suggestion is trying just a slightly modified version of this; code pasted in my answer, but if that doesn't work I think that's as far as I can go. I'm sorry it doesn't work. Your Class Library code is identical to mine. Even your ArchestrA script code is virtually identical. At this point the problem has to lie in the newer Wonderware version. My company does have a project being done in 2020 currently so I'll hopefully get my hands on the software shortly and can troubleshoot it locally. Maybe I'll be able to give pointers then. – Grambot May 12 '21 at 18:01
  • I get the same error, that is a bummer. Thanks for trying. It's seem like it could work but I don't what the current 2020 R2 issue is. It seems like something has change as the simple addition DLL had to have modified script to get passed the same error message. What version do you have it working on. I think I have access to 2017 and 2014. May if I have it working in an old version I can bug support. – Tanquen May 12 '21 at 19:47
  • Definitely works on 2014 which is what my client is running. I have 2017 on a VM that I can test it with later on and report back. – Grambot May 12 '21 at 21:17
  • I was able to dig up an old 2014 R2 SP1 VM and both DLLs and script behave the same as 2020 R2. Not sure what I am missing. ??? :( I don't know how they got that simple addition DLL and scrip to work with out the "cls = new ClassLibraryDemo.DemoClass();" line. – Tanquen May 13 '21 at 23:14
  • Do you know exactly what line of the ArchestrA script throws the exception? Maybe we can narrow it down and find out? The other thing I was wondering about, is when you were updating/publishing new DLLs for your Class Library, were you updating the version numbers? I'm wondering if Wonderware held onto a previous copy in some way. – Grambot May 14 '21 at 15:30
  • I wondered about the DLL updates and had seen posts about how you have to change the version of the DLL to get the IDE to update. The 2020 R2 VM has asked if I want to replace the current DLL, maybe something new or I change enough in Visual Studio to cause a new version. The 2014 VM never had it and I imported the latest DLL with the code from the OP. Not many if any lines to comment out and not just have it invalidate the System Platform script. It's got to be the myLib or myGfc objects it thinks are not correctly defined. Like the simple addition DLL until the "cls = new..." was added. – Tanquen May 14 '21 at 18:14
  • If I comment out the myGfc.Width and myGfc.Height there is no error but nothing happens. – Tanquen May 14 '21 at 18:37
  • Maybe something is wrong with the Class library or the user32.dll it needs? I'd be curious to see/know more about the working one you have in 2014. Maybe the OS it is running on matters. – Tanquen May 25 '21 at 15:33