Summary
This article explains how to include MS Agent into an simple Windows Form based application using C#. The code is compiled using Visual Studio .Net and the released Microsoft (R) Visual C# Compiler Version 7.00.9466 [CLR version v1.0.3705] and tested on Windows 2000 Server SP2.
Prerequisites
In order to run this example, you will need MS Agent agent installed. Note that if you are using Windows 2000, this is installed by default. Other operating systems will need it specifically installing.
MainWindow.cs
The simple Windows Form contains nothing revolutionary, it is a simple window with a help menu. The menu contains only one option - "Agent Help". The helpMenuItem_Click method triggers what we are really interested in!
private void helpMenuItem_Click(object sender, System.EventArgs e)
{
new AgentActivator();
}
AgentActivator.cs
This Class is essentially the work horse of the program. Note the "using" statements we require for the MS Agent to function!
using System.Runtime.InteropServices;
using System.Threading;
using AgentServerObjects;
using AgentObjects;
The no parameter constructor calls the StartAgent() method with is responsible for creating the MS Agent. So lets walk through it.......
Firstly, we need an object that will be used to hold our actual Agent character!
IAgentCharacterEx CharacterEx=null;
Now its time to create 3 ints to hold the Character ID, Request ID and Sink ID, and an instance of the AgentServer, and return if this could not be completed for whatever reason, otherwise continuing.
int dwCharID=0, dwReqID=0, sinkID=0;
AgentServer Server = new AgentServer();
if (Server == null)
{
Console.WriteLine("STOP: The Agent Server could not start");
return;
}
Console.WriteLine("Agent Server created!");
Once we have the server object, we cast it to a IAgentEx interface that allows our application to load characters, receive events and determine the state of the Agent Server. You would never do this in a real application, but I have hard coded the specific Agent character I want to use.... in this case Peedy. However, feel free to change it to any of the others and give them a try!
genie.acs, robby.acs, peedy.acs, merlin.acs are the four characters that are supplied by default. Toolkits, however, are available to create your own!
Once we have specified the character, we call the Load method on the Server Interface to load the character passing in the ints for the character and request ids that the COM object expects; and catching any exceptions that are thrown - eg: using an invalid character name!
IAgentEx SrvEx;
SrvEx = (IAgentEx) Server;
try
{
String CharacterFile = "peedy.acs";
SrvEx.Load(CharacterFile, out dwCharID, out dwReqID);
}
catch (Exception ex)
{
Console.WriteLine("Failed to load Agent character! Exception details:");
Console.WriteLine(ex);
}
Now that we have loaded a character, its time register an event handler (more on that later) and show him, her or it to the world!! This is done simply by calling the GetCharacterEx method on the server passing in the dwCharID and our previously defined CharacterEx holder object. Now we can simply call the show method on our CharacterEx object!
SrvEx.GetCharacterEx(dwCharID, out CharacterEx);
//Set event handler
Sink = new AgentEventHandler();
SrvEx.Register(Sink, out sinkID);
// Show the character.
//The first parameter determines whether or not the character is
//displayed by showing an animation.
CharacterEx.Show(0, out dwReqID);
This makes the charater appear on the screen... so now lets make it do something more useful! The Speak method will make he speak (obviously) and the Play method will animate it in. In this case, it plays the "Greet" animation. For a complete list of animations, please refer to the MS Agent SDK documention.
// Make the character speak
CharacterEx.Speak("Hello C-sharp world!", null, out dwReqID);
CharacterEx.Play("Greet",out dwReqID);
Position = new Point(100,300);
Thread.Sleep(5000);
I included a "Position" Point object to make moving the Agent Character around the screen a little easier! Simply pass in the new co-ordinates, and off it goes!!
//This object is can be used to move the character around the screen
public Point Position
{
get
{
int x, y;
CharacterEx.GetPosition(out x, out y);
return new Point(x, y);
}
set
{
int nReqID;
CharacterEx.MoveTo((short)value.X, (short)value.Y, 1000, out nReqID);
}
}
It is also possible to directly modify the Character's speech bubble too! This requires getting the IAgentBallonEx object for the Character and then calling the setter methods for the appropriate property such as Font, Style etc.
//This object is can be used to set the font, style etc of the speech bubble
public IAgentBalloonEx Balloon
{
get
{
return (IAgentBalloonEx) CharacterEx;
}
}
And that is essentially it! However, the Agent is not much use if it cannot respond to events. So as promised, here is how to make an event handler!
AgentEventHandler.cs
The main events handled by an Agent Character are via its IAgentNotifySink interface. We must first create a class that implements this interface, and define the all the methods, and then expand the events we are interested in catching.
using System;
using AgentServerObjects;
namespace AgentWindow
{
/// <summary>
/// Handles Events for the Agent
/// </summary>
public class AgentEventHandler : IAgentNotifySink
{
.......
There are many methods in this interface, but by way of illustration, I expanded on the Click method that listens to see when a users performs a single mouse click on the Agent Character. In response to the event, I decided to simply show a message box.
public void Click(int dwCharID, short fwKeys, int x, int y)
{
System.Windows.Forms.MessageBox.Show("You clicked on the agent", "Event");
}
The last, but not least part of the exercise is to register the EventHandler. This is done in the AgentActivator class. Firstly by creating a new instance of the AgentEventHandler and then by calling the Register method on the server interface passing in the sinkID we defined earlier on.
//Set event handler
Sink = new AgentEventHandler();
SrvEx.Register(Sink, out sinkID);
And that is all there is to it! Of course, this example is not a very useful implementation of the Agent, but illustrates how to form the basic requirements needed to include them in your applications!