Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

VS.NET MSN Messenger Add-In

0.00/5 (No votes)
29 Jul 2002 1  
An add-in for VS.NET to enable MSN Messenger in a tool window

Sample Image

Introduction

I have long been a fan of code project and finally I have something to share. Browsing the Microsoft site I came across the documentation for MSN Messenger so minutes later I had fired up Visual Studio and started to investigate the possibility's. Having looked at what is available I decided to make this add-in for VS.NET

Referencing Messenger

I am not much a person for writing so I will let the code do the talking. The first thing you need to do is reference the Messenger ActiveX normally this can be done just by adding a reference to the COM object but in this case because of a bug it does not work. You actually need to rebuild the assembly created from TLBImp after changing a couple of methods. This in one of the things that makes the project more interesting.

  1. Use Tlbimp.exe to generate a Messenger interop assembly (this is located in C:\Program Files\Messenger by default):
    tlbimp msmgs.exe /out:Messenger.dll
  2. Disassemble the interop assembly, and then save it as an IL file:
    ildasm /text Messenger.dll /out:Messenger.il
  3. Open the IL file in any text editor, and then change the following line (mark the class as public instead of private):
    .class private auto ansi sealed DMsgrObjectEvents_SinkHelper
    to
    .class public auto ansi sealed DMsgrObjectEvents_SinkHelper
    and just below that
    .class private auto ansi sealed DMsgrObjectEvents_EventProvider
    to
    .class public auto ansi sealed DMsgrObjectEvents_EventProvider
  4. Compile the IL file:
    ilasm /dll Messenger.il
  5. This DLL is now ready to be referenced later in our project.

Creating an Addin

Visual Studio has always been great for generating code from a wizard one less thing for me to do. If you just choose New Project\Other Projects\Extensibility Projects\Visual Studio .NET add-in and run through the wizard. I will assume everyone here is sensible enough to configure these but here is a brief description:

  1. Create an add-in using C# (default)
  2. This relates to the environments you want to use the add-in up to you really but I chose both
  3. Give your add-in a nice name
  4. Options
    • Add a button to the tools menu at present this will not do anything except load the add-in
    • The next two options relate to when you want the add-in to load
    • Do you want all users to use the add-in
  5. Help about options (maybe I should have put something here)
  6. On the summary page just click finish

Creating a Tool Window

Now we have our add-in how do we get it to be a tool window? This is an area I think could be improved both in the IDE and MSDN as it took a fair amount of searching to find out what i needed to do. In the end a Tool Window Sample was located. The sample is from Microsoft and shows how to create a Tool Window in .NET. If you just build the VSUserControlHost ActiveX control and I will try and explain what you need to do in the add-in we have.

  1. Add a reference to the ActiveX control created by building VSUserControlHost
  2. Locate the Connect.cs file in the Messenger add-in and add the following code to the end of the OnConnection method
    object objTemp = null;
    string guidstr = "{716238D9-8ED3-48aa-A7A0-A73CA6FDF1EF}";
    
    EnvDTE.Window windowToolWindow = 
        applicationObject.Windows.CreateToolWindow (
        addInInstance,
        "VSUserControlHost.VSUserControlHostCtl",
        "Messenger", guidstr, ref objTemp);
        
    windowToolWindow.Visible = true;
    
    VSUserControlHostLib.IVSUserControlHostCtl objControl =
        (VSUserControlHostLib.IVSUserControlHostCtl)objTemp;
        
    objControl.HostUserControl(
        System.Reflection.Assembly.GetExecutingAssembly().Location,
        "MsgAddin.HostUserControl");
    The guidstr in the above code was generated using guidgen.exe and I would advise for your future add-ins you use this also. The only other part of this code that can differ is the last parameter to HostUserControl() which is the full class name for your Tool Window in our case "MsgrAddin.HostUserControl".

The Messenger Code

Right, now for the Messenger window itself. I hope everyone here already knows how to create a windows form and find their way round the source code because the only difference here is that this will be a User Control. A user control can be created with by adding a new item to the Messenger add-in project and choosing a user control. From here on it is exactly the same as working with a windows form, which I will get to in a moment. Once you have added the controls and events for the Send button and the user ListView we can now add the code. There are a couple of members in the control class that we need:

Initialization

Messenger.MsgrObjectClass msg;
Messenger.IMsgrUser CurrentUser;
Messenger.IMsgrUsers Users;

We set these up in the constructor as follows:

msg = new Messenger.MsgrObjectClass();

try
{
  // TODO: Improve login for errors and cancel

  // Check if messenger is signed in

  if(msg.LocalState == Messenger.MSTATE.MSTATE_OFFLINE)
  {
    Messenger.MessengerAppClass app = 
        new Messenger.MessengerAppClass();

    app.IMessengerApp_LaunchLogonUI();

    // HACK: Must be a better way

    // wait for the login to complete

    while(msg.LocalState != Messenger.MSTATE.MSTATE_ONLINE)
      System.Threading.Thread.Sleep(5000);
  }

  // Get the User list and fill the list view

  Users = msg.get_List(Messenger.MLIST.MLIST_CONTACT);

  for(int i = 0; i < Users.Count; i++)
  {
    Messenger.IMsgrUser u = Users.Item(i);
    userList.Items.Add(new ListViewItem(u.FriendlyName, GetStateImage(u.State)));
  }

  // Recieve notification for messages recieved

  msg.OnTextReceived +=
    new Messenger.DMsgrObjectEvents_OnTextReceivedEventHandler
                                     (this.OnTextRecieved);

  // Recieve notification for user state change

  msg.OnUserStateChanged += new 
    Messenger.DMsgrObjectEvents_OnUserStateChangedEventHandler
                                     (this.OnUserStateChanged);
	
}
// TODO: Improve exception handling

catch(Exception e)
{
	MessageBox.Show(e.Message);
}

Receiving Messages

Having now set all our objects we just need the code for the different events OnTextRecieved() is called whenever Messenger receives a message. The only time we are interested is when the content type is text.

private void OnTextRecieved(Messenger.IMsgrIMSession s, 
    Messenger.IMsgrUser u, string header, string text, 
    ref bool default)
{
    if(header.IndexOf("Content-Type: text/plain") != -1 && 
        u.FriendlyName != "Hotmail")
    {
        messageWindow.AppendText(u.FriendlyName + ": " + text + "\r\n");
        CurrentUser = u;
        default = false;
    }
}

When we receive a text message this is appended to the edit control (anyone want to enhance the text control to support fonts, hyperlinks, smileys etc). You will notice that the default parameter is changed to false this causes Messenger not to show a chat window itself.

Sending Messages

As the code runs the current contact changes depending on what you have selected in the user list and the last message received so be aware of who you are sending your message to. To send a message to the current contact a message can be typed into the edit box and clicking send with this code:

private static string header = 
    "MIME-Version: 1.0\r\nContent-Type: text/plain;" +
    "charset=UTF-8\r\nX-MMS-IM-Format: " +
    "FN=MS%20Shell%20Dlg; EF=; CO=0; CS=0; PF=0\r\n\r\n";

private void send_Click(object sender, System.EventArgs e)
{
    CurrentUser.SendText(header, this.sendText.Text, 
        Messenger.MMSGTYPE.MMSGTYPE_ALL_RESULTS);
    
    messageWindow.AppendText("You say: " + sendText.Text + "\r\n");
}

On sending the message it is appended to the message window. Messenger sends a header with the message a bit of debugging supplied the header string shown above this is so messenger know what to do with the message at the other end just like we do in the OnTextRecieved() above.

Updating contacts status

As with the main messenger client I show the status of users with different icons in the ListView. This status is first updated when the constructor is called but as this status changes the OnUserStatusChanged() event is called using this event the icons can be updated:

private void OnUserStateChanged(Messenger.IMsgrUser user, 
    Messenger.MSTATE state, ref bool default)
{
    for(int i = 0; i < Users.Count; i++)
    {
        if(user == Users.Item(i))
        {
            ListViewItem item = userList.Items[i];
            item.ImageIndex = GetStateImage(user.State);
        }
    }
}

The state parameter that is passed holds the previous state so it is necessary to find the user in our list of Users in order to find their new status. The ListView is then updated with the new status.

Summary

I hope this has been of some interest to somebody. Now that you know how to use a small part of the Messenger functionality, have a play with the other things that are available. I think there are many other things that could be done with Messenger and I hope someone comes up with other articles with these ideas. On a more serious note having seen how easy it is to create add-ins for VS.NET you can now produce some more productive add-ins.

Disclaimer

It works on my machine

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here