Daniel Garcia
Posts: 9
Joined: 2010-10-14
|
I'm having trouble displaying a WPF form when clicking a mail inspector button, but only when running in Outlook 2003 + MS Word as the email editor.
We have a ADXOlInspectorCommandBar with a button. Here is the "Click" handler:
Private Sub Button_Settings4_Click(ByVal sender As Object) Handles Button_Settings4.Click
Dim theDialog As MyDll.MyWPFDialog = New MyDll.MyWPFDialog()
theDialog.ShowDialog()
End Sub
This causes the exception listed below. However, if I change the settings to NOT use MS Word as the email editor, everything works prefectly. Also, the same code seems to work perfectly fine for Outlook 2007/2010, although in this case we use an ADXRibbonTab. Here is the handler:
Private Sub Button_Settings3_OnClick(ByVal sender As System.Object, ByVal control As AddinExpress.MSO.IRibbonControl, ByVal pressed As System.Boolean) Handles Button_Settings3.OnClick
Dim theDialog As MyDll.MyWPFDialog = New MyDll.MyWPFDialog()
theDialog.ShowDialog()
End Sub
Also, I am not (knowingly) doing anything with threads in MyWPFDialog. In fact, it seems the exception is thrown by the default constructor of MyWPFDialog before any of my code has a chance to run.
Am I missing something obvious? I've found these 2 posts, which seem somewhat related to my issue, but I seem to be unable to put the pieces together:
http://social.msdn.microsoft.com/forums/en-US/vsto/thread/506920bb-fd5f-43e5-9ae7-9fbfdfb6a9b0
http://social.msdn.microsoft.com/forums/en-US/vsto/thread/ef297b3c-806c-4f95-8f49-f4f97370e0a1/
Here are the exception details:
Exception Type: System.InvalidOperationException
Message: The calling thread must be STA, because many UI components require this.
Dat a: System.Collections.ListDictionaryInternal
TargetSite: Void .ctor()
HelpLink: NULL
Source: PresentationCore
StackTrace Information:
at System.Windows.Input.InputManager..ctor()
at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
at System.Windows.Input.InputManager.get_Current()
at System.Windows.Input.KeyboardNavigation..ctor()
at System.Windows.FrameworkElement.FrameworkServices..ctor()
at System.Windows.FrameworkElement.EnsureFrameworkServices()
at System.Windows.FrameworkElement..ctor()
at System.Windows.Controls.Control..ctor()
at System.Windows.Window..ctor()
at MyDll.MyWPFDialog..ctor() |
|
Eugene Astafiev
Guest
|
|
Daniel Garcia
Posts: 9
Joined: 2010-10-14
|
Hi Eugene,
Thanks, your suggestion may help (we are testing and will report back ASAP) but I hope there is a cleaner way to fix this issue because of a couple of practical requirements that I did not mention in my original post:
1) [MyDll] is being used in different contexts outside of our add-in-express plugin, so ideally we'd like to keep [MyDll] intact. Your suggestion seems to require modifying every form in [MyDll] to handle the "Closed" event to send the WM_MYMESSAGES2 message. Not fun, but we can do this if we must.
2) [MyDll] contains not only forms, but also methods like [MyDll.MyHandler.RunWizard()] which takes the user through a bunch of forms. All of that workflow is encapsulated inside [MyDll], including the creation and displaying of the necessary forms, so I'm not sure how we would apply your suggestion here?
So, basically what we need is a way to "set things up" in the add-in in a way that let's [MyDll] do whatever it wants in terms of opening/closing WPF forms internally. Do you think there is any hope of achieving this? |
|
Eugene Astafiev
Guest
|
Hi Daniel,
Note, in case of Word editor a button event handler of the inspector window is executed in another thread. Please try to use the approach implemented in the sample add-in project I posted above. Does it work for you? If not, could you please send a sample (newly created, not your complex one) add-in project which can reproduce the issue to the support e-mail address (see readme.txt for details)? |
|
Daniel Garcia
Posts: 9
Joined: 2010-10-14
|
Hi Eugene,
Thanks, your sample avoids the STA error during form creation, and I'm showing the pseudo-code below in case it helps someone else (it is based on the sample you sent).
But before that, a couple of questions about your last post:
1) Is this "event-handler-in-another-thread" something that affects all versions of Outlook? (we have only encountered it in 2003)
2) So, if I understand your last post correctly, all we need to do is to "forward" the event (via SendMessage) to the main thread and then do whatever we want from there, like calling MyDll.MyHandler.RunWizard()?
And here is the pseudo-code. Note that since we are using wpf we are dealing with the parent/owner window issue in a different manner than in your sample:
Private Const WM_USER As Integer = &H400
Private Const WM_MYMESSAGES1 As Integer = WM_USER + 1001
Private Const WM_MYMESSAGES2 As Integer = WM_USER + 1002
Private mySettingsForm As MyDll.MyWpfDialog = Nothing
Private Sub Button_Settings4_Click(ByVal sender As Object) Handles Button_Settings4.Click
Me.SendMessage(WM_MYMESSAGES1, IntPtr.Zero, IntPtr.Zero)
End Sub
Private Sub AddinModule_OnSendMessage(ByVal sender As Object, ByVal e As AddinExpress.MSO.ADXSendMessageEventArgs) Handles Me.OnSendMessage
Select Case e.Message
Case WM_MYMESSAGES1
SyncLock Me
Try
If (mySettingsForm Is Nothing) Then
mySettingsForm = New MyDll.MyWpfDialog()
Dim theInteropHelper As Windows.Interop.WindowInteropHelper = New Windows.Interop.WindowInteropHelper(mySettingsForm)
theInteropHelper.Owner = Me.NativeWindowHandle
AddHandler mySettingsForm.Closed, AddressOf mySettingsForm_Closed
End If
mySettingsForm.ShowDialog()
Catch
End Try
End SyncLock
Exit Select
Case WM_MYMESSAGES2
SyncLock Me
mySettingsForm = Nothing
End SyncLock
Exit Select
End Select
End Sub
Private Sub mySettingsForm_Closed(ByVal sender As Object, ByVal e As System.EventArgs)
Me.SendMessage(WM_MYMESSAGES2, IntPtr.Zero, IntPtr.Zero)
End Sub |
|
Eugene Astafiev
Guest
|
Hi Daniel,
1. Nope. As far as I know only Outlook 2003 uses Word as an e-mail editor.
2. Exactly! You are on the right avenue.
Good luck with your add-in project! |
|