控件中国网现已改版,您看到的是老版本网站的镜像,系统正在为您跳转到新网站首页,请稍候.......
中国最专业的商业控件资讯网产品咨询电话:023-67870900 023-67871946
产品咨询EMAIL:SALES@COMPONENTCN.COM

Winform 单实例运行

作者:未知 出处:cnblog 2013年07月04日 阅读:

 前两天在博客园看到《如何防止程序多次运行》,文章写的很好,最后还留下一个问题给我们思考。关于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控件,并指定图标。
 
  如果不需要这其中的功能,可以将类任意修改,满足你的需要。
 

热推产品

  • ActiveReport... 强大的.NET报表设计、浏览、打印、转换控件,可以同时用于WindowsForms谀坔攀戀Forms平台下......
  • AnyChart AnyChart使你可以创建出绚丽的交互式的Flash和HTML5的图表和仪表控件。可以用于仪表盘的创......
首页 | 新闻中心 | 产品中心 | 技术文档 | 友情连接 | 关于磐岩 | 技术支持中心 | 联系我们 | 帮助中心 Copyright-2006 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 电话:023 - 67870900 传真:023 - 67870270 产品咨询:sales@componentcn.com 渝ICP备12000264号 法律顾问:元炳律师事务所 重庆市江北区塔坪36号维丰创意绿苑A座28-5 邮编:400020
在线客服
在线客服系统
在线客服
在线客服系统