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.
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.
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:
- In the Solution Explorer, right-click the MessagePlugin module project, select Add, and then select Class.
- Change the Name to MessagePluginWorkItem.cs.
- 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:
- In the Solution Explorer, right-click the MessagePlugin module project, select Add, and then select Class.
- Change the Name to MessagePluginModuleInit.cs.
- 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!
- In the Solution Explorer, right-click the CABPluginApplication project, select Add, and then select New Item.
- From the Templates dialog box, select XML File.
- Change the Name to ProfileCatalog.xml.
- 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:
Figure. The final solution.
And, I leave you with some screenshots:
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