CAB Quickie – The Plug-in Application: The Message Plug-in (Part 4)

 

In this part, you will finish the quickie by adding a CAB module to the project: the Message plug-in. It is called like that as it will only display a message entered by the user. The input will be performed on a view (a SmartPart), which will be a UserControl, so, you will add a Windows Control Library.

1. In Visual Studio, point to Add on the File menu, and then click New Project.

templateMessageProject

Figure. Creating the MessagePlugin module project.

2. In the New Project dialog box, expand the Visual C# node. Click the Windows project type.

3. In the Templates window, select Windows Control Library.

4. Change the Name to MessagePlugin.

5. Change the location for the solution to the source folder located inside the PluginQuickie folder.

6. Click OK.

SEMessagePlugin

Figure. The MessagePlugin module project added to the solution.

As you have already done, you will change the output path of the MessagePlugin project to bin\Debug folder. To accomplish this, right-click the MessagePlugin project (in the Solution Explorer) and select Properties. In the Build tab, go to the Output section and edit the Output path to %PluginQuickieFolder%\bin\Debug.

Moreover, add only the CAB assemblies located in the Lib folder in the same way you did at the CAB Quickie – The Plug-in Application: The CAB Plug-in System Application post.

Once you have done this, you will start setting up the view:

1. In the Solution Explorer, right-click the UserControl1.cs file, select Rename, and change the name to MessageView.cs.

2. Set its Size property to 210, 80.

3. Add a Label to the MessageView with the following values set to the corresponding properties:

 

Property Value
(Name) titleLabel
AutoSize False
BackColor LightBlueSky
Dock Top
Font Arial, 9,75pt, style=Bold
ForeColor White
Location 210, 19
Text Write a message:

4. Add a TextBox to the MessageView with the following values set to the corresponding properties:

 

Property Value
(Name) messageTextBox
Location 3, 23
Size 202, 20

5. Add a Button to the MessageView with the following values set to the corresponding properties:

 

Property Value
(Name) displayButton
Location 70, 49
Size 75, 23
Text Display

6. Double-click the displayButton to generate the code for the handler for its click and add the following code line inside:

MessageBox.Show(messageTextBox.Text, “Showing message:”);

Done with the View! :)

By now you may be wondering: “Wait a minute! No presenter or controller for this view?” Well, the MVC and the MVP patterns are intended for complex UI logic and to separate it from a complex model. None of these points are present, so none of the patterns (MVC and MVP) are present. :)

Let’s keep going! The MessagePlugin module needs two things to get set up: a WorkItem, to get a container for the module, and a ModuleInit class, to get the module initialized and added to the CAB application.

Firstly, let’s start by adding the WorkItem class:

  1. In the Solution Explorer, right-click the MessagePlugin module project, select Add, and then select Class.
  2. Change the Name to MessagePluginWorkItem.cs.
  3. Click OK.

This class will be used as a container only for the whole MessagePlugin module. It will add a menu item to the Plugins menu item located at the main menu strip of the MainForm, which, on click, will display the MessageView in a WindowWorkspace (that will be added in the ModuleInit class later on). So, now, you’ll configure for that purpose:

1. Add the following using statements:

using System.Drawing;

using System.Windows.Forms;

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.WinForms;

2. Replace the signature of the class with this one:

public class MessagePluginWorkItem : WorkItem

3. Add the following code to the class, which overrides the OnRunStarted() method (that is called when the WorkItem gets initializated):

protected override void OnRunStarted()

{

    base.OnRunStarted();

    ToolStripMenuItem item = new ToolStripMenuItem(“Message Window”);

    item.Click += new EventHandler(item_Click);

    RootWorkItem.UIExtensionSites["PluginsMenuBar"].Add<ToolStripMenuItem>(item);

}

void item_Click(object sender, EventArgs e)

{

    MessageView view = SmartParts.AddNew<MessageView>();

    WindowSmartPartInfo wspi = new WindowSmartPartInfo();

    wspi.MaximizeBox = false;

    wspi.Title = “Message Plugin!”;

    wspi.Location = new Point(((Screen.PrimaryScreen.WorkingArea.Width - view.Width) / 2), ((Screen.PrimaryScreen.WorkingArea.Height - view.Height) / 2));

    Workspaces["WinWork"].Show(view, wspi);

}

NOTE: As you can see from this code, you’re adding a new ToolStripMenuItem to the PluginsMenuBar UIExtensionSite (that is the menu located in the main menu strip of the form with the text “Plugins”), plus a handler for its click event which creates and adds a new MessageView to the WorkItem and displays it in the “WinWork” WindowWorkspace with a SmartPartInfo (that locates it at centre screen).

Now, let’s add the ModuleInit class:

  1. In the Solution Explorer, right-click the MessagePlugin module project, select Add, and then select Class.
  2. Change the Name to MessagePluginModuleInit.cs.
  3. Click OK.

Now you will configure the class to get the module plugged in to the CAB application:

1. Add the following using statement:

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.WinForms;

2. Replace the signature of the class with this one:

public class MessagePluginModuleInit : ModuleInit

3. Add the following code to get the RootWorkItem injected to the class:

private WorkItem _rootWorkItem;

[ServiceDependency]

public WorkItem RootWorkItem

{

    get { return _rootWorkItem; }

    set { _rootWorkItem = value; }

}

NOTE: When CAB gets this class (the ModuleInit class), it searches for dependencies and inject them. The WorkItem that gets injected in this code is, indeed, the RootWorkItem, as it is where the ModuleInit class gets created and added.

4. Add the following code to the class, which overrides the Load() method (that is called in order to load the module):

public override void Load()

{

    base.Load();

   MessagePluginWorkItem workItem = RootWorkItem.WorkItems.AddNew<MessagePluginWorkItem>();

   workItem.Workspaces.AddNew<WindowWorkspace>(“WinWork”);

    workItem.Run();

}

NOTE: This code adds a new instance of the MessagePluginWorkItem to the RootWorkItem and a WindowWorkspace to the MessagePluginWorkItem with the id “WinWork”.

There’s only one thing left to do! How does the CAB Application know that it has to load the MessagePlugin? Simple: by looking at the ProfileCatalog.xml! But the CAB Application does not have one, so let’s add it!

  1. In the Solution Explorer, right-click the CABPluginApplication project, select Add, and then select New Item.
  2. From the Templates dialog box, select XML File.
  3. Change the Name to ProfileCatalog.xml.
  4. Click OK.

Once it’s added, set its Copy to Output Directory property to Copy always (this is very important, otherwise CAB won’t find it and will not load the plug-ins!), and then add this code to the file, which represents the collection of modules the application must initialize:

<SolutionProfile xmlns=http://schemas.microsoft.com/pag/cab-profile>

    <Modules>

    <ModuleInfo AssemblyFile=MessagePlugin.dll/>

    </Modules>

</SolutionProfile>

Having done all these steps, just save, compile and run the project. You will see that the “Hello World!” application has a new menu item under the “Plugins” menu item saying “Message Window”. When you click on it the view is displayed as a new window, thanks to the WindowWorkspace.

The final solution will look like this:

SEFinalSolution

Figure. The final solution.

And, I leave you with some screenshots:

mainApplicationFinal

mainApplicationFinal2

mainApplicationFinal3

 

Conclusion

This Quickie dealt with one possible way to use the ApplicationContextApplication class provided by CAB. There are much more usages than this, for example, displaying more than one form, or a console application. Moreover, the ApplicationContext class that you add to the ApplicationContextApplication class can have dependencies injected, as it is created by CAB, so you may perform several checks before showing a form or start your program.

I hope that this short example (that’s why it’s called a quickie ;)) may help you have an overview on this class and its usage.

As always: any feedback is welcome! :)

Cheers,

Nacho

CAB Quickie – The Plug-in Application: The CAB Plug-in System Application (Part 3)

 

In this part, you will add the CAB plug-in application. It will be a Windows Application for two reasons:

  1. You will create a class that inherits from the ApplicationContext class, so you need the System.Windows.Forms assembly.
  2. The CAB plug-in application will become the start up project.

Let’s start by adding the new project.

1. In Visual Studio, point to Add on the File menu, and then click New Project.

templateCABProject

Figure. Creating the CABPluginApplication project.

2. In the New Project dialog box, expand the Visual C# node. Click the Windows project type.

3. In the Templates window, select Windows Application.

4. Change the Name to CABPluginApplication.

5. Change the location for the solution to the source folder located inside the PluginQuickie folder.

6. Click OK.

SECABPluginApplication

Figure. The CABPluginApplication project added to the solution.

Now, you need to change the output path of the CABPluginApplication project to bin\Debug folder, in the same way as you did in the CAB Quickie – The Plug-in Application: The Main Application post. To accomplish this, right-click the CABPluginApplication project (in the Solution Explorer) and select Properties. In the Build tab, go to the Output section and edit the Output path to %PluginQuickieFolder%\bin\Debug.

As I wrote in the first post, the CABPluginApplication will not contain a form to display; instead, it will use the MainForm of the MainApplication in an ApplicationContext class. So, you don’t need the Form1.cs file, so just delete it. To do this, right-click the Form1.cs file, in the Solution Explorer, and select Delete.

 

It’s time to get CAB started! Time to add the references!

1. In the Solution Explorer, right-click the References folder and select Add Reference.

2. In the dialog box, go to the Browse tab, browse to the %PluginQuickieFolder%\Lib folder, and select the assemblies you’ve previously copied there:

  • Microsoft.Practices.CompositeUI
  • Microsoft.Practices.CompositeUI.WinForms
  • Microsoft.Practices.ObjectBuilder

Finally, as the CAB application will use the MainForm class of the “Hello World!“ application, you need to add a reference to this project, so in the Projects tab, select the MainApplication project.

After you have done this, the solution should look like this:

SECABReferencesAdded

Figure. CAB and MainApplication references added to the CABPluginApplication project.

The ApplicationContextApplication<TWorkItem, TShell> class calls the Application.Run(ApplicationContext context) method in its overridden Start() method. This is because TShell is type of ApplicationContext. So, you need to add a class that inherits from the ApplicationContext class.

Let’s do that!

  1. In the Solution Explorer, right-click the CABPluginApplication project, select Add, and then select Class.
  2. Change the Name to PluginContext.cs.
  3. Click OK.

This class will inherit from the ApplicationContext class and will use the MainForm class of the “Hello World!” application, so you need to add the following using statements:

using System.Windows.Forms;

using MainApplication;

Then, make it inherit from ApplicationContext by replacing the signature of the class with this one:

public class PluginContext : ApplicationContext

Finally, you will add the necessary code to set its MainForm property with a new instance of the MainApplication class of the “Hello World!” application in its constructor, as follows:

public PluginContext()

{

       this.MainForm = new MainForm();

}

Alright! Almost done! :)

Ok, now that you have set all the necessary things, it’s time to finish configuring the CAB project to make it the new start-up project:

1. In the Solution Explorer, right-click the Program.cs file, select Rename, and change the name to PluginApplication.

2. Right-click the Program.cs file again, and select View Code.

3. Add the following using statements:

using Microsoft.Practices.CompositeUI;

using Microsoft.Practices.CompositeUI.WinForms;

using Microsoft.Practices.CompositeUI.WinForms.UIElements;

4. Replace the signature of the class with this one:

public class PluginApplication : ApplicationContextApplication<WorkItem, PluginContext>

NOTE: Here, you set a WorkItem type to act as the RootWorkItem and a PluginContext type to act as the ApplicationContext of the CABApplication class.

5. Replace the body of the Main() method with the following code:

new PluginApplication().Run();

NOTE: This line will create a new instance of the PluginApplication class and call the CABApplication.Run() method.

6. Override the AfterShellCreated() method, and place the following code:

protected override void AfterShellCreated()

{

    base.AfterShellCreated();

    ToolStripMenuItem item = new ToolStripMenuItem(“Plugins”);

    this.Shell.MainForm.MainMenuStrip.Items.Add(item);

    ToolStripItemCollectionUIAdapter adapter = new ToolStripItemCollectionUIAdapter(item.DropDownItems);

    RootWorkItem.UIExtensionSites.RegisterSite(“PluginsMenuBar”, adapter);

}

NOTE: This code will add a new menu item in the main menu strip of the application, with the “Plugins” text, and then add a UIElementAdapter for the DropDownItems colletion of the Plugins menu item, which will be available throughout the whole application.

Finally, right-click the CABPluginApplication project and select Set as StartUp Project.

Once you have done all these steps, just save, compile and run the project. You will see the same “Hello World!” application plus the “Plugins” menu item and, now, in an application context running on CAB! :)

mainApplicationOnCAB

Figure. Outcome: The MainApplication running on CAB.

Next Steps

In the next part, you will create the Message plug-in and get it to work with the CAB plug-in system in a loosely coupled way.

CAB Quickie – The Plug-in Application: The Main Application (Part 2)

 

In this part, you will add the “main application”. It will be a “Hello World!” application that will act as the program you are about to extend using a plug-in system based on CAB.

First of all, you will create a new Windows Application project.

1. Return to the PluginQuickie blank solution and, in Visual Studio, point to Add on the File menu, and then click New Project.

templateProject

Figure. Creating the MainApplication project.

2. In the New Project dialog box, expand the Visual C# node. Click the Windows project type.

3. In the Templates window, select Windows Application.

4. Change the Name to MainApplication.

5. Change the location for the solution to the source folder located inside the PluginQuickie folder.

6. Click OK.

SEMainApplication

Figure. The MainApplication project.

As I wrote in the CAB Quickie – The Plug-in Application: Setting up the development environment post, the bin\Debug folder was created to contain all the built projects, so you need to change the output path of the MainApplication project to this folder. To accomplish this, right-click the MainApplication project (in the Solution Explorer) and select Properties. In the Build tab, go to the Output section and edit the Output path to %PluginQuickieFolder%\bin\Debug.

projectProperties

Figure. Output path in the Output section located at Build tab in the Project properties. Note: you might not see a relative path until you close the properties window and open it again.

After doing this, you’ll start setting up the MainForm:

1. In the Solution Explorer, right-click the Form1.cs file, select Rename, and change the name to MainForm.cs.

2. In the Designer, right-click the MainForm and select Properties.

3. Set the following values to the corresponding properties:

 

Property Value
Size 300, 300
StartPosition CenterScreen
Text MainForm

4. Add a Label to the MainForm with the following values set to the corresponding properties:

 

Property Value
(Name) HelloWorldLabel
Font Arial, 20,25pt, style=Bold
Location 61, 115
Text Hello World!

5. Add a MenuStrip to the MainForm and name it HelloWorldMenuStrip.

6. Add a ToolStripMenuItem in the HelloWorldMenuStrip by typing “&File” in the “Type Here” box, and another one inside the fileToolStripMenuItem (this name is given when the item is added) by typing “&Exit” (which will be named exitToolStripMenuItem).

7. Double-click the exitToolStripMenuItem to generate the code for the handler for the click event of the menu item and add the following code line inside:

Application.Exit();

NOTE: This will close the application when clicking on the exitToolStripMenuItem.

8. Once you have done this, in the Designer, right-click the MainForm, select Properties, and set the MainMenuStrip property to the HelloWorldMenuStrip menu strip.

When all these steps are done, just save, compile and run the project. You will see an ordinary Hello World application. So far, we haven’t seen anything about CAB yet.

mainApplication

Figure. Outcome: The MainApplication.

Next Steps

In the next part, you will add the CAB plug-in application (that will be another Windows Application with references to the CAB assemblies).

CAB Quickie – The Plug-in Application: Setting up the development environment (Part 1)

 

In this part, you will set up the development environment. By this, I mean a blank solution to host all the projects and a folder structure for a cleaner view. I would like to remark that these steps are not a “must have“ (they just provide a neater development environment), but they are a good practice.

First of all, you will create a blank solution to host both the non-CAB application and the CAB plug-in application.

1. Open the Visual Studio, point to New on the File menu, and then click Project.

templateSolution

Figure. Setting up the blank solution.

2. In the New Project dialog box, expand the Other Project Types node. Click the Visual Studio Solutions project type.

3. In the Templates window, select Blank Solution.

4. Change the Name to PluginQuickie.

5. Select the location for the solution (e.g.: your Visual Studio Projects folder).

6. Click OK.

SEBlankSolution

Figure. The initial blank solution.

Now, you will create the folder structure for this solution:

  1. Open the PluginQuickie folder and add three new folders: bin, Lib, and source.
  2. Inside the bin folder add a new folder and name it Debug.

The folder structure should look like this:

folderStructure

Figure. The initial folder structure.

The Lib folder will contain the necessary CAB assemblies, the bin\Debug folder will contain all the built projects, and the source folder will contain the source code.

Finally, to finish setting up the environment, you will add the following CAB assemblies to the Lib folder (just copy the assemblies from the CAB folder to the Lib folder):

  • Microsoft.Practices.CompositeUI
  • Microsoft.Practices.CompositeUI.WinForms
  • Microsoft.Practices.ObjectBuilder

Ok, you are done! You have set your development environment! :)

 

Next Steps

In the next part, you will add a Hello World application (that will only be an ordinary Windows Application) which will play the role of the application we are about to extend using the CAB-fashioned plug-in system.

CAB Quickie – The Plug-in Application (Overview)

This purpose of this Quickie is to show one of the possible uses of the ApplicationContextApplication<TWorkItem, TShell> class. Here, the CAB Shell application does not contain a main form (it belongs to a non-CAB application); instead, it starts with an ApplicationContext class.

Some time ago, some people asked at Codeplex forums, if they could use CAB in a non-Windows Form application (by this, they meant an application with no main form, such as a Console application). I’ll start by saying: yes, you can! :)

To get things started, I’ll give you an extract of the documentation that I found when searching for information on this:

ApplicationContextApplication

This class is used in Windows Forms applications that do not show a main window as part of the start-up process, applications that require fine-grained control over threading, or applications that have complex requirements for creation of the UI before the application starts. The ApplicationContext type provides control of both the application main form (if you are using one) and the application main thread lifetime.

The following are examples:

· Applications that need to load as plug-ins into other systems. For example, if you want to use the Composite UI Application Block to create an Office Add-In, where an Office Form will provide the main interaction window, you would use the ApplicationContextApplication class.

· Applications that need to start up without a visual window, show a “splash screen” window, or run as an icon in the Windows toolbar notification area.”

That’s quite what they were looking for! But the problem of this extract is that… that’s it! :( I mean, there’s no more information on how to use it nor an example or QuickStart for a quick glimpse on it!

So, that’s why I’ve decided to write this HOL-style post, to help you have a look at how to build a CAB application using the ApplicationContextApplication<TWorkItem, TShell> class from scratch!

The Scenario

You are asked to code an ordinary “Hello World!” windows application. You deliver it, but then you are asked to mount a plug-in system on it to make it extensible, in order to add plug-ins. For example, you are asked to create a “Message plug-in” that shows a dialog that let’s the user write a custom message and the display it on a button click.

You think about CAB, but you also think that it’s too late to modify the whole main application to get CAB work with it, so you think of adding a new project, a CAB project, and make the main application work with CAB.

This CAB application will be in charge of displaying the main form (hosted on the “Hello World!” application) and also of loading the plug-ins.

Throughout this article, you will:

  1. Set up the development environment: you will create a blank solution and a folder structure for a clean view.
  2. Create the “Hello World!” application: you will add a Windows Application to the blank solution and set it up to be the Main application.
  3. Create the CAB Plug-in system application: you will add another Windows Application to the solution and set it up to work with CAB and the “Hello World!” application. When this is done, it will become the new start-up project.
  4. Create the “Message” plug-in: you will add a Windows Class Library to the solution.

Download the final solution here: Plugin Quickie.

« Previous PageNext Page »