This topic demonstrates how to start an instant messaging conversation. This process involves creating a Conversation instance using the ConversationManager class, creating a participant using the Conversation instance, and connecting to the participant using one of the participant's modalities. In this process, you must handle state change events on both the ConversationManager and Conversation .

The following figure illustrates the classes, methods, and events used in the process of starting an instant messaging conversation.

Starting an Instant Messaging Conversation

The following walkthrough steps obtain a conversations manager and add the conversation.

Walkthrough Steps

  1. Create a callback method that handles the ConversationAdded event.

  2. Create a callback method that handles the ParticipantAdded event.

  3. Get the LyncClient instance and verify that the client is signed in to the server. For information about signing in to Microsoft Lync Server 2010, see Walkthrough: Sign In to Lync with UI Suppressed

  4. Get the ConversationManager class instance by reading the ConversationManager property.

  5. Register for the ConversationAdded event.

  6. Call AddConversation .

    Important note Important

    If you have a conference Url and you intend to join the associated conference, call JoinConference instead of AddConversation. An instance of Conversation is returned.

Additional walkthrough steps are described in the following section.

Handling Events

The next two procedures are examples of the steps to create event handlers for conversation related events. Examples of the event handler methods are included later in this topic.

ConversationAdded Event

Complete the following steps within a callback method that handles ConversationAdded .

Walkthrough Steps

  1. Check the modality state of the instant message modality on the added conversation. If the modality is ModalityState . Notifiedthen conversation was not started by the local user. For this walkthrough, you handle the event for only the conversation added by the local user.

    Tip Tip

    The ConversationAdded event is raised when either a local user starts a conversation or a remote user invites the local user to a new conversation.

  2. Register for conversation state change events on the Conversation instance.

  3. Call the CanInvoke method and pass ConversationAction . AddParticipant. Continue walkthrough steps if a truevalue is returned.

  4. If you can add a participant, get a Contact instance to add to the conversation by calling into GetContactByUri . A contact that resolves to the passed Uri is returned.

  5. Get the instant messaging Modality instance from the Modalities property of the Conversation instance in the dataparameter of the ConversationAdded event handler: data.Conversation.Modalities[ModalityTypes.InstantMessagingModality]

ParticipantAdded Event

Complete the following steps within a callback method that handles ParticipantAdded .

Walkthrough Steps

  1. Read the IsSelf property of the added participant exposed by Participant property. The following steps should not be executed for the self-participant.

  2. Get the remote participant InstantMessageModality from Participant by reading the Modalities property collection and returning the InstantMessageModality .

    Tip Tip

    The instant messaging modality is auto-accepted at both the local and remote endpoints. You do not need to call Connecton this modality. The instant messaging modality is ready to use when you obtain it from the conversation's modalities collection.

  3. Cast the Modalityclass instance to the InstantMessageModality class to obtain instant messaging receive features.

  4. Register for InstantMessageReceived message received events to catch incoming instant messages from other participants.

  5. Register for participant events on the remote participant.

Send and Receive Messages

As the previous figure illustrates, the walkthrough steps to send an IM message involve many more steps than those you execute to receive and render an instant message from a remote participant. In both cases, you use the InstantMessageContentType enumeration to either set the message format of a message you send or determine the message format of a message you receive. A sent or received message is encapsulated in a generic IDictionarythat uses an enumerator of InstantMessageContentType as the key and a formatted message string as the value of the dictionary entry.

Send a Message

Sending an instant message involves setting the local user's composing state to typing, capturing and sending text, and setting the user's composing state to idle again. These actions are performed in this sequence and each depends on the completion of the previous step. You should use the System.AsyncCallbackmethod you define for each operation to initiate the next operation in the sequence.

  1. Verify the conversation is active and the conversation instant messaging modality is connected.

  2. When the local user begins to type in the form entry control designated to accept message text, call into CanInvoke , passing ModalityAction . SetIsTyping. If you cannot set this property, skip the next step.

  3. Call BeginSetComposing on the conversation instant messaging modality. Pass trueas the first argument.

  4. In the callback invoked by the previous step or upon completion of typing in the form control, instantiate an instance of IDictionary<InstantMessageContentType, string>and add an entry containing a key as enumerator for the message text formatting and value as message text.

  5. Call BeginSendMessage and pass your message dictionary as the first argument. Be sure to pass a System.AsyncCallbackmethod in the second argument.

  6. In the callback invoked after the previous step:

    1. Call EndSendMessage . You must surround this call with a try/catch block, catching the LyncClientException . A remote contact can change their availability to DND or offline at any time. Such an availability change causes this exception to be raised when your message cannot be delivered to the remote contact.

    2. Call BeginSetComposing on the conversation instant messaging modality. Pass falseas the first argument.

Receive a Message

The following walkthrough handles the InstantMessageReceived event by getting the message text formatting enumerator for the incoming message and parsing the message text according to the specified formatting.

  1. Get the message contents as IDictionary<InstantMessageContentType,string>by reading Contents .

  2. A single message may contain text in multiple formats. For each format sent, an entry exists in the dictionary you get from the previous step. Iterate on the dictionary items and assemble a display string based on the format and contents of the dictionary.

  3. Display the resulting string.

Examples

The walkthrough assumes you have created a Windows.Forms object and populated it with a TextBoxcontrol for user entry.

Start a Conversation

The following example creates a new conversation by calling into AddConversation on ConversationManager .

C#  Copy imageCopy Code
		private string myRemoteParticipantUri;
		private Conversation _Conversation;

		//assume example has obtained and signed in to this
LyncClient instance.
		private LyncClient _LyncClient;
		public void StartIMConversation(string participantUri)
		{
			_LyncClient.ConversationManager.ConversationAdded +=
ConversationsManager_ConversationAdded;
			myRemoteParticipantUri = participantUri;
			_Conversation =
_LyncClient.ConversationManager.AddConversation();
	}

Register for Conversation Events

The following example registers for Conversation events. The Conversation obtained from Conversation is a reference to the new conversation. You can register for events on the Conversationusing the Conversation instance.

C#  Copy imageCopy Code
	 
		/// Handles ConversationAdded state change event raised on
ConversationsManager
		/// <param name="source">ConversationsManager: The
source of the event</param>
		/// <param name="data">ConversationsManagerEventArgs
The event data. The incoming Conversation is obtained
here</param>
		void ConversationsManager_ConversationAdded(Object source,
ConversationManagerEventArgs data)
		{
			// Register for Conversation state changed events.
			data.Conversation.ParticipantAdded +=
Conversation_ParticipantAdded;
			data.Conversation.StateChanged +=
Conversation_ConversationChangedEvent;

			// Add a remote participant.
			data.Conversation.
AddParticipant(_LyncClient.ContactManager.GetContactByUri(this.myRemoteParticipantUri));

	}

ParticipantAdded Event

The following example handles the ParticipantAdded event. The example event handler gets the instant messaging modality from the modality collection on the new participant and registers for messages received from the participant. InstantMessageReceived is raised on any participant when that participant sends a message.

C#  Copy imageCopy Code
		/// <summary>
		/// ParticipantAdded callback handles ParticpantAdded event
raised by Conversation
		/// </summary>
		/// <param name="source">Conversation Source
conversation.</param>
		/// <param name="data">ParticpantCollectionEventArgs
Event data</param>
		void Conversation_ParticipantAdded(Object source,
ParticipantCollectionChangedEventArgs data)
		{
		
			if (data.Participant.IsSelf == false)
			{
				if
(((Conversation)source).Modalities.ContainsKey(ModalityTypes.InstantMessage))
				{
				 
data.Participant.Modalities[ModalityTypes.InstantMessage].InstantMessageReceived
+= myInstantMessageModality_MessageReceived;
				 
data.Participant.Modalities[ModalityTypes.InstantMessage].IsTypingChanged
+= myInstantMessageModality_ComposingChanged;

		}
	}

User starts typing

A user's cursor has entered a text entry control and the example sets the IsTyping property to true.

Important note Important

The conversationinstant message modality must be used to set the typing property for the local user rather than the instant message modality of the local participant.

  Copy imageCopy Code
		private void txtMessage_Enter(object sender, EventArgs e)
		{
			if
((InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage].CanInvoke(ModalityAction.SetIsTyping))
			{
			 
(InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage].BeginSetComposing(true,
ComposingCallback, null);
		}
	}

User completes typing.

A user's cursor has left a text entry control and the example sets the IsTyping property to false.

Important note Important

The conversationinstant message modality must be used to set the typing property for the local user rather than the instant message modality of the local participant.

  Copy imageCopy Code
		private void txtMessage_Leave(object sender, EventArgs e)
		{
			if
((InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage].CanInvoke(ModalityAction.SetIsTyping))
			{
			 
(InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage].BeginSetComposing(false,
ComposingCallback, null);
		}
	}

Send a Message in Plain Text

The following example sends the text content of a user interface text box to a remote conversation participant.

Important note Important

The conversationinstant message modality must be used to send an instant message to other users instead of the local participant's instant message modality.

C#  Copy imageCopy Code
		private void SendMessage(string messageToSend)
		{
			try
			{
				IDictionary<InstantMessageContentType,
string> textMessage = new
Dictionary<InstantMessageContentType, string>();
			 
textMessage.Add(InstantMessageContentType.PlainText,
messageToSend);
				if
(((InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage]).CanInvoke(ModalityAction.SendInstantMessage))
				{
				 
_Conversation.Modalities[ModalityTypes.InstantMessage].BeginSendMessage(
						textMessage
						, SendMessageCallback
						, textMessage);
			}
		}
			catch (LyncPlatformException e)
			{
				MessageBox.Show("Client Platform Exception: " +
e.Message, "Send Message");
		}
	}

SendMessage Callback

The following example callback method is invoked by InstantMessageModality after BeginSendMessage is complete. Verify asynchronous operation results here if you want to see if the message was sent successfully.

C#  Copy imageCopy Code
		/// <summary>
		/// Async callback method invoked by InstantMessageModality
instance when SendMessage completes
		/// </summary>
		/// <param name="_asyncOperation">IAsyncResult The
operation result</param>
		/// 
		private void SendMessageCallback( IAsyncResult ar)
		{
		 
(InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage].BeginSetComposing(false,
ComposingCallback, null);
			if (ar.IsCompleted == true)
			{


				try
				{
				
((InstantMessageModality)_Conversation.Modalities[ModalityTypes.InstantMessage].EndSendMessage(ar);
			}
				catch (LyncClientException lce)
				{
					MessageBox.Show("Lync Client Exception on
EndSendMessage " + lce.Message);
			}

		}
	}

ComposingChanged Event

The following example handles the event raised when a participant starts or stops typing.

C#  Copy imageCopy Code
		void myInstantMessageModality_ComposingChanged(object
source, IsTypingChangedEventArgs data)
		{
			if (data.IsTyping == true
			{
			 
MessageBox.Show(((InstantMessageModality)source).Participant.Contact.GetContactInformation(ContactInformationType.DisplayName)
+ " is typing");
		}
	}

InstantMessageModality MessageReceived Event

The following example handles the InstantMessageReceived . This example uses the PlainTextenumerator. If this enumerator is used, message content is rendered as plain text regardless of how it was formatted by the sender. If the incoming message contains data that cannot be rendered as plain text, the data is not rendered.

C#  Copy imageCopy Code
		/// <summary>
		/// Callback is invoked when IM Modality state changes upon
receipt of message
		/// </summary>
		/// <param name="source">InstantMessageModality
Modality </param>
		/// <param name="data">SendMessageEventArgs The new
message.</param>
		void myInstantMessageModality_MessageReceived(Object
source, MessageSentEventArgs data)
		{
			IDictionary<InstantMessageContentType,string>
messageFormatProperty = data.Contents;
			if
(messageFormatProperty.ContainsKey(InstantMessageContentType.PlainText))
			{
				string outVal = string.Empty;
				string Sender =
(string)((InstantMessageModality)source).Participant.Contact.GetContactInformation(ContactInformationType.DisplayName);
				if
(messageFormatProperty.TryGetValue(InstantMessageContentType.PlainText,
out outVal))
				{
					//outVal will be an empty string if the
received message contains only an image.
					MessageBox.Show("New message: " + outVal);
					//invoke delegate that sets text property of a
form browser control with outVal
			}
		}
	}

See Also

Concepts

Other Resources

Handle Events for a Modality