Non-modal dialogs from Word in Outlook

B

bluenoser

Hi everyone,

I've got an Outlook 2003 (and 2002) Add-In written in C#/.NET 1.1 which
launches a Windows Form from within an Inspector. When Word is used as the
email editor, form.Show() just freezes Outlook, which must be task-killed. I
can launch the Form as a modal dialog using form.ShowDialog(), but then the
email window is unavailable and doesn't redraw itself until the Form has
closed. It also occasionally appears directly underneath the email window,
which is extremely confusing for our clients.

Can anyone tell me how to launch a Windows Form as a non-modal dialog from
within an Outlook Inspector with Word as the email editor?
 
K

Ken Slovak - [MVP - Outlook]

You'd need to make the Word window the parent of the dialog. A Word
Inspector has Word as the parent and then the parent of that is a handle to
an Outlook Explorer.

I don't know if there's some equivalent in C#, but in VB 6 I'd use the
form's Activate event to set the ZOrder of the form to 0. The equivalent can
be done using the Win32 API by calling SetForegroundWindow with the hwnd of
the dialog.
 
A

Alex

Hi Aaron,

bluenoser said:
Hi Ken,

Thanks for your reply. I've tried setting Word as the parent, but I am
unable to get a handle for the window. I've tried David Thielen's approach:

http://thielen.typepad.com/programming/2005/01/get_parent_wind.html

Unfortunately, I haven't been able to get it to work. Do you know how to get
a reference to the Word editor? Casting the Inspector parent to an
IWin32Window is invalid.

Here's what worked for me:

First, I defined a helper class for Win32 functions:

public abstract class Win32
{
private Win32() {} // static class

public static void ThrowLastError()
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

[DllImport("user32.dll")]
public static extern IntPtr GetActiveWindow();

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, int nMaxCount);
}


Then, I added a method in my dialog:

public void SetOwnerAndShow(string caption)
{
// Find window to make owner
hWndOwner = Win32.FindWindow(null, caption);
if (hWndOwner == IntPtr.Zero)
Win32.ThrowLastError();

// Set owner to found window
if (Win32.SetParent(Handle, hWndOwner) == IntPtr.Zero)
Win32.ThrowLastError();

Show();
}


Finally, I called it from my Word add-in:

// Set the owner of the dialog to the currently active Word window and display it
IntPtr hWnd = Win32.GetActiveWindow();
StringBuilder title = new StringBuilder(Win32.GetWindowTextLength(hWnd) + 1);
Win32.GetWindowText(hWnd, title, 256);

string caption = title.ToString();
myDialog.SetOwnerAndShow(caption);


This assumes that the Word window is currently active.

It seems to work OK but suggestions for improvement are always welcome.
 
B

bluenoser

Hi Alex,

Thanks, but that just gives me the same behaviour as though I had called
myDialog.Show() -- the new form appears, but is unresponsive and Outlook must
be task-killed.

Any other suggestions?

Thanks,

Aaron
 
B

bluenoser

Hi everyone,

Thanks for your help, but I used an alternate approach (launching a separate
process to open the Form) involving temporary registry keys and other nasty
things.

If this is a known problem in .NET 1.1, Microsoft should acknowledge it (and
hopefully fix it in 2.0).

Cheers,

-Aaron
 
K

Ken Slovak - [MVP - Outlook]

It's a known problem in all versions of Outlook, and indeed with all other
Office applications and not a .NET problem specifically. None of those
applications provide a hwnd property.

What you have to do in Outlook is get the caption name of the window on the
first Activate event and use that and FindWindow to locate the window you
want and from there you would get the hwnd of that window.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top