![]() |
General Programming »
Macros and Add-ins »
VS.NET Add-ins
Intermediate
VS.NET MSN Messenger Add-InBy John A DavisAn add-in for VS.NET to enable MSN Messenger in a tool window |
C#, VC7.NET 1.0, Win2K, WinXP, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||

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
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.
tlbimp msmgs.exe /out:Messenger.dll
ildasm /text Messenger.dll /out:Messenger.il
.class private auto ansi sealed DMsgrObjectEvents_SinkHelperto
.class public auto ansi sealed DMsgrObjectEvents_SinkHelperand just below that
.class private auto ansi sealed DMsgrObjectEvents_EventProviderto
.class public auto ansi sealed DMsgrObjectEvents_EventProvider
ilasm /dll Messenger.il
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:
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.
VSUserControlHostOnConnection 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".
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:
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);
}
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.
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.
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.
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.
It works on my machine
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 29 Jul 2002 Editor: James T. Johnson |
Copyright 2002 by John A Davis Everything else Copyright © CodeProject, 1999-2009 Web16 | Advertise on the Code Project |