First steps - WinForms

The following executions show all steps necessary to create a basis for the actual add-in development. The complete Microsoft Visual Studio project can be obtained here: AddInSampleFirstSteps-WinForms.

Prerequisites

Creating a project

Start Microsoft Visual Studio and create a new Windows Forms project. Additionally select .NET Framework 4.6.1.

First steps - WinForms 1:

Now open the project properties and change the Output type setting in the Application section to Class Library. Check that Target framework has been set to .NET Framework 4.6.1.

Switch to the Build section and enter the path to the AddIn folder of the TwinCAT BA Project Builder under Output path (standard is TwinCAT -> BA Project Builder -> AddIns). Select the value x86 under Platform target.

Since this project concerns a class library, you must first define an external program with which the AddIn is to be started to start and debug. In the Debug section, enter the path to the TwinCAT BA Project Builder next to Start external program (standard is TwinCAT -> BA Project Builder -> TwinCAT.BA.ProjectBuilder.UI.exe).

Remove the Program.cs file, which is created as standard, from the project.

Adding references

The next step covers the adding of three references.

Adding an icon

If desired, add an icon (16 x 16 pixels) to the project and set the Build Action property to Resource.
First steps - WinForms 3:

Placing at disposal

Two classes need to be added so that the AddIn can be displayed and loaded in the TwinCAT BA Project Builder. Firstly, a class that is derived from ContractAttribute and overwrites several properties. These display the AddIn in the TwinCAT BA Project Builder. Secondly, a class must be created containing the IContractWinForms interface. The AddIn is loaded via the TwinCAT BA Project Builder using the GetForm method.

Create a new class with the name AddInEntryMetadata and derive it from ContractAttribute. Add the properties Description, ShortDescription, Name, Version and Icon. This information is displayed in the TwinCAT BA Project Builder when selecting the AddIn.

using TwinCAT.BA.ProjectBuilder.AddIn.Contract;

namespace AddInSampleFirstSteps
{
    public class AddInEntryMetadata : ContractAttribute
    {
    // Gets the description of the AddIn.
    public override string Description
    {
        get
        {
        return "AddIn Sample FirstSteps of the TwinCAT BA Project Builder for WinForms";
        }
    }

    // Gets the short description of the AddIn.
    public override string ShortDescription
    {
        get
        {
        return "AddIn Sample FirstSteps for WinForms";
        }
    }

    // Gets the name of the AddIn.
    public override string Name
    {
        get
        {
        return "Sample FirstSteps WinForms";
        }
    }

    // Gets the version of the AddIn.
    public override string Version
    {
        get
        {
        return "1.0.0";
        }
    }
    
    // Gets or sets the contract metadata icon path.
    // "pack://application:,,,/<- Assembly name ->/;component/<- Subfolder or image/icon file name"
    public override string Icon
    {
        get
        {
        return "pack://application:,,,/AddInSampleFirstSteps;component/AddIn.png";
        }
    }    
    }
}

Now create the AddInEntryPoint class and implement the IContractWinForms interface. In addition, the class must be decorated with the attributes Export and AddInEntryMetadata.

The interface contains the GetForm() method. This is called by the BA Project Builder when the AddIn is to be displayed. Furthermore, two events must be implemented which are necessary for accessing the Output window of the BA Project Builder.

using System;
using System.ComponentModel.Composition;
using System.Windows.Forms;
using TwinCAT.BA.ProjectBuilder.AddIn.Contract;

namespace AddInSampleFirstSteps
{
    [Export(typeof(IContractWinForms))] // Marks this class as an entry point for the TwinCAT BA Project Builder    
    [AddInEntryMetadata] // Adds necessary information about the AddIn to this class
    public class AddInEntryPoint : IContractWinForms
    {
    private AddInEntryMetadata addInEntryMetadata = null;
    public event EventHandler<ContractLogEventArgs> LogEvent;
    public event EventHandler<ContractClearLogEventArgs> ClearLogEvent;      
    
    public Form GetForm()
    {
        this.addInEntryMetadata = new AddInEntryMetadata();
        // Passing the main class of the AddIn
        return new Form1(this);
    }

    public void RaiseLogEvent(LogLevel level, string message)
    {
        OnLog(new ContractLogEventArgs(this.addInEntryMetadata, level, message));
    }

    // The event-invoking method that derived classes can override. 
    private void OnLog(ContractLogEventArgs e)
    {
        // Make a temporary copy of the event to avoid possibility of 
        // a race condition if the last subscriber unsubscribes 
        // immediately after the null check and before the event is raised.
        EventHandler<ContractLogEventArgs> handler = this.LogEvent;
        if (handler != null)
        {
        handler(this, e);
        }
    }

    public void RaiseClearLogEvent()
    {
        OnClearLog(new ContractClearLogEventArgs(this.addInEntryMetadata));
    }

    // The event-invoking method that derived classes can override. 
    private void OnClearLog(ContractClearLogEventArgs e)
    {
        // Make a temporary copy of the event to avoid possibility of 
        // a race condition if the last subscriber unsubscribes 
        // immediately after the null check and before the event is raised.
        EventHandler<ContractClearLogEventArgs> handler = this.ClearLogEvent;
        if (handler != null)
        {
        handler(this, e);
        }
    }
    }
}

Programming

The main functionalities are implemented in the Form1 class.

using System.Windows.Forms;
using TwinCAT.BA.ProjectBuilder.AddIn.IL;

namespace AddInSampleFirstSteps
{
    public partial class Form1 : Form
    {
    AddInEntryPoint addInEntryPoint = null;
    BAProjectBuilder projectBuilder = null;

    public Form1(AddInEntryPoint addInEntryPoint)
    {
        InitializeComponent();
        // Code here
        this.addInEntryPoint = addInEntryPoint;
        this.projectBuilder = new BAProjectBuilder();
    }
    }
}

Debugging

The TwinCAT BA Project Builder is started automatically with the project. You can execute the AddIn both via the Tools menu of the TwinCAT BA Project Builder ...
First steps - WinForms 4:

... and via the toolbar.
First steps - WinForms 5:

In both cases the TwinCAT BA Project Builder creates an instance of the AddIn and calls the GetForm method.

An instance of the AddInEntryMetadata class is already created when starting the BA Project Builder and all information necessary for the representation in the TwinCAT BA Project Builder is read out via the Properties.