问题
I'm writing a Windows shell extension in C# using EZShellExtensions.NET.
I contribute a context menu that shows dialogs.
Suppose that I show an Explorer window (A). Then I use the context menu to show non modal window (B).
In Windows XP and Windows Vista, when I close A, B is closed (I want this behavior). However, in Windows 7, when I close A, B is not closed but it doesn't respond to events. My questions are:
- Do you know why Windows 7 manage the showed form as a child form?
- Is there a way to maintain the message loop if I close A?
EDIT: If I set A as owner of B, when I close A, B is also closed. But it creates a new issue. B is always over A.
回答1:
Finally I have implemented it in the following way. The dialog is shown using ShowDialog()
but is launched (and created in a thread). ShowDialog()
implements its own message loop, so as the form is launched in a thread, the main form respond to events, and also you can close the main form and the child form still respond to events. This is very useful for a ShellExtension application.
Remember dispose all on your form, in order to free the thread, and also the shell extension thread (each shell extension window and childs are executed in a thread).
The following code fixed my issue:
protected virtual void SetupViewControl()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoSetupViewControl));
while (!mViewControlCreated)
{
// wait for view control created
Thread.Sleep(100);
}
}
private bool mViewControlCreated = false;
protected virtual void DoSetupViewControl(object state)
{
mViewControl = ViewControlFactory.CreateViewControl();
mViewControl.Dock = DockStyle.Fill;
mViewControl.Initialize();
this.Controls.Clear();
this.Controls.Add(mViewControl);
IntPtr wHnd = GetActiveWindow();
IWin32Window owner = GetOwner(wHnd);
mViewControlCreated = true;
ShowDialog(owner);
this.Dispose();
}
private IWin32Window GetOwner(IntPtr wHnd)
{
if (wHnd == IntPtr.Zero) return null;
return new WindowWrapper(wHnd);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetActiveWindow();
private class WindowWrapper : IWin32Window
{
private IntPtr mHwnd;
public WindowWrapper(IntPtr handle)
{
mHwnd = handle;
}
public IntPtr Handle
{
get { return mHwnd; }
}
}
来源:https://stackoverflow.com/questions/7000532/close-child-dialogs-when-closing-the-parent