Office Communicator Automation API gives you the ability to construct a fully functional custom contact list within your application. This contact list can be the base on which all other Office Communicator Automation functionality is built. Initiating a conversation using IM, telephone or video always begins by selecting one or more contacts from your list. If you want to initiate these conversations from within your application, you must also implement a contact list in your application.

The examples cited in this topic are from a C# sample application installed when you installed this SDK. The sample application uses the contact list in this example to select and manage contacts. Using asynchronous callback functions, the example contact list is able to display remote contact status in real time as it changes. This feature is critical to the success of your custom contact list.

Typically, you will create a contact list organized by contact group. You can use this list to interact with your contacts. This interaction can include:

To accomplish this functionality, this topic demonstrates the implementation of various Office Communicator Automation API interfaces. These interfaces allow you to create a fully functional contact list. The Messenger cocreatable object is used in conjunction with these interfaces:

The IMessenger2::MyGroups method provides a collection of IMessengerGroup objects. The IMessengerGroup::Contacts method provides a collection of IMessengerContact objects. Finally, the IMessengerContactAdvanced interface provides you with methods and properties to manage presence for each of the contacts in your contact list.

The example code also uses the IMessenger::MyContacts property. This property is used to directly access the local client contact list without interacting with contact groups. This is necessary in the case of a local client application that cannot display ListView items by group. In all other cases, the code uses a contact collection in the context of the owning group.

The following example is from the sample C# application installed with this SDK. The form uses a ListView control to display the contacts for a local client. The complete code listing at the end of the topic is from ContactList.cs. The designer generated code for the Windows form and controls is found in ContactList.Designer.cs.

Contact List

To implement the contact list in the example, you need to accomplish several programming tasks. The application logic for each task is fairly simple. A C# programmer with limited experience should be able to create a contact list from this example.

The contactList class represents the custom contact list example. The form uses a ListView control, a context menu strip activated by clicking the right mouse button, a select button, and a close button. The constructor method of the contactList class is where you find the bulk of the automation code that builds the contact list. The programming tasks accomplished by the class are described below.

Calling a Custom Contact List Dialog

Describes a scenario where you call a custom contact dialog in your application.

Determining the Local Client Operating System

Describes the reasons why your application should detect the local machine host operating system.

Loading Contact Groups

Describes filling a ListView control organized by group and item.

Loading Contacts without Grouping

Describes filling a ListView control using ListViewItem objects only.

Loading Contacts into ListView Group Item

A detailed description of the process of loading contacts and groups. Includes a code example.

Updating Contact Status

Describes the process of keeping contact status current using a callback function.

Adding and Removing Contacts from the List

Describes the process of requesting the addition or removal of a contact from the local client contact list.

Adding and Removing Contact Groups from the List

Describes the process of requesting the addition or removal of a group from the local client contact list.

Removing a Contact from a Group

Describes the process of removing a contact from a group.

Selecting Contacts from the List

Describes the process of processing the user selection of multiple contacts to returned to a calling form.

Moving a Contact into a Contact Group

Describes the process of associating a contact to a group.

Summary

This example took you through the creation of an Office Communicator contact list and the use of the custom list in a sample application to initiate a multi-contact conference. It demonstrated the use of several Office Communicator Automation API interfaces to access and select contacts, contact groups, and contact presence information. If you want to incorporate the contactList class in your application, you need to also include the ContactList.Designer.cs and ContactList.resx source files because they contains the definitions of the form, controls, and the image list used to display the presence gum-drops in the ListView control.

This topic did not cover all the possible functionality of the contact management related interfaces of Office Communicator Automation API. The installed C# SDK sample application demonstrates this additional functionality.

Complete Code Sample

Copy Code
/*====================================================
Copyright (c) Microsoft Corporation. All rights reserved.

This source code is intended only for use with Microsoft Development Tools and/or on-line documentation.  See these other materials for detailed information regarding Microsoft code samples.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS."  YOU BEAR THE RISK OF USING IT.
MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTIES OR CONDITIONS.
TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
=====================================================*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CommunicatorAPI;
using CommunicatorPrivate;
using System.Runtime.InteropServices;
using System.Collections;
using Microsoft.Win32;

namespace sampleOCClient
{
	public partial class contactList : Form
	{
		CommunicatorAPI.MessengerClass communicator;
		IMessengerGroups contactGroups;
		IMessengerContacts contactCollection;
		stringInputForm stringForm;
		ReturnError formReturnErrors = new ReturnError();
		bool isRunningXPOrLater = false;
		/*
		 * listDict keeps a listview item index integer paired with 
		 * a contact signin name. This is used to determine the contact
		 * signin name placed in the public SignInName property at the time
		 * the user clicks the selectButton
		 */
		Dictionary<Int32,String> listDict = new Dictionary<int,string>();

		/*
		 * the SignInName property represents the contact signin name
		 * selected by the user from the listview. The calling code will query
		 * this property to determine which contact was selected from the listview
		 */
		string signInName = "";
		public string SignInName
		{
			get
			{ return signInName; }
			set
			{ signInName = value; }
	}

		/*
		 * This property is set by the calling code to cause the
		 * contact list to display the selectButton
		 */
		bool selectMode = false;
		public bool SelectMode
		{
			set
			{ 
				selectMode = value;
				if (selectMode == true)
				{
					SelectButton.Visible = true;
					SelectButton.Refresh();
			}
		}
	}
		public contactList(object Communicator)
		{

			InitializeComponent();
			Application.EnableVisualStyles();
			isRunningXPOrLater = OSFeature.Feature.IsPresent(OSFeature.Themes);
			try
			{
				communicator = (CommunicatorAPI.MessengerClass)Communicator;
				listDict.Clear();
				if (communicator != null)
				{
					contactListView.ShowItemToolTips = true;
			}
			
		}
			catch (COMException ce)
			{
				throw new COMException(
						"Contact List COM Exception" ,
						ce.ErrorCode
						); 
		}
			catch (Exception e)
			{
				throw new Exception(
						"Contact List Exception" ,
						e.InnerException
						);
		}
	}
		private void loadGroupsIntoMenu()
		{
			IMessengerGroups theseGroups = (IMessengerGroups)communicator.MyGroups;
			this.moveContactToGroupItem.DropDownItems.Clear();
			foreach (IMessengerGroup thisGroup in theseGroups)
			{
				if (thisGroup.Name != "~")
				{
					this.moveContactToGroupItem.DropDownItems.Add(thisGroup.Name);
			}
				else
				{
					this.moveContactToGroupItem.DropDownItems.Add("Other Contacts");
			}
		}
			foreach (ToolStripMenuItem i_MenuItem in moveContactToGroupItem.DropDownItems)
			{
				try
				{
					i_MenuItem.Click += new System.EventHandler(this.OtherContactsItem_Click);
			}
				catch (Exception e)
				{
					MessageBox.Show(e.Message.ToString());
			}
		}
	}

		void i_MenuItem_DropDownItemClicked(
			 object sender, 
			 ToolStripItemClickedEventArgs e
			 )
		{
			throw new Exception("The method or operation is not implemented.");
	}
		private ListViewGroup createGroupListItem(
							object passedGroup,
							int groupCount
							)
		{
			/*
			 * 1st overload of ListViewGroup accepts an IMessengerGroup and total contact groups
			 * The contact collection of the passedGroup is iterated on to load individual
			 * contact items into the ListView as ListViewItem objects
			*/
			ListViewGroup returnGroup;

			//cast passedGroup object to IMessengerGroup interface
			IMessengerGroup workGroup = (IMessengerGroup)passedGroup;
			string groupHead;
			bool isAllContactGroup = false;

			//is passed group the "Other Contacts" group?
			if (workGroup.Name == "~")
			{
				if (groupCount > 1)
					groupHead = "Other Contacts";
				else
					groupHead = "All Contacts";
				isAllContactGroup = true;
		}
			else
				groupHead = workGroup.Name;

			//create ListViewGroup object and set text + alignment
			returnGroup = new ListViewGroup(
							groupHead, 
							HorizontalAlignment.Left
							);
		
			//get collection of contacts belonging to group
			IMessengerContacts workGroupContacts = (IMessengerContacts)workGroup.Contacts;

			if (workGroupContacts != null && workGroupContacts.Count > 0)
			{
				//iterate over collection of contacts
				foreach (IMessengerContact groupContact in workGroupContacts)
				{
					processContactIntoList(groupContact, isAllContactGroup, returnGroup);
			}
		}
			return returnGroup;
	}

		private ListViewGroup createGroupListItem(
					string passedGroupName
					)
		{
			/*
			 * 2nd overload of ListViewGroup accepts a string as a group name
			 * and iterates on local machine registry key HKEY_CURRENT_USER\Software\Microsoft\Communicator\<communicator.MySigninName>\GroupStateCacheU\~~
			 * values for recent Office Communicator users by SignInName.
			 * Each SignInName in the registry key is passed as an argument to GetContact(). 
			 * The returned IMessengerContact object is used to add a ListViewItem representing
			 * the contact.
			 *Caution: 
			 *Incorrectly editing the registry may severely damage
			 *your system. Before making changes to the registry, 
			 *You should back up any valued data on the computer.
			 */

			//cast passedGroup object to IMessengerGroup interface
			string groupHead = passedGroupName;
			bool isAllContactGroup = false;


			//create ListViewGroup object and set text + alignment
			ListViewGroup returnGroup = new ListViewGroup(
							groupHead,
							HorizontalAlignment.Left
							);

			try
			{
				RegistryKey currentUserKey = Registry.CurrentUser.
										OpenSubKey("Software").
										OpenSubKey("Microsoft").
										OpenSubKey("Communicator").
										OpenSubKey(communicator.MySigninName).
										OpenSubKey("GroupStateCacheU").
										OpenSubKey("~~");
				string[] valueName = currentUserKey.GetValueNames();
				if (valueName != null)
				{
					for (int i = 1; i < valueName.Length; i++)
					{
						if (valueName[i].Length > 0)
						{
							string keyValue = currentUserKey.GetValue(valueName[i]) as string;
							if (keyValue != null)
							{
								if (keyValue.Length > 0 && keyValue.ToUpper().Contains("SIP:"))
								{
									IMessengerContact thisContact = (IMessengerContact)communicator.GetContact(keyValue, communicator.MyServiceId);
									if (thisContact != null && thisContact.IsSelf == false)
									{
										processContactIntoList(thisContact, isAllContactGroup, returnGroup);
								}
							}
						}
					}
				}
			}
				currentUserKey.Close();
			
		}
			catch (COMException CE)
			{
				MessageBox.Show("COM Exception: " + formReturnErrors.returnComError(CE.ErrorCode));
		}
			catch (Exception e)
			{
				MessageBox.Show("Exception: " + e.Message);
		}

			return returnGroup;
	}

		private void processContactIntoList(object passedContact, bool isAllContactGroup,object returnGroup)
		{
			/*
			 * takes a passed IMessengerContact object, a boolean flag indicating the "Other Contacts" group
			 * is being processed, and the ListViewGroup object to be added to the ListView.
			 * When the "Other Contacts" group is being processed, the code must determine that the contact 
			 * has not been added to one of the user defined groups yet. If not, the contact is added to "Other Groups"
			 * 
			 * Adding the contact amounts to getting the presence properties of the contact and adding the appropriate
			 * values as sub-items of the ListViewItem representing the contact added to the ListView
			 */

			IMessengerContact thisContact = (IMessengerContact)passedContact;
			ListViewGroup thisGroup = (ListViewGroup)returnGroup;
			//look for contact already in list
			ListViewItem contactToUpdate = null;
			contactToUpdate = contactListView.FindItemWithText(thisContact.FriendlyName);

			//if not processing the "Other Contacts" group OR 
			//   processing the "Other Contacts" group and contact is NOT already in list...
			if (isAllContactGroup == false || (isAllContactGroup == true && contactToUpdate == null))
			{

				//create new ListViewItem with contact Friendly Name
				ListViewItem contactItem = new ListViewItem(
											 thisContact.FriendlyName.ToString(),
											 thisGroup
											 );

				//set tooltip by querying presence properties array for Presence Note
				IMessengerContactAdvanced a_contact = (IMessengerContactAdvanced)thisContact;
				object[] a_presenceProp = (object[])a_contact.PresenceProperties;
				string toolString = a_presenceProp[(int)PRESENCE_PROPERTY.PRESENCE_PROP_PRESENCE_NOTE].ToString();
				if (toolString.Length == 0)
					toolString = "Default Toolstring";
				contactItem.ToolTipText = toolString;


				//set presence icon and availability string for contact in listview
				string statusString = "";
				statusString = updateContactList(
							 contactItem,
							 (IMessengerContactAdvanced)thisContact
							 );

				//add listview sub item for status column of contact list
				ListViewItem.ListViewSubItem itemToAdd = new ListViewItem.ListViewSubItem();
				itemToAdd.Name = "Status";
				itemToAdd.Text = statusString;

				//add sub-item to item
				contactItem.SubItems.Add(itemToAdd);

				// add item to contact list
				contactListView.Items.Add(contactItem);

				//with new index value, add to dictionary using index of item added
				// and sign-in name. 
				listDict.Add(
						 contactListView.Items.Count,
						 a_contact.SigninName
						 );
		} // here

	}

		public void createContactItem(object passedContact)
		{
			/*
			 * called when a non-XP workstation is host of application. The contacts cannot be
			 * displayed under ListViewGroup objects. Instead, the contact collection of the 
			 * communicator object is iterated on and each contact in the collection is loaded
			 * in the ListView with its presence properties.
			 */

			//cast passedContact to IMessengerContact interface
			try
			{
				IMessengerContactAdvanced workContact = (IMessengerContactAdvanced)passedContact;

				try
				{
					//create new ListViewItem object with contact Friendly Name
					ListViewItem contactItem = new ListViewItem(workContact.FriendlyName.ToString());

					//set presence icon and availability string
					string statusString = updateContactList(
										contactItem, 
										(IMessengerContactAdvanced)workContact
										);

					//create sub item object and add to sub-item collection of item
					ListViewItem.ListViewSubItem itemToAdd = new ListViewItem.ListViewSubItem();
					itemToAdd.Name = "Status";
					itemToAdd.Text = workContact.Status.ToString();
					contactItem.SubItems.Add(itemToAdd);

					//set tooltip value of item
					object[] a_presenceProp = (object[])workContact.PresenceProperties;
					string toolString = a_presenceProp[(int)PRESENCE_PROPERTY.PRESENCE_PROP_PRESENCE_NOTE].ToString();
					contactItem.ToolTipText = toolString;

					//add contact item to listview
					contactListView.Items.Add(contactItem);
			}
				catch (Exception)
				{
			}
		}
			catch (InvalidCastException)
			{ }
	}
		public void updateContactStatus(
					object passedContact, 
					MISTATUS newStatus
					)
		{
			//cast passedContact to IMessengerContactAdvanced interface
			IMessengerContactAdvanced thisContact = (IMessengerContactAdvanced)passedContact;
			try
			{
				//look for passed contact in listview
				ListViewItem contactToUpdate = contactListView.FindItemWithText(thisContact.FriendlyName);

				//if found, update the icon and availability string
				string newContactStatus = "";
				if (contactToUpdate != null)
					newContactStatus = updateContactList(
									 contactToUpdate, 
									 thisContact
									 );

		}
			catch (Exception)
			{
				throw;
		}
	}

		private void closeButton_Click(
					 object sender,
					 EventArgs e
					 )
		{
			this.Close();
	}

		private void SelectButton_Click(
					 object sender,
					 EventArgs e
					 )
		{
			/*
			 * When this form is opened and the SelectMode property is
			 * set to true, this selectButton is displayed so that the user
			 * can select multiple contacts. The selected contacts are returned
			 * with the SignInName property which will contain a comma-separated list
			 * of contact sign-in names.
			 * 
			 * This code iterates on the collection of selected listview items and looks
			 * up the corresponding signin name from the dictionary<int,string> object listDict
			 * Each signin name is appended to a string. Until the count of 
			 * selected contacts processed by the foreach loop reaches the total number of contacts
			 * processed, a comma is appended to the string.
			 */
			try
			{
				StringBuilder sb = new StringBuilder();
				int currentSelectedContact = 1;
				foreach (ListViewItem selectedContactItem in contactListView.SelectedItems)
				{
					if (contactListView.SelectedItems.Count == 1)
					{
						//append signin name of contact
						sb.Append(listDict[selectedContactItem.Index + 1]);
				}
					else
					{
						//append signin name of contact
						sb.Append(listDict[selectedContactItem.Index + 1]);

						//append a comma if this contact is not the last contact selected
						if (currentSelectedContact < contactListView.SelectedItems.Count)
							sb.Append(", ");
						currentSelectedContact++;
				}
			}
				// fill property with string built by foreach loop
				signInName = sb.ToString();
		}
			catch (Exception)
			{
				throw;
		}
			this.Close();
	}

		private string updateContactList(
					 ListViewItem contactItem,
					 IMessengerContactAdvanced contact
					 )
		{
			/*
			 * this method updates the ListView item passed as parameter 1 with the status information
			 * of the passed IMessengerContact object
			 */

			string statusString = "";
			switch (contact.Status)
			{
				case MISTATUS.MISTATUS_AWAY:
					statusString = "Away";
					contactItem.ImageIndex = 1;
					break;
				case MISTATUS.MISTATUS_BE_RIGHT_BACK:
					statusString = "Be right back";
					contactItem.ImageIndex = 1;
					break;
				case MISTATUS.MISTATUS_BUSY:
					statusString = "Busy";
					contactItem.ImageIndex = 10;
					break;
				case MISTATUS.MISTATUS_DO_NOT_DISTURB:
					statusString = "Do not disturb";
					contactItem.ImageIndex = 8;
					break;
				case MISTATUS.MISTATUS_IN_A_CONFERENCE:
					statusString = "In a conference";
					contactItem.ImageIndex = 10;
					break;
				case MISTATUS.MISTATUS_IN_A_MEETING:
					statusString = "In a meeting";
					contactItem.ImageIndex = 10;
					break;
				case MISTATUS.MISTATUS_OFFLINE:
					statusString = "Off-line";
					contactItem.ImageIndex = 16;
					break;
				case MISTATUS.MISTATUS_ON_THE_PHONE:
					statusString = "In a call";
					contactItem.ImageIndex = 10;
					break;
				case MISTATUS.MISTATUS_ONLINE:
					statusString = "Available";
					contactItem.ImageIndex = 19;
					break;
				case MISTATUS.MISTATUS_IDLE:
					statusString = "Idle";
					contactItem.ImageIndex = 14;
					break;
				case MISTATUS.MISTATUS_OUT_OF_OFFICE:
					statusString = "Out of the office";
					contactItem.ImageIndex = 1;
					break;
				case MISTATUS.MISTATUS_OUT_TO_LUNCH:
					statusString = "Out to lunch";
					contactItem.ImageIndex = 1;
					break;
				default:
					statusString = "Unknown";
					contactItem.ImageIndex = 22;
					break;
		}

			//The status string of the listview item is updated

			//instantiate a collection of sub-items for the current listview item
			ListViewItem.ListViewSubItemCollection subCollection = contactItem.SubItems;

			//iterate over the collection, looking for the subitem whose name is "Status"
			foreach (ListViewItem.ListViewSubItem subItem in subCollection)
			{
				//if the "Status" item then update the text value
				if (subItem.Name == "Status")
					subItem.Text = statusString;
		}
			return statusString;
	}

		private void addContactButton_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			// add a contact
			try
			{
				int parentHandle = 0;
				stringForm = new stringInputForm();
				stringForm.PromptString = "Contact Sign-in Name";
				stringForm.TitleText = "Input Contact Sign-in Name";
				stringForm.ShowDialog();
				if (stringForm.StringBoxText.Length > 0)
					communicator.AddContact(
								 parentHandle, 
								 stringForm.StringBoxText
								 );
				stringForm.Close();
		}
			catch (ArgumentException AE)
			{
			 MessageBox.Show("Contact List " + AE.Message.ToString());
		}
			catch (COMException ACE)
			{
				MessageBox.Show("Contact List " + formReturnErrors.returnComError(ACE.ErrorCode));
		}

	}
		public void loadContactList()
		{

			/*
			* This method is responsible for building the
			* contact list. Before building the contact list, the code must determine
			* what operating system is hosting the application. 
			* By calling OSFeature.Feature.IsPresent(OSFeature.Themes) which returns a boolean value,
			* the code determines that it will create contact groups if client is hosted by Windows XP.
			* 
			* If XP:
			*	A collection of contact groups is returned by a call to IMessenger::MyGroups
			*	If a collection of groups exists...
			*	 The collection is iterated over to process each individual group. This process
			*	 includes adding each group member(contact) to first a: the group b: the listview.
			* 
			*	 The "Other Contacts" group is not processed in this iteration. It is necesary to 
			*	 add all contacts which belong to groups first. After the user defined groups and 
			*	 their contacts have been added to the list view, the "Other Contacts" group is added.
			*	 This last group contains every contact belonging to the local client. To avoid adding
			*	 contacts to the "Other Contacts" group when the contact has already been added to a 
			*	 user-define group, the code checks to see if the contact already exists in the list. 
			*	 If it does not, then the contact is added to the "Other Contacts" group.
			* If NOT XP:
			*	A collection of contacts is returned by a call to IMessenger::MyContacts.
			*	The code iterated over the collection and adds each individual contact to the contactListView.
			*/

			contactListView.Items.Clear();
			contactListView.Groups.Clear();
			listDict.Clear();
			try
			{
				contactCollection = (IMessengerContacts)communicator.MyContacts;
				if (isRunningXPOrLater == true && OSFeature.Feature.IsPresent(OSFeature.Themes))
				{
					// get contact group collection
					contactGroups = (IMessengerGroups)communicator.MyGroups;
					if (contactGroups != null)
					{
						//instantiate IMessengerGroup object for the "Other Contacts" group
						IMessengerGroup allContactGroup = null;
						contactListView.BeginUpdate();
						//iterate on the groups collection
						foreach (IMessengerGroup contactGroupItem in contactGroups)
						{
							//process all user-defined contact groups
							if (contactGroupItem.Name != "~")
							{
								//process individual group and return created group list view item object
								ListViewGroup newGroup = createGroupListItem(
														 contactGroupItem, 
														 contactGroups.Count
														 );

								contactListView.Groups.Add(newGroup);
								ListViewItem groupItem = new ListViewItem(newGroup);
						}
							// "Other Contacts" group
							else
							{
								// set IMessengerGroup object equal to found "Other Contacts" group
								allContactGroup = contactGroupItem;
						}
					}
						if (allContactGroup != null)
						{
							//process "Other Contacts" group
							ListViewGroup newGroup = createGroupListItem(
													 allContactGroup, 
													 contactGroups.Count
													 );
							contactListView.Groups.Add(newGroup);
					}

						ListViewGroup recentUsersGroup = createGroupListItem("Recent Contacts");
						contactListView.Groups.Add(recentUsersGroup);
				}
			}
				else
				{
					//get collection of contacts for local client
					if (contactCollection != null)
					{
						//iterate over collection of contacts
						foreach (IMessengerContact contactItem in contactCollection)
						{
							//add contact to listview
							createContactItem(contactItem);
					}
				}
			}
				contactListView.EndUpdate();
				loadGroupsIntoMenu();


		}
			catch (COMException)
			{
				throw;
		}
			catch (Exception)
			{

				throw;
		}
	}

		private void removeContactButton_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			try
			{
				foreach (ListViewItem selectedContactItem in contactListView.SelectedItems)
				{
					object contactToRemove = null;
					contactToRemove = communicator.GetContact(listDict[selectedContactItem.Index + 1],communicator.MyServiceId);
					if (contactToRemove != null)
						contactCollection.Remove((IMessengerContact)contactToRemove);
					selectedContactItem.BackColor = Color.Gray;
			}
		}
			catch (ArgumentException AE)
			{
				MessageBox.Show("Contact List Argument Exception: " + AE.Message.ToString());
		}
			catch (COMException CE)
			{
				MessageBox.Show("Contact List COM Exception: " + formReturnErrors.returnComError(CE.ErrorCode));
		}
			catch (Exception Ex)
			{
				MessageBox.Show("Contact List Exception: " + Ex.Message);
		}

	}

		private void contactActionMenu_Opening(
					 object sender, 
					 CancelEventArgs e
					 )
		{

	}

		private void removeContactItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			try
			{
				ListViewItem selectedContactItem = contactListView.FocusedItem;
				if (selectedContactItem.Text.Length > 0)
				{
					object contactToRemove = null;
					contactToRemove = communicator.GetContact(listDict[selectedContactItem.Index + 1], communicator.MyServiceId);
					if (contactToRemove != null)
						contactCollection.Remove((IMessengerContact)contactToRemove);
					selectedContactItem.BackColor = Color.Gray;
			}
		}
			catch (ArgumentException AE)
			{
				MessageBox.Show("Contact List Argument Exception: " + AE.Message.ToString());
		}
			catch (COMException CE)
			{
				MessageBox.Show("Contact List COM Exception: " +
								formReturnErrors.returnComError(CE.ErrorCode)
								);
		}
			catch (Exception Ex)
			{
				MessageBox.Show("Contact List Exception: " + 
								Ex.Message
								);
		}
	}

		private void addContactToolStripMenuItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			// add a contact
			try
			{
				int parentHandle = 0;
				stringForm = new stringInputForm();
				stringForm.PromptString = "Contact Sign-in Name";
				stringForm.TitleText = "Input Contact Sign-in Name";
				stringForm.ShowDialog();
				if (stringForm.StringBoxText.Length > 0)
					communicator.AddContact(parentHandle, 
								 stringForm.StringBoxText
								 );
				stringForm.Close();

		}
			catch (ArgumentException AE)
			{
				MessageBox.Show("Contact List " + 
								AE.Message.ToString()
								);
		}
			catch (COMException ACE)
			{
				MessageBox.Show("Contact List " + 
								formReturnErrors.returnComError(ACE.ErrorCode)
								);
		}

	}

		private void addGroupToolStripMenuItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			try
			{
				stringForm = new stringInputForm();
				stringForm.PromptString = "Group Name";
				stringForm.TitleText = "Input Group Name";
				stringForm.ShowDialog();
				if (stringForm.StringBoxText.Length > 0)
					communicator.CreateGroup(
								 stringForm.StringBoxText, 
								 "serviceID"
								 );

				stringForm.Close();
		}
			catch (COMException CGCE)
			{

				MessageBox.Show(
						 formReturnErrors.returnComError(CGCE.ErrorCode)
						 );
		}
			catch (Exception CGE)
			{
				MessageBox.Show(
						 CGE.Message.ToString()
						 );
		}

	}

		private void removeGroupToolStripMenuItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{

	}

		private void removeGroupToolStripMenuItem_Click_1(
					 object sender, 
					 EventArgs e
					 )
		{
			try
			{
				ListViewItem selectedContactItem = contactListView.FocusedItem;
				if (selectedContactItem != null)
				{
					IMessengerGroups theseGroups = (IMessengerGroups)communicator.MyGroups;
					foreach (IMessengerGroup thisGroup in theseGroups)
					{
						if (thisGroup.Name == selectedContactItem.Group.Header)
						{
							theseGroups.Remove(thisGroup);
							break;
					}
				}
			}
		}
			catch (COMException ICE)
			{
				MessageBox.Show(
						 formReturnErrors.returnComError(ICE.ErrorCode)
						 );
		}

	}

		private void removeFromGroupItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			try
			{
				ListViewItem selectedContactItem = contactListView.FocusedItem;
				if (selectedContactItem.Text.Length > 0)
				{
					object contactToRemove = null;
					contactToRemove = communicator.GetContact(
												 listDict[selectedContactItem.Index + 1], 
												 communicator.MyServiceId
												 );
					if (contactToRemove != null)
					{
						IMessengerGroups theseGroups = (IMessengerGroups)communicator.MyGroups;
						foreach (IMessengerGroup thisGroup in theseGroups)
						{
							if (thisGroup.Name == selectedContactItem.Group.Header)
							{
								thisGroup.RemoveContact(contactToRemove);
								break;
						}
					}
						foreach (IMessengerGroup thisGroup in theseGroups)
						{
							if (thisGroup.Name == "~")
							{
								thisGroup.AddContact(contactToRemove);
								break;
						}
					}

				}
					selectedContactItem.BackColor = Color.Gray;
			}
		}
			catch (ArgumentException AE)
			{
				MessageBox.Show(
						 "Contact List Argument Exception: " + 
						 AE.Message.ToString()
						 );
		}
			catch (COMException CE)
			{
				MessageBox.Show(
						 "Contact List COM Exception: " + 
						 formReturnErrors.returnComError(CE.ErrorCode)
						 );
		}
			catch (Exception Ex)
			{
				MessageBox.Show(
						 "Contact List Exception: " + 
						 Ex.Message
						 );
		}


	}

		private void addContactToGroupItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{
	}

		private void GroupBink(
					 object sender, 
					 DragEventArgs e
					 )
		{
	}

		private void itemDragging(
					 object sender, 
					 ItemDragEventArgs e
					 )
		{

	}

		private void processItem(
					 object sender, 
					 ToolStripItemClickedEventArgs e
					 )
		{

	}

		private void OtherContactsItem_Click(
					 object sender, 
					 EventArgs e
					 )
		{
			/*
			 * called when user selects Move Contact To... and makes a selection among
			 * the user-defined groups loaded into the menu.
			 * Gets the contact based on the ListView item which has focus. 
			 * the generic dictionary listDict<int,string> is used to look up the SigninName
			 * of the contact based on the index position in the ListView.
			 * 
			 * The correct IMessengerGroup to add the contact to is found by 
			 * iterating on the IMessengerGroups collection of the communicator object
			 * When a group is found with a name matching the user selection on the menu, 
			 * the contact is added to that group and the code breaks out of the iteration.
			 */
			string groupName = sender.ToString();
			if (groupName == "Other Contacts")
				groupName = "~";
			try
			{
				ListViewItem selectedContactItem = contactListView.FocusedItem;
				if (selectedContactItem.Text.Length > 0)
				{
					object contactToAdd = null;
					contactToAdd = communicator.GetContact(
												listDict[selectedContactItem.Index + 1],
												communicator.MyServiceId
												);
					if (contactToAdd != null)
					{
						IMessengerGroups theseGroups = (IMessengerGroups)communicator.MyGroups;
						foreach (IMessengerGroup thisGroup in theseGroups)
						{
							if (thisGroup.Name == groupName)
							{
								thisGroup.AddContact(contactToAdd);
								break;
						}
					}

				}
					selectedContactItem.BackColor = Color.Gray;
			}
		}
			catch (ArgumentException AE)
			{
				MessageBox.Show(
						 "Contact List Argument Exception: " + 
						 AE.Message.ToString()
						 );
		}
			catch (COMException CE)
			{
				MessageBox.Show(
						 "Contact List COM Exception: " + 
						 formReturnErrors.returnComError(CE.ErrorCode)
						 );
		}
			catch (Exception Ex)
			{
				MessageBox.Show(
						 "Contact List Exception: " + 
						 Ex.Message
						 );
		}

	}

		private void addContactToGroupItem_Click_1(object sender, EventArgs e)
		{

	}
}
}

Changing Presence of the Caller

You can only change your own presence status, although you can query the presence of others. Changing presence involves setting the IMessenger::MyStatus property to a different value as defined in the MISTATUS enumerated type, as illustrated in the following C# code snippet.

Copy Code
CommunicatorAPI.Messenger communicator = null;
communicator = new CommunicatorAPI.Messenger();

// Assume a local Communnicator is running.

// Shows the status of the caller as Do Not Disturb.
communicator.MyStatus = MISTATUS_DO_NOT_DISTURB;

You can also set the IMessengerContactAdvanced::PresenceProperties to publish the following presence status:

  • Availability

  • System-defined activity

  • Custom activity

  • Presence status

For more information, see IMessengerContactAdvanced::PresenceProperties.

Getting Presence Status of a User

When a user object (implementing the IMessengerContact interface) is retrieved, the user's presence status is obtained by calling the IMessengerContact::Status property. This following C# code snippet illustrates retrieving the presence status.

Copy Code
private string GetPresence(IMessengerContact contact)
{
	MISTATUS presenceStatus = MISTATUS.MISTATUS_UNKNOWN;

	//We need the try here since Communicator will return a contact 
	//object for any SIP URI that it is handled whether it can be 
	//resolved or not. All the properties of the contact object are 
	//valid except the status which returns a COM exception when you 
	//try to access it. 
	try
	{
		presenceStatus = contact.Status;
}
	catch
	{
		presenceStatus = MISTATUS.MISTATUS_UNKNOWN;
}

	string strStatus = Enum.GetName(typeof(MISTATUS), presenceStatus);
	return strStatus;
}

In a production code, the strStatus variable should return a more user-friendly string that is mapped to the presenceStatus value.

See Also