最後に、次のように実装しました。ダイアログはを使用して表示ShowDialog()
されますが、起動されます(そしてスレッドで作成されます)。ShowDialog()
独自のメッセージループを実装しているため、フォームがスレッドで起動されると、メインフォームはイベントに応答します。また、メインフォームを閉じても、子フォームは引き続きイベントに応答します。これは、ShellExtensionアプリケーションに非常に役立ちます。
スレッドとシェル拡張スレッドを解放するために、すべてをフォームに破棄することを忘れないでください(各シェル拡張ウィンドウと子はスレッドで実行されます)。
次のコードは私の問題を修正しました:
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; }
}
}