Modeless owned dialog prevents switching word documents

A

Alex

Hello,

Here's an interesting problem:

In my Word add-in (C#) I have a Windows Form that must always float above the currently active Word window.
I accomplished it by changing the owner of the form to be the active Word window (see implementation below).

This works but, unfortunately, after playing around a little (minimizing and restoring windows, switching applications) the system will no longer let me switch between Word windows by clicking on their icons on the Taskbar or using Alt-TAB (Alt-F6 seems to work OK). Sometimes, if I continue playing around, the form will decide to hide itself...

One way to recreate this behaviour is to open two Word documents, show the form, click on it to make it active and then start switching between the Word windows using the Taskbar.

Can anyone help me figure out what is going on?

Best wishes,
Alex.


The implementation:

// This class handles the interaction with MS-Word
class MyAddIn
{
// The floating Form
private FormMainUI mainUI;

// Hook events
public void Init(Word.Application app)
{
((Word.ApplicationEvents3_Event) app).WindowActivate +=
new Word.ApplicationEvents3_WindowActivateEventHandler(EventWindowActivate);
}

private void EventWindowActivate(Word.Document document, Word.Window window)
{
// Get the current window handle
IntPtr hWnd = Win32.GetActiveWindow();

// Verify that it's a Word window
const string wordClass = "OpusApp";
int len = wordClass.Length + 1;
StringBuilder className = new StringBuilder(len);
Win32.GetClassName(Win32.GetAncestor(hWnd, Win32.GA_ROOT), className, len);
if (className.ToString() != wordClass)
return;

// Set owner
mainUI.SetOwner(hWnd);
}
}


// The floating Form
internal class FormMainUI : System.Windows.Forms.Form
{
// Non-default settings
private void InitializeComponent()
{
// ...
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.Name = "FormMainUI";
// ...
}

// Here's the beef:
public void SetOwner(IntPtr hWnd)
{
// SetWindowLong() does not play nicely with Marshal.GetHRForLastWin32Error()
// so no error checking
Win32.SetWindowLong(this.Handle, Win32.GWL_HWNDPARENT, (int)hWnd);

// Refresh window
uint flags = Win32.SWP_NOSIZE | Win32.SWP_NOMOVE | Win32.SWP_FRAMECHANGED;
if (this.Visible)
flags |= Win32.SWP_SHOWWINDOW;
if (!this.ContainsFocus)
flags |= Win32.SWP_NOACTIVATE;
Win32.SetWindowPos(this.Handle, Win32.HWND_TOP, 0, 0, 0, 0, flags);
}
}


// P/Invoke stuff
public abstract class Win32
{
private Win32() {} // static class

[DllImport("user32.dll")]
public static extern IntPtr GetAncestor(IntPtr hwnd, uint gaFlags);

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

[DllImport("user32.dll", SetLastError = true)]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

public const uint GA_ROOT = 2;
public const int GWL_HWNDPARENT = -8;
public const uint SWP_NOSIZE = 0x0001;
public const uint SWP_NOMOVE = 0x0002;
public const uint SWP_FRAMECHANGED = 0x0020;
public const uint SWP_SHOWWINDOW = 0x0040;
public const uint SWP_NOACTIVATE = 0x0010;
public static IntPtr HWND_TOP = (IntPtr)(0);
}
 
W

Wei-Dong XU [MSFT]

Hi Alex,

Currently I am finding a support professional for you. If any update, we
will reply here at the first time.

Best Regards,
Wei-Dong XU
Microsoft Product Support Services
This posting is provided "AS IS" with no warranties, and confers no rights.
It is my pleasure to be of assistance.
 
P

Peter Huang [MSFT]

Hi Alex,

We did not recommend to use Win32 API(e.g. SetWindowLong,SetWindowPos) to
change the Word windows' relationship and behavior.
Because the Word is very complex windows application, simply call the APIs
may occur unexpected behavior.

From Whidbey, we will have VSTO 2.0 which expose simple managed interface
to including windows form control in the Task Panel which will help you get
the similar hehavior in contrast to floating form.

How to Create HTML Action Panes for Word and Excel using VSTO 2005
http://blogs.msdn.com/pstubbs/archive/2005/09/05/461130.aspx

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Alex

Hello Peter,

"Peter Huang" said:
We did not recommend to use Win32 API(e.g. SetWindowLong,SetWindowPos) to
change the Word windows' relationship and behavior.

I would prefer to stay 100% managed myself but there isn't any way of doing it.
You have recommended Win32 API solutions yourselfs when there was no other alternative.
Because the Word is very complex windows application, simply call the APIs
may occur unexpected behavior.

Nonetheless, it is imperative for us to have this functionality.
Otherwise, we may just as well scrap the project.
From Whidbey, we will have VSTO 2.0 which expose simple managed interface
to including windows form control in the Task Panel which will help you get
the similar hehavior in contrast to floating form.

This is not an option because:
1) VSTO is document-centric and we need add-in functionality (that is, available for *all* Word documents)
2) We will probably ship the product before Whidbey comes out of beta and management does not approve of beta tools.


It is very important for us to get it to work right.


Best wishes,
Alex.
 
P

Peter Huang [MSFT]

Hi

Because Word did not expose such interface for us to customize, that is why
we will introduce the Task Pane interface in vsto2.0. Because that will use
the Task Pane to serve as the modeless form to interactive with the
document. So far we use Word OM to customize the Word
application(CodeBehind, ComAddin, ISmartDocument...), the win32 windows API
will confuse the orginal word windows management. And this is a hack
behavior.

Since from your scenario, it seems that you wants the winform to be a top
level window and live across the word documents.
If so, I think you may set the winform windows as top level window, and
when you change between windows, it will just stay live.
e.g.
WindowActivate Event
visible = true
WindowDeactivate Event
visible = false

If you do want the API approach, I think you may try to contact
MCS(Microsoft Consulting Service) to see if they would provide Win32 level
Word application customization.
http://www.microsoft.com/services/microsoftservices/default.mspx



Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Alex

Hello Peter,

Peter Huang" said:
Since from your scenario, it seems that you wants the winform to be a top
level window and live across the word documents.
If so, I think you may set the winform windows as top level window, and
when you change between windows, it will just stay live.
e.g.
WindowActivate Event
visible = true
WindowDeactivate Event
visible = false

I tried this approach but it has one serious problem:

If Word pops up a modal dialog when my winform is on top, it may get obscured by the winform.
So the user cannot dismiss the dialog (because it is under the winform) and cannot move/minimize/close the winform (because a modal dialog is wating for input). We get a deadlock!

This is a serious problem!


Best wishes,
Alex.
 
P

Peter Huang [MSFT]

Hi

I think the recommended approach is to use SmartDocument or VSTO 2.0 which
is matured approach.(maybe vsto 2.0 is somewhat new product)

For your scenario, I think there is two approaches.
How did the dialog show up?
1. If it is show up by your program, you can disable the topmost
temporarily before show the modal dialog.
2. If it is show up by word, you can not control its behavior, then I think
you can try to put the form on the right, and shrink the winword' window,
just as the word's help file do to make sure the modal dialog will not be
covered.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Alex

Hello Peter,

Peter Huang" said:
I think the recommended approach is to use SmartDocument or VSTO 2.0 which
is matured approach.(maybe vsto 2.0 is somewhat new product)

Peter, I really appreciate your help. Your advice has proven invaluable and helped us immensely with our project.
However, I feel a little frustrated by the need to constantly repeat the reasons that we cannot use VSTO or smart documents in this project.
For your scenario, I think there is two approaches.
How did the dialog show up?

Word pops up dialogs when an unsaved document is closed, etc.
2. If it is show up by word, you can not control its behavior, then I think
you can try to put the form on the right, and shrink the winword' window,
just as the word's help file do to make sure the modal dialog will not be
covered.

Unfortunately, the winform must float. This is a requirement.


Thank you,
Alex.
 
P

Peter Huang [MSFT]

Hi

I think it is hard to do that, that is why we introduce Task Pane, so that
we can use an uncoverred action panel together with Word windows.
If all the approach as I suggest before is not available for you, I think
you may try to contact MSPSS to see if there is any better approach to do
the job.
Thanks!

If you still have any concern, please feel free to post here.


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Alex

Problem solved.

I now make my form owned by the window that shows the actual Word document (instead of the top level "OpusApp") and everything works fine.


Best wishes,
Alex.
 

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