如何制作单个实例表单(不是应用程序)?

时间:2010-06-21 19:30:22

标签: c# winforms modal-dialog

在我的C#应用​​程序中,我有一个可以从菜单命令打开的选项对话框。

我想确保选项对话框只有一个实例(用户无法在给定时间打开多个选项窗口)而不进行模态化。

此外,如果用户已经打开了此窗口,并且他在菜单项中单击以再次打开它,则应用程序只会使已经可见的表单成为最顶层的窗口。

有人能指出我如何完成这些任务的方向吗?

非常感谢。

8 个答案:

答案 0 :(得分:18)

嗯,最简单的方法是使用一个静态字段来存储对单个实例的引用或null,然后是一个检索它或创建一个新方法的方法。

请注意,此不是与使其成为单例相同 - 因为我假设表单已关闭,您希望下次创建新实例。 (替代方案 - 隐藏它并重复使用 - 在STO的回答中显示。)你可能想要这样的东西:

public class OptionsDialog : Form
{
    private static OptionsDialog openForm = null;

    // No need for locking - you'll be doing all this on the UI thread...
    public static OptionsDialog GetInstance() 
    {
        if (openForm == null)
        {
            openForm = new OptionsDialog();
            openForm.FormClosed += delegate { openForm = null; };
        }
        return openForm;
    }
}

当然,你也可以让方法执行“把它带到前面”的步骤。

答案 1 :(得分:10)

您需要阻止表单关闭。如果不这样做,表格将被处理并变得无法使用。您可以通过实现FormClosing事件来执行此操作:

    protected override void OnFormClosing(FormClosingEventArgs e) {
        if (e.CloseReason == CloseReason.UserClosing) {
            this.Hide();
            e.Cancel = true;
        }
    }

要使其成为单身人士,只需跟踪主表单类中表单的生命周期:

    frmOptions options;

    private void btnShowOptions_Click(object sender, EventArgs e) {
        if (options == null) {
            options = new frmOptions();
            // To make absolutely sure:
            options.FormClosed += (o, ea) => options = null;
        }
        else {
            options.WindowState = FormWindowState.Normal;
        }
        options.Show();
    }

答案 2 :(得分:6)

您需要此表单作为属性

Form1 myForm = null;
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    myForm = null;
}

private void ShowForm()
{
    if (myForm != null)
    {
        myForm.BringToFront();
    }
    else
    {
        myForm = new Form1;
        myForm.Show();
    }
}

答案 3 :(得分:2)

您可以使用以下代码:

private MyDialogForm _FormInstance;

public void ShowOptions()
{
     if (_FormInstance == null)
     {
        _FormInstance = new MyDialogForm();
        _FormInstance.FormClosing += (s,e) => 
        {
             e.Cancel = true;
             _FormInstance.Hide();
        }
      }
     _FormInstance.Show();
}

答案 4 :(得分:0)

我假设你至少有两种形式。一种形式,称为frmMain,允许您打开frmOptions。在frmMain中,添加一个frmOptions类型的变量,如下所示:

public partial class frmMain : Form
{
     private frmOptions optionsInstance = null;
     ...

在打开“选项”对话框的例程中,添加以下内容:

if (optionsInstance == null || !optionsInstance.Visible)
{
     optionsInstance = new frmOptions();
     optionsInstance.Show();
}

当frmOptions关闭时,optionsInstance将不为null,这就是为什么在实例化frmOptions实例之前检查它是否可见。

如果这对您不起作用,您可以尝试使用互斥锁,但这可能有点过分。

答案 5 :(得分:0)

基于Jon Skeet's answer,我使用以下代码将表单显示为模式对话框。

        if (this.aboutForm == null)
        {
            this.aboutForm = new AboutForm();
            this.aboutForm.FormClosed += (sender2, e2) => { this.aboutForm = null; };
            this.aboutForm.ShowDialog(this);
        }
        else
        {
            this.aboutForm.Focus();
        }

我必须这样做是因为我有一个菜单项在主窗体的菜单中显示关于窗体,并在通知图标的上下文菜单中显示。如果我使用主窗体的菜单打开About窗体,我仍然可以使用notify图标的上下文菜单项打开另一个实例。

答案 6 :(得分:0)

    Main_Frm _main_Frm = null;

    private void Show_bt_Click(object sender, EventArgs e)
    {

        if (_main_Frm != null)
        {
            _main_Frm .BringToFront();
        }
        else
        {
            _main_Frm = new Comission_Frm();
            _main_Frm .Show();
        }

         //This condition used when you closed the form the form will disposed and when you reopen.
        if (_main_Frm .IsDisposed)
        {
            _main_Frm = new _Main_Frm ();
            _main_Frm .Show();
        }
   }

答案 7 :(得分:0)

这可能有帮助! 注意:以下代码摘自以下文章: https://www.dotnetcurry.com/ShowArticle.aspx?ID=150

static class Program
    {
        ///<summary>
        /// The main entry point for the application.
        ///</summary>
        [STAThread]
        static void Main()
        {
            bool instanceCountOne = false;

            using (Mutex mtex = new Mutex(true, "MyRunningApp", out instanceCountOne))
            {
                if (instanceCountOne)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                    mtex.ReleaseMutex();
                }
                else
                {
                    MessageBox.Show("An application instance is already running");
                }
            }
        }
    }