C# 在具有多个顶级表单的应用程序中,如何防止用户认为它由于模式对话框而被锁定?
在具有多个顶级窗口的应用程序中,带模式对话框的正常WinForms行为似乎有问题。我很好奇是否有人制定了更有效的方法。让我解释一下 情况: 当您执行dialog.ShowDialog(父窗口)时,用户单击或激活父窗口的任何尝试都会导致激活模式对话框,并将其闪烁,以便清楚地显示“您必须首先处理此问题”。太好了 如果用户点击应用程序中的另一个顶级窗口,它不会做任何事情……它不会闪烁模式对话框……它不会给你警告……它甚至不会打开模式对话框……如果你的计算机没有静音,你最多可能会听到一声蜂鸣。它唯一正确的地方是它不会激活或打开你正在点击的窗口…这至少给了用户一个线索 如果用户使用任务栏选择其他顶级窗口之一,现在它将把它带到前面!它仍然不会激活,但现在它可能完全覆盖了该模式对话框。任何与该顶级窗口交互的尝试都将失败。好像锁上了。因此,许多用户认为我们的应用程序已锁定…他们最终在任务管理器中杀死我们的应用程序并重新启动!并将其作为bug报告给我们。事实上,他们刚刚打开了一个模态对话框,需要返回到它 问题: 有没有办法点击或激活我们应用程序中的任何窗口,使模式对话框出现在前面并闪烁(就像它的父窗口现在会做的那样) 我能以某种方式成为一组窗口的父对象吗 我们考虑过让所有的模态对话框都在最上面…但是我们的一些模态对话框打开了其他窗口…一些不应该在最上面,所以管理最上面变得很复杂。此外,它与其他应用程序不友好 在具有多个顶级表单的应用程序中,如何防止用户认为它由于隐藏的模式对话框而被锁定?您可以处理表单事件,然后使用“检查是否有打开的模式表单且模式表单不是当前表单”,然后激活模式表单:C# 在具有多个顶级表单的应用程序中,如何防止用户认为它由于模式对话框而被锁定?,c#,.net,winforms,modal-dialog,topmost,C#,.net,Winforms,Modal Dialog,Topmost,在具有多个顶级窗口的应用程序中,带模式对话框的正常WinForms行为似乎有问题。我很好奇是否有人制定了更有效的方法。让我解释一下 情况: 当您执行dialog.ShowDialog(父窗口)时,用户单击或激活父窗口的任何尝试都会导致激活模式对话框,并将其闪烁,以便清楚地显示“您必须首先处理此问题”。太好了 如果用户点击应用程序中的另一个顶级窗口,它不会做任何事情……它不会闪烁模式对话框……它不会给你警告……它甚至不会打开模式对话框……如果你的计算机没有静音,你最多可能会听到一声蜂鸣。它唯一正确
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();
}
}
private void Form1\u已激活(对象发送方,事件参数e)
{
var f=Application.OpenForms.Cast(),其中(x=>x.Modal.LastOrDefault();
如果(f!=null&&f!=this)
{
如果(f.WindowState==FormWindowState.Minimized)
f、 WindowState=FormWindowState.Normal;
f、 激活();
}
}
您可以将逻辑放在基本表单中,或者在打开表单时,将此类处理程序附加到其
激活的事件。此答案受上述Reza答案的启发,但Reza的答案似乎无法处理模式对话框打开非模式表单的情况。现在,我们从基本表单的激活事件处理程序调用以下函数
/// <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;
}
//
///在OpenForms中查找justActivatedForm之后的最后一个模态表单;
///如果它找到它,那么它会激活它并返回它。否则,它将返回null。
///
///刚刚激活的表单,提示检查模态。
///返回justActivatedForm之后的最后一个模态窗体;或者,如果不存在这样的值,则为空。
公共静态表单ActivateLastModalForm(表单justActivatedForm)
{
//在justActivatedForm之后是否有模态形式?如果是,则获取最后一个模态形式。
Form lastmodel=null;
bool foundJustActivatedForm=false;
foreach(Application.OpenForms中的表单)
{
如果(foundJustActivatedForm)
{
如果(形式模态)
lastModal=形式;
}
else if(form==justActivatedForm)
{
foundJustActivatedForm=true;
}
}
//如果在justActivatedForm之后找到最后一个模态窗体,请将其激活
if(lastmodel!=null)
{
LOG.Focus(“找到模态形式,激活它…”);
如果(lastModal.WindowsState==FormWindowsState.Minimized)
lastModal.WindowsState=FormWindowsState.Normal;
lastModal.Activate();
}
返回模式;
}
如果您发现此解决方案中存在任何缺陷,请告知我们 我认为最好的办法是尽量减少显示的单独窗口和模式对话框的数量,这样就不会出现问题。谢谢!这让我找到了我刚刚发布的解决方案,它似乎运行良好。(你的代码保持原样,一些被模态对话框激活但本身不是模态的表单将被破坏…变得没有响应。)但是你的回答给了我我所缺少的关键成分。谢谢!!