In this article:
Starting and Displaying Fore.NET Form
Article number: KB000021
The article is used to introduce application developers to functionalities and features of using Fore.NET in Foresight Analytics Platform. It is also recommended to study the following:
NOTE. The development by means of the Fore.NET language, as well as the Fore language, must be performed in the test schema. Test and production repository are synchronized by means of update manager.
The first and fundamental difference of Fore.NET and Fore is that Fore.NET is enclosed in the .NET assembly object, that is Fore.NET units and Fore.NET can be created and used only within Fore.NET assemblies.
Consider a simple example. Open integrated development environment from the project navigator and create a Fore.NET assembly. Two objects are created: a Fore.NET assembly itself and a Fore.NET unit "Program" with the following code:
Imports System;
Public Class StartParams
Private m_Metabase: Prognoz.Platform.Interop.Metabase.IMetabase;
Public Property Metabase: Prognoz.Platform.Interop.Metabase.IMetabase
Get
Begin
Return m_Metabase
End Get
Set
Begin
m_Metabase := Value;
End Set
End Property Metabase;
End Class;
Public Class Program
[STAThread]
Public Shared Sub Main(Params: StartParams);
Begin
End Sub;
End Class;
This differs from the situation in Fore.
Introduce a definition:
An input point in Fore.NET is a published static method Main of the Program class of the <Identifier of the started .NET assembly> namespace.
An input point has a parameter of the StartParams type which contains a link to the current repository. This link is used instead of the MetabaseClass.Active method which is unavailable in Fore.NET as COM does not contain static method and properties. When a Fore.NET assembly is created a link to the Metabase assembly is automatically added to the list of links.
Fore.NET has several types of assemblies: EXE, DLL. EXE in its turn is divided into WindowsApplication and ConsoleApplication. The DLL type is assigned to the Fore.NET assembly by default when it is created, which enables the user to run it from the object navigator in the current process of Foresight Analytics Platform, and connect this Fore.NET assembly to other Fore.NET assemblies using links.
Unlike a simple Fore assembly, a Fore.NET assembly can be started from the object navigator (context menu option: Open), input point of the assembly is called.
Like in Fore, a Fore.NET assembly can be started for debugging from the development environment. Debugging is also performed in a separate platform process. Start up speed is the same as in Fore.
Unlike in Fore, you need to write additional code to start a newly created empty Fore.NET form.
See the following example of a created Fore.NET form:
Imports System;
Imports System.Collections.Generic;
Imports System.ComponentModel;
Imports System.Data;
Imports System.Drawing;
Imports System.Text;
Imports System.Windows.Forms;
Imports Prognoz.Platform.Forms.Net;
Namespace <Assembly_Identifier>
Public Partial Class <Form_Object_Identifier>Form: Prognoz.Platform.Forms.Net.ForeNetForm
Public Constructor <Form Object Identifier>Form();
Begin
InitializeComponent;
End Constructor;
End Class;
End Namespace;
A designer without parameters is generated for the form, where the InitializeComponent method is called. Going to the definition of this method opens another unit with the following code:
Imports System;
Imports System.Collections.Generic;
Imports System.ComponentModel;
Imports System.Data;
Imports System.Drawing;
Imports System.Text;
Imports System.Windows.Forms;
Imports Prognoz.Platform.Forms.Net;
Namespace <Assembly_Identifier>
Public Partial Class <Form_Object_Identifier>Form: Prognoz.Platform.Forms.Net.ForeNetForm
Private components: System.ComponentModel.IContainer = null;
Protected Override Sub Dispose(disposing: boolean);
Begin
If (disposing And (components <> null)) then
components.Dispose();
End If;
Inherited Dispose(disposing);
End Sub;
Private Sub InitializeComponent();
Begin
Self.components := New Container();
Self.Text := "<Form_Name>";
Self.Font := New System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((204) As Byte));
Self.ResumeLayout(False);
End Sub;
End Class;
End Namespace;
You can see that a form with all its components is actually created in the InitializeComponent method. This gives a more clear idea of the moment when the form components are created.
This unit (<Form_Name>.Designer) is the form's design: it stores the components positioned on the form, their style and settings and so on. This unit is included into the Fore.NET assembly as well as other units and forms, but its content is generated automatically by the form designer.
When creating a Fore.NET form, two classes with the same names are defined: <Form_Object_Identifier>Form. One of them is included into the designer unit, another is in the form unit. This is actually one and the same class, this possibility is provided by the keyword Partial included into the definition of form class (for further information on partial classes see. Specification of the Fore.NET language).
The Fore.NET assemblies work as follows: the assembly itself is started and not its individual units and forms. So, to start a form, you need to create it and display in the input point of the Fore.NET assembly:
Public Shared Sub Main(Params: StartParams);
Var
Forma: <Form_Object_Identifier>Form = New <Form_Object_Identifier> Form() = [<Form_Object_Identifier> Form];
Begin
Forma.Metabase := Params.Metabase;
Forma.Show(); // or Forma.ShowDialog();
End Sub;
This code creates a form object, then fills in the Metabase property for this object and displays it on the screen. Thus, the Metabase property of the ForeNetForm basic class is used within the form code instead of MetabaseClass.Active.
Single .NET assembly units may contain several implementations of entry points; the point which will be executed on .NET assembly startup is specified in assembly parameters. Some form can also be specified as a .NET assembly startup object, in this case entry points are ignored.
A .NET form can be opened modally relative to another .NET form by using the ShowDialog method. Modal forms are always shown in front of their parent forms. On working with a modal form consider the following: on closing a modal form its resources are not deleted. The form can be reopened by calling the ShowDialog method. To delete modal form resources, force call the Dispose method or use the Using operator on initializing the modal form:
Public Partial Class TESTForm: Prognoz.Platform.Forms.Net.ForeNetForm
Public Constructor TESTForm();
Begin
InitializeComponent();
End Constructor;
about: ForeNetForm;
Public Sub ShowModalForm();
Begin
about := New CustomDialogForm();
about.ShowDialog();
End Sub;
Public Sub ShowModalForm1();
Begin
Using about := New CustomDialogForm() Do
about.ShowDialog();
End Using;
End Sub;
Public Sub ShowModalForm2();
Begin
about := New CustomDialogForm();
about.ShowDialog();
about.Dispose();
End Sub;
Public Sub ReuseModalForm();
Begin
If (about <> Null) And (Not about.IsDisposed) Then
about.ShowDialog();
End If;
End Sub;
End Class;
The ShowModalForm, ShowModalForm1 and ShowModalForm2 methods open a modal window. If the window is opened by calling the ShowModalForm method, all resources remain in the computer memory after closing the window. The window can be reopened by calling the ReuseModalForm method. If the window is opened by calling the ShowModalForm1 or ShowModalForm2 methods, all resources are freed after closing the window.
The Fore.Net enables to use standard .NET components (everything included into the System.Windows.Forms namespace). The Fore.NET enables to use components used in the Fore. To find the, open the Data Access and Common Controls tabs in the Components Panel window. These components are defined in the system assembly Forms.Net. You can work as in Fore, though there are some features.
Consider the RdsDictionaryBoxNet component as an example. The following properties are defined in this component: Columns, CanElementLevelUp, CanElementDown, CanElementUp, FocusedElement, Source, UiSource, CtrlBox. All properties except UiSource and CtrlBox are used in the standard Fore component RdsDictionaryBox. The events match as well. let us consider the new properties:
UiSource. A reference to the data source: UiRdsDictionaryNet.
CtrlBox. Reference to the IRdsDictionaryBox object that is embedded into RdsDictionaryBoxNet to be displayed on the Fore.NET form. This property gives access to all properties and methods of COM interface IRdsDictionaryBox, including properties hidden for Fore. So you should use this link with care.
Errors (Exceptions) in the Fore.NET can be divided into two types:
User's errors. For example, NullReferenceException, InavalidCastException and other that are handled in a standard way and displayed as follows:
Object reference is not set to an object instance.
Error class: NullReferenceException
___________________________________
Calls stack:
in OBJ18283.Program.kuku() in OBJ18284:row 32
in OBJ18283.OBJ18762Form.test() in OBJ18761:row 23
Errors generated by methods and properties of classes and interfaces of the Foresight Analytics Platform kernel. For the present the following error message is displayed:
An error in the HRESULTE_FAIL format is returned as the result of calling a COM component
If you have received this error text you should add a Defect with an example.
Fore.NET assemblies can be used to store external .NET assemblies. For example, ready-made classes and components written in C# (or another .NET-compatible language) can be copied into a Fore.NET assembly, and then you can use this assembly through a link in other Fore.NET assemblies.
Use the IForeNetAssembly.LoadExternal(FileName: String) method to load an external assembly into the Fore.NET Assembly object of the repository:
Sub Test;
Var Asm: IForeNETAssembly; //type for net-assembly, defined in system assembly ForeNet
Begin
Asm := MetabaseClass.Active.ItemById(<Identifier_Of_Created_NET-assembly>).Edit As IForeNETAssembly;
Asm.IsExternal := True;
Asm.LoadExternal(<Path_To_External_Assembly>);
If Asm.AssemblyTarget <> 1 Then
Asm.AssemblyTarget := 1; // set assembly type dll
End If;
(Asm As IMetabaseObject).Save;
End Sub Test;
To use types defined in a Fore.NET assembly (external or standard), you need to connect the Fore.NET assembly using a reference and use the following interfaces and types:
ForeNETAssemblyClass, IForeNetAssembly, IForeNetAssemblyRuntime, IForeNetForm, IForeNetRuntimeType and so on.
For example, there is a class written in Fore.NET and saved in a .NET assembly:
Imports System;
Imports System.Windows.Forms;
Public Class Foo
Public Sub Test();
Begin
MessageBox.Show("Fore.NET method");
End Sub;
End Class;
Consider an example of calling the Test method from Fore:
Sub Button1OnClick(Sender: Object; Args: IMouseEventArgs);
Var run: IForeNETRuntime;
asm: IForeNETRuntimeAssembly;
typeFoo: IForeNETRuntimeType;
obj: IForeNETRuntimeObjectInstance;
res: Variant;
Begin
run := ForeNETAssemblyClass.Runtime; //obtain Runtime, where net code is to be executed
asm := run.Assembly(MetabaseClass.Active.ItemById("<NET-assembly_Identifier>").Bind As IForeNETAssembly); // obtain compiled NET assembly
typeFoo := asm.Type("<NET assembly_Identifier>.Foo"); //Obtain class Foo
obj := typeFoo.CreateInstance; //Create object of Foo class
res := typeFoo.InvokeMethod("Test", obj, New Variant[0]); //call method of this class
End Sub Button1OnClick;
To use the types defined in Fore units and forms in Fore.NET, connect the Fore assembly and use the following interfaces and types:
IForeClass, IForeObject, IForeAssembly, IForeSub and so on.
For example, there is a class and method written in the Fore language:
Public Class Foo: Object
Public Constructor CreateEx(X: Integer; Y: Integer);
Begin
End Constructor CreateEx;
Public Sub Test;
Begin
WinApplication.InformationBox("Fore method");
End Sub Test;
Public Sub TestWithParams(X: Integer; Y: Integer);
Begin
WinApplication.InformationBox("Fore method with parameters");
End Sub TestWithParams;
End Class Foo;
Consider an example of calling two methods via Fore.NET:
Imports System;
Imports Prognoz.Platform.Interop.Metabase;
Imports Prognoz.Platform.Interop.Fore;
Public Class Program
//Calling Test procedure
Private Shared Sub InvokeMethod(mb: IMetabase);
Var
svc: IForeServices;
rnt: IForeRuntime;
assm: IForeAssembly;
ifs: IForeSub;
ifc: IForeClass;
ifo: IForeObject;
result: object;
Begin
svc := Mb As IForeServices; //Obtain object for work with Fore
rnt := svc.GetRuntime(); //Obtain Runtime, in which Fore methods will be executed
rnt.LoadAssembly("<Fore_Unit_Identifier>"); //Load Fore unit
assm := rnt.BindToAssembly("<Fore_unit_identifier>"); //Obtain compiled assembly
ifc := assm.BindToClass("Foo "); //Obtain Fore class
ifo := ifc.CreateObject(); //Create object class Foo
ifs := ifc.BindToMethod("Test"); //Get method of this class
ifs.Self := ifo; //set object
ifs.Invoke(); //Call method Fore
End Sub;
//Calling TestWithParams function with passing values of two parameters
Private Shared Sub InvokeMethodWithParams(MB: IMetabase; x: integer; y: integer);
Var
svc: IForeServices;
rnt: IForeRuntime;
assm: IForeAssembly;
ifconst, ifs: IForeSub;
ifc: IForeClass;
ifo: IForeObject;
result: object;
Begin
svc := Mb As IForeServices; //Obtain object for work with Fore
rnt := svc.GetRuntime(); //Obtain Runtime, in which Fore methods will be executed
rnt.LoadAssembly("<Fore_Unit_Identifier>"); //Load Fore unit
assm := rnt.BindToAssembly("<Fore_unit_identifier>"); //Obtain compiled assembly
ifc := assm.BindToClass("Foo "); //Obtain Fore class
ifo := ifc.CreateObject(); //Create object class Foo
//Designer
ifconst := ifc.BindToMethod("CreateEx");
ifconst.Self := ifo;
ifsconst.Params.Item(0).Value := -1; //Specify the first parameter
ifsconst.Params.Item(1).Value := -1; //Specify the second parameter
ifconst.Invoke();
//Method
ifs := ifc.BindToMethod("TestWithParams"); //Obtain method of this class
ifs.Params.Item(0).Value := x; //Specify the first parameter
ifs.Params.Item(1).Value := y; //Specify the second parameter
ifs.Self := ifo; //Specify object
ifs.Invoke(); //Call method Fore
result := ifs.ResultValue; //Obtain execution result
End Sub;
[STAThread]
Public Shared Sub Main(Params: StartParams);
Begin
InvokeMethod(Params.Metabase);
InvokeMethodWithParams(Params.Metabase, 1, 100);
End Sub;
End Class;
There is no direct access (early binding) between Fore and Fore.NET. Thus, you cannot connect Fore and Fore.NET assemblies to each other using a reference and use types defined in these assemblies on the compilation stage.
See also:
Developers Knowledge Base | Integrated Development Environment | Components of .NET Form Designer | Early and Late Bindong