When should you use AddinExpress.MSO.ADXAddinModule.SendMessage(int, System.IntPtr, System.IntPtr)?

Add-in Express™ Support Service
That's what is more important than anything else

When should you use AddinExpress.MSO.ADXAddinModule.SendMessage(int, System.IntPtr, System.IntPtr)?
 
Paul Cross


Guest


Hi,

The documentation appears to be a little light on the usage scenarios of the above method. Please can you provide some insight?

Thanks,
Paul
Posted 02 Mar, 2010 03:47:44 Top
Andrei Smolin


Add-in Express team


Posts: 18793
Joined: 2006-05-11
Hi Paul,

We give a sample code in the class reference, see {Add-in Express}\Docs\Add-in Express 2009 for .NET.chm.

Also see http://www.add-in-express.com/docs/net-office-tips.php#wait-a-little.

SendMessage + OnSendMessage constitute sort of smart timer, the event of which occurs when the host application is able to process it. Also, OnSendMessage always occurs in the main thread only and you can use this fact to make calls to the Outlook Object model from a thread (all Office applications are not thread-safe).


Andrei Smolin
Add-in Express Team Leader
Posted 02 Mar, 2010 04:00:41 Top
Paul Cross


Guest


Thanks for the prompt reply.

A few more questions though I'm afraid...

What's the best way to determine if a particular method/property/event is running on Outlook's main thread?

What is the recommended way to pass data with SendMessage? I've seen a sample which simply stores "parameters" as instance/static data, but I'm concerned that other events may overwrite this prior to to OnSendMessage being called. Would it be better to create a custom structure and marshal it through the LParam or WParam arguments?

Does this make sense?

Paul
Posted 03 Mar, 2010 02:09:28 Top
Sergey Grischenko


Add-in Express team


Posts: 7233
Joined: 2004-07-05
Hi Paul.

You can use the AppDomain.GetCurrentThreadId method to determine the current thread.
And you can use the LParam or WParam arguments to pass custom structures with the this.SendMessage method.
Posted 03 Mar, 2010 11:24:14 Top
Paul Cross


Guest


Hi Sergey,

BTW AppDomain.GetCurrentThreadId is deprecated ...

I've come up with an alternative mechanism to achieve the same result. Perhaps you could review the code below and let me know if it will work...

// Keep a reference for the duration of the Add-in's lifetime
internal static MainThread MainThread { get; private set; }

// Initialize our MainThread wrapper
private void OnAddinInitialize(object sender, EventArgs e)
{
MainThread = new MainThread();
}

internal class MainThread
{
private static readonly SynchronizationContext SynchronizationContext;
static MainThread()
{
Application.DoEvents();
if (SynchronizationContext.Current != null)
{
SynchronizationContext = SynchronizationContext.Current;
}
}

internal static void ExecuteOnMainThread(SendOrPostCallback callback, object state)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
SynchronizationContext context = SynchronizationContext;
if (context != null)
{
context.Send(callback, state);
}
}
}

The usage pattern is then similar to this...

private void OnNewMail(object sender, ADXMAPINewMailNotificationEventArgs e)
{
MainThread.ExecuteOnMainThread(OnNewMail, e);
}

private static void OnNewMail(object state)
{
ADXMAPIObjectNotificationEventArgs e = state as ADXMAPIObjectNotificationEventArgs;
if (e == null)
{
return;
}
////
// DO STUFF
////
}

Thoughts?
Posted 04 Mar, 2010 06:55:30 Top
Sergey Grischenko


Add-in Express team


Posts: 7233
Joined: 2004-07-05
Hi Paul.

Thanks for the code. I would just use the connective of SendMessage + OnSendMessage and pass the data with the LParam or WParam arguments.
Posted 04 Mar, 2010 10:21:48 Top
Paul Cross


Guest


But doesn't my mechanism enable me to pass complex types as arguments? I don't want the marshaling headache
Posted 04 Mar, 2010 11:19:36 Top
Robert Mondavi




Posts: 30
Joined: 2009-08-20
Paul, regarding your question regarding how to determine if your code is running in outlook's main thread, we use the InvokeRequired method of the Windows.Forms.Control class. The property evaluated to True if the calling code is running in the same thread than the one that created the Control itself.

Bob
Posted 04 Mar, 2010 14:49:54 Top
Paul Cross


Guest


Thanks for the tip Bob. Unfortunately, I'm not running in the context of a Control...
Posted 05 Mar, 2010 06:18:50 Top
Sergey Grischenko


Add-in Express team


Posts: 7233
Joined: 2004-07-05
Hi Paul.

I don't want the marshaling headache

What do you mean? Your code works in Outlook process. You don't need to marshal any types. You can allocate a memory buffer using the Marshal class and load your data into the buffer. Then you can pass the address of the buffer in the SendMessage method.
Posted 05 Mar, 2010 08:08:19 Top