我遇到了一个类似的问题。有一个模态对话框,但在该对话框中有一个按钮“选择”,需要切换到主表单(最好不关闭模态对话框),从那里选择一些区域,然后返回到带有选择信息的模态对话框。我试图用无模式对话框/显示/隐藏来解决这个问题,并且在找不到任何好的(易于编码)解决方案之后,编写了一些有点繁琐的方法,使用Win32本地函数调用。在测试过后,它可以很好地适用于Winforms和XAML。
问题本身也不是一个容易的问题-用户按下“选择”键,然后他可能会忘记自己正在选择某些内容,并返回到相同或不同的选择对话框,这可能导致两个或多个相同对话框的实例。
我正在尝试使用静态变量(instance / parent)来解决这个问题-如果您具有纯Winforms或纯WPF技术,您可以从instance.Parent或instance.Owner中获取parent。
public partial class MeasureModalDialog : Window
{
public static MeasureModalDialog instance = null;
public static object parent = null;
static public void showDialog(object _parent)
{
parent = _parent;
if (instance == null)
{
instance = new MeasureModalDialog();
if (parent != null && parent is System.Windows.Forms.IWin32Window)
new System.Windows.Interop.WindowInteropHelper(instance).Owner = (parent as System.Windows.Forms.IWin32Window).Handle;
instance.Closed += (_sender, _e) => { instance.SwitchParentChildWindows(true); };
instance.ShowDialog();
instance = null;
parent = null;
}
else
{
instance.SwitchParentChildWindows(false);
}
}
public void SwitchParentChildWindows( bool bParentActive )
{
View3d.SwitchParentChildWindows(bParentActive, parent, this);
}
public void AreaSelected( String selectedAreaInfo )
{
if( selectedAreaInfo != null )
textAreaInfo.Text = selectedAreaInfo;
SwitchParentChildWindows(false);
}
private void buttonAreaSelect_Click(object sender, RoutedEventArgs e)
{
SwitchParentChildWindows(true);
View3d.SelectArea(AreaSelected);
}
...
public static class View3d
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowEnabled(IntPtr hWnd);
static public IntPtr getHandle( object formOrWindow )
{
System.Windows.Window window = formOrWindow as System.Windows.Window;
if( window != null )
return new System.Windows.Interop.WindowInteropHelper(window).Handle;
System.Windows.Forms.IWin32Window form = formOrWindow as System.Windows.Forms.IWin32Window;
if (form != null)
return form.Handle;
return IntPtr.Zero;
}
static public void SwitchParentChildWindows(bool bParentActive, object parent, object dlg)
{
if( parent == null || dlg == null )
return;
IntPtr hParent = getHandle(parent);
IntPtr hDlg = getHandle(dlg);
if( !bParentActive )
{
bool bEnabled = IsWindowEnabled(hParent);
View3d.EndMeasuring(true);
bool bEnabled2 = IsWindowEnabled(hParent);
if( bEnabled != bEnabled2 )
return;
}
if( bParentActive )
{
EnableWindow(hDlg, false);
ShowWindow(hDlg, 0);
}
EnableWindow(hParent, bParentActive);
if( bParentActive )
{
SetForegroundWindow(hParent);
BringWindowToTop(hParent);
} else {
ShowWindow(hDlg, 5 );
EnableWindow(hDlg, true);
SetForegroundWindow(hDlg);
}
}
...
相同的范式可能会在模态对话框中出现问题,因为每个选择函数调用链都会消耗堆栈,最终可能会导致堆栈溢出,或者您也可能会在管理父窗口状态(启用/禁用)时遇到问题。
因此,我认为这是解决问题的相当轻量级的解决方案,即使它看起来相当复杂。