在具有多个 top-level 表单的应用程序中,您如何防止用户认为它由于模态对话框而被锁定?
In an app with multiple top-level forms, how do you prevent the user from thinking it locked up due to a modal dialog?
在具有多个 top-level windows 的应用程序中,模式对话框的正常 WinForms 行为似乎有问题。我很好奇是否有人开发出更有效的方法。让我解释一下……
情况:
当您执行 dialog.ShowDialog(parent) 时,用户单击或激活该 parent window 的任何尝试都会导致激活模态对话框,并且闪烁它,清楚地表明“你必须先处理这个。”太棒了
如果用户在您的应用中点击另一个 top-level windows,它不会执行任何操作……它不会闪烁模态对话框……它不会提供你一个警告......它甚至没有提出模态对话框......如果你没有将计算机静音,你可能得到的最多是哔哔声。它唯一做对的是它不会激活或提示您正在单击的 window ……这至少给了用户一个线索。
如果用户使用任务栏 select 您的另一个 top-level windows,现在它将把它带到前面!它仍然不会激活,但现在它可能会完全覆盖该模式对话框。任何与 top-level window 交互的尝试都会失败。好像锁起来了因此,许多用户认为我们的应用程序已锁定……他们最终在任务管理器中终止了我们的应用程序并重新启动!并将其作为错误报告给我们。事实上,他们刚刚打开了一个模态对话框,需要 return。
问题:
有什么方法可以在我们的应用程序中点击或激活任何 window 来使模态对话框出现在前面并闪烁(就像它的 parent window 一样)现在)?
我可以parent到一组windows吗?
我们考虑过将所有模态对话框置于最顶层……但是我们的一些模态对话框打开了其他 windows……有些不应该位于最顶层,因此管理最顶层变得很复杂。而且它对其他应用程序不友好。
在具有多个 top-level 表单的应用程序中,您如何防止用户认为它由于隐藏的模态对话框而被锁定?
您可以处理Activated
event of your forms and then using Application.OpenForms
检查是否有打开的模态窗体并且模态窗体不是当前窗体,然后激活模态窗体:
private void Form1_Activated(object sender, EventArgs e)
{
var f = Application.OpenForms.Cast<Form>().Where(x => x.Modal).LastOrDefault();
if (f != null && f != this)
{
if (f.WindowState == FormWindowState.Minimized)
f.WindowState = FormWindowState.Normal;
f.Activate();
}
}
您可以将逻辑放在基本表单中,或者在打开表单时,将此类处理程序附加到其 Activated
事件。
这个答案的灵感来自于上面 Reza 的答案,但是 Reza 的答案似乎没有处理模态对话框打开非模态窗体的情况。现在,我们从基本表单的 Activated 事件处理程序中调用以下函数。
/// <summary>
/// Looks for the last Modal Form in OpenForms that is AFTER justActivatedForm;
/// if it finds it, then it Activates it and returns it. Otherwise, it returns null.
/// </summary>
/// <param name="justActivatedForm">The Form that was just Activated, prompting this check for Modal.</param>
/// <returns>Returns the last Modal Form AFTER justActivatedForm; or null if no such exists.</returns>
public static Form ActivateLastModalForm(Form justActivatedForm)
{
// Is there a Modal Form after justActivatedForm? If so, get the last Modal Form.
Form lastModal = null;
bool foundJustActivatedForm = false;
foreach (Form form in Application.OpenForms)
{
if (foundJustActivatedForm)
{
if (form.Modal)
lastModal = form;
}
else if (form == justActivatedForm)
{
foundJustActivatedForm = true;
}
}
// If last Modal Form is found after justActivatedForm, Activate it
if (lastModal != null)
{
LOG.Focus("Found Modal Form. Activating it...");
if (lastModal.WindowState == FormWindowState.Minimized)
lastModal.WindowState = FormWindowState.Normal;
lastModal.Activate();
}
return lastModal;
}
如果您发现此解决方案有任何缺陷,请告诉我们!
在具有多个 top-level windows 的应用程序中,模式对话框的正常 WinForms 行为似乎有问题。我很好奇是否有人开发出更有效的方法。让我解释一下……
情况:
当您执行 dialog.ShowDialog(parent) 时,用户单击或激活该 parent window 的任何尝试都会导致激活模态对话框,并且闪烁它,清楚地表明“你必须先处理这个。”太棒了
如果用户在您的应用中点击另一个 top-level windows,它不会执行任何操作……它不会闪烁模态对话框……它不会提供你一个警告......它甚至没有提出模态对话框......如果你没有将计算机静音,你可能得到的最多是哔哔声。它唯一做对的是它不会激活或提示您正在单击的 window ……这至少给了用户一个线索。
如果用户使用任务栏 select 您的另一个 top-level windows,现在它将把它带到前面!它仍然不会激活,但现在它可能会完全覆盖该模式对话框。任何与 top-level window 交互的尝试都会失败。好像锁起来了因此,许多用户认为我们的应用程序已锁定……他们最终在任务管理器中终止了我们的应用程序并重新启动!并将其作为错误报告给我们。事实上,他们刚刚打开了一个模态对话框,需要 return。
问题:
有什么方法可以在我们的应用程序中点击或激活任何 window 来使模态对话框出现在前面并闪烁(就像它的 parent window 一样)现在)?
我可以parent到一组windows吗?
我们考虑过将所有模态对话框置于最顶层……但是我们的一些模态对话框打开了其他 windows……有些不应该位于最顶层,因此管理最顶层变得很复杂。而且它对其他应用程序不友好。
在具有多个 top-level 表单的应用程序中,您如何防止用户认为它由于隐藏的模态对话框而被锁定?
您可以处理Activated
event of your forms and then using Application.OpenForms
检查是否有打开的模态窗体并且模态窗体不是当前窗体,然后激活模态窗体:
private void Form1_Activated(object sender, EventArgs e)
{
var f = Application.OpenForms.Cast<Form>().Where(x => x.Modal).LastOrDefault();
if (f != null && f != this)
{
if (f.WindowState == FormWindowState.Minimized)
f.WindowState = FormWindowState.Normal;
f.Activate();
}
}
您可以将逻辑放在基本表单中,或者在打开表单时,将此类处理程序附加到其 Activated
事件。
这个答案的灵感来自于上面 Reza 的答案,但是 Reza 的答案似乎没有处理模态对话框打开非模态窗体的情况。现在,我们从基本表单的 Activated 事件处理程序中调用以下函数。
/// <summary>
/// Looks for the last Modal Form in OpenForms that is AFTER justActivatedForm;
/// if it finds it, then it Activates it and returns it. Otherwise, it returns null.
/// </summary>
/// <param name="justActivatedForm">The Form that was just Activated, prompting this check for Modal.</param>
/// <returns>Returns the last Modal Form AFTER justActivatedForm; or null if no such exists.</returns>
public static Form ActivateLastModalForm(Form justActivatedForm)
{
// Is there a Modal Form after justActivatedForm? If so, get the last Modal Form.
Form lastModal = null;
bool foundJustActivatedForm = false;
foreach (Form form in Application.OpenForms)
{
if (foundJustActivatedForm)
{
if (form.Modal)
lastModal = form;
}
else if (form == justActivatedForm)
{
foundJustActivatedForm = true;
}
}
// If last Modal Form is found after justActivatedForm, Activate it
if (lastModal != null)
{
LOG.Focus("Found Modal Form. Activating it...");
if (lastModal.WindowState == FormWindowState.Minimized)
lastModal.WindowState = FormWindowState.Normal;
lastModal.Activate();
}
return lastModal;
}
如果您发现此解决方案有任何缺陷,请告诉我们!