Winform 單一實例運行

來源:互聯網
上載者:User
前言

  前兩天在部落格園看到《如何防止程式多次運行》,文章寫的很好,最後還留下一個問題給我們思考。關於Winform的防止多次運行,曾經也想研究過,但是後來工作上沒有需要,於是就放棄了研究,這兩天找資料,將其封裝了一下,最後實現的效果為:Winform程式運行後,再次點擊exe,會將Winform顯示出去,若該表單被其他表單遮擋,則將其前置,若該表單被最小化至托盤,將其顯示並前置。

原理  

  使用命名事件,進程在此啟動時,前一個進程會收到通知,並做出回應。

using System;using System.Collections.Generic;using System.Runtime.InteropServices;using System.Text;using System.Threading;using System.Windows.Forms;namespace Ulitiy{    /// <summary>    /// 工作列簡單封裝    /// </summary>    /// <remarks>    /// 檢查程式是否再次運行:在main方法裡調用:TaskBarUtil.CheckCreated();    /// 主表單在load事件或者構造方法初始化組件後調用:new TaskBarUtil(this, notifyIcon1);    /// </remarks>    public class TaskBarUtil    {        private Form mainForm;        private NotifyIcon notifyIcon1;        public static EventWaitHandle ProgramStarted;        public TaskBarUtil(Form main, NotifyIcon notifyIcon1)        {            this.mainForm = main;            this.notifyIcon1 = notifyIcon1;            Load();        }        [DllImport("user32.dll")]        public static extern bool SetForegroundWindow(IntPtr hWnd);        #region 右下角表徵圖控制        private void Load()        {            //註冊進程OnProgramStarted            ThreadPool.RegisterWaitForSingleObject(ProgramStarted,                (obj, timeout) => { ShowForm(); },                null, -1, false);            #region 表單事件            mainForm.SizeChanged += new EventHandler((sender, e) =>              {                  if (mainForm.WindowState == FormWindowState.Minimized)                  {                      HideForm();                  }              });            mainForm.FormClosing += new FormClosingEventHandler((sender, e) =>            {                //注意判斷關閉事件Reason來源於表單按鈕,否則用菜單退出時無法退出!                           if (e.CloseReason == CloseReason.UserClosing)                {                    mainForm.WindowState = FormWindowState.Minimized;    //使關閉時視窗向右下角縮小的效果                    notifyIcon1.Visible = true;                    e.Cancel = true;                }            });            #endregion            #region 工作列表徵圖上下文事件            ContextMenuStrip contextMenuStrip1 = new ContextMenuStrip();            //設定工作列表徵圖上下文事件            var tsmShow = new ToolStripMenuItem();            tsmShow.Name = "tsmShow";            tsmShow.Text = "顯示";            tsmShow.Click += new System.EventHandler((sender, e) =>            {                if (mainForm.Visible) return;                ShowForm();            });            var tsmExit = new ToolStripMenuItem();            tsmExit.Text = "退出";            tsmExit.Name = "tsmShow";            tsmExit.Click += new System.EventHandler((sender, e) =>            {                Application.Exit();            });            contextMenuStrip1.Items.Add(tsmShow);            contextMenuStrip1.Items.Add(tsmExit);            #endregion            #region 工作列表徵圖事件            notifyIcon1.ContextMenuStrip = contextMenuStrip1;            notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;            //notifyIcon1.Click += new EventHandler((sender, e) =>            //{            //    //ShowForm();            //});            notifyIcon1.MouseClick += new MouseEventHandler((sender, e) =>            {                if (e.Button != MouseButtons.Right)                {                    ShowForm();                }            });            #endregion        }        private void ShowForm()        {            mainForm.Visible = true; //顯示表單            if (mainForm.WindowState == FormWindowState.Minimized)                mainForm.WindowState = FormWindowState.Normal;  //恢複表單預設大小            //該屬性在設定後,再次雙擊exe,會導致表單在彈出時假死,使用form的Actived事件替代            //mainForm.ShowInTaskbar = true;            mainForm.Show();            //前置該表單            SetForegroundWindow(mainForm.Handle);        }        private void HideForm()        {            mainForm.Visible = false;   //隱藏表單            //notifyIcon1.ShowBalloonTip(3000, "提示", "雙擊恢複視窗", ToolTipIcon.Info); //出顯汽泡提示,可以不用            //mainForm.ShowInTaskbar = false; //從狀態列中隱藏            mainForm.Hide();        }        #endregion        #region 檢查是否啟動過,如果啟動則通知前一個進程,並退出當前進程        /// <summary>        /// 檢查是否啟動過,如果啟動則通知前一個進程,並退出當前進程        /// </summary>        public static void CheckCreated()        {            // 嘗試建立一個命名事件            bool createNew;            //ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, "MyStartEvent", out createNew);            ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, Application.ProductName, out createNew);            // 如果該命名事件已經存在(存在有前一個運行執行個體),則發事件通知並退出            if (!createNew)            {                TaskBarUtil.ProgramStarted.Set();                Environment.Exit(1);            }        }        #endregion    }}

  其中遇到的問題有在顯示和隱藏對表單的操作中,如果改變form的ShowInTaskbar會出問題。經過不嚴格的測試,這種發生在,在Winform運行後,多次點擊exe,在此過程中單機表單關閉,偶爾會出現無法找到控制代碼的錯誤。所以在顯示和隱藏表單的操作中,就沒有對該屬性進行操作。

  封裝類包含了如下功能:

  1、Winform 進程只能運行一個執行個體。

  2、Winform 工作列表徵圖含操作功能表,顯示和退出,並包含相應的事件。

  3. Winform 工作列表徵圖含滑鼠點擊事件,點擊即顯示表單。

  使用過程中注意: 拖入notifyicon控制項,並指定表徵圖。

  如果不需要這其中的功能,可以將類任意修改,滿足你的需要。

  樣本下載

參考文章

  Winform單一實例運行

  [C# 開發技巧]如何防止程式多次運行

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.