• WPF程序长时间无人操作


    在软件开发中为了安全性,特别是那些需要用到用户名和密码登录服务端的程序,常常考虑长期无人操作,程序自动跳转到用户登录界面。

    判断程序是否长时间无人操作,有两个依据,第一个是鼠标长时间不动,第二个是鼠标焦点长时间不在此程序中(即用户长时间在操作其他的程序)。

     

    一、鼠标长时间不动

    在其他博客中看到过针对鼠标长时间不动这种情况的解决方案【1】,参考此博客,将相应的代码加入到App.xaml.cs(代码如下),本文实现的是鼠标长时间不动(本例中设置10s不动)则重启该程序(因为对于需要账号密码登录的程序,鼠标长时间不动这样就能退出登录,并重新启动到登录界面,从而保证了安全性)。

    /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            private DispatcherTimer mousePositionTimer;    //长时间不操作该程序退回到登录界面的计时器
            private Point mousePosition;    //鼠标的位置
    
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);  //启动程序
                mousePosition = GetMousePoint();  //获取鼠标坐标
    
                mousePositionTimer = new DispatcherTimer();
                mousePositionTimer.Tick += new EventHandler(MousePositionTimedEvent);
                mousePositionTimer.Interval = new TimeSpan(0, 0, 10);     //每隔10秒检测一次鼠标位置是否变动
                mousePositionTimer.Start();
            }
    
            private void MousePositionTimedEvent(object sender, EventArgs e)
            {
                if (!HaveUsedTo())
                {                                    
                    mousePositionTimer.Stop();
                    //重新启动此程序
                    System.Windows.Forms.Application.Restart();
                    Application.Current.Shutdown();
                }
            }
    
            //判断鼠标是否移动
            private bool HaveUsedTo()
            {
                Point point = GetMousePoint();
                if (point == mousePosition)
                {
                    return false;
                }
                mousePosition = point;
                return true;
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            private struct MPoint
            {
                public int X;
                public int Y;
    
                public MPoint(int x, int y)
                {
                    this.X = x;
                    this.Y = y;
                }
            }
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern bool GetCursorPos(out MPoint mpt);
     
            /// 获取当前屏幕鼠标位置   
            public Point GetMousePoint()
            {
                MPoint mpt = new MPoint();
                GetCursorPos(out mpt);
                Point p = new Point(mpt.X, mpt.Y);
                return p;
            } 
        }

    但是这个解决方案有个问题,如图1所示,假设计时器的间隔时间为10s,鼠标坐标的起始点为(0,0),如果鼠标10s内不动,则到10s时计时器会执行重启程序操作。但是,当时间在1s时,我们移动了鼠标(假设移动到(0,1)),然后再次鼠标长时间不动,则当时间到10s时鼠标相比0s时刻,鼠标的坐标是变动了的,从而不会执行计时器事件,程序继续10s计时,如果接下来10s鼠标也不移动,则到达20s时计时器事件才会响应重启程序的操作。这样程序实际上是经历了19s才进行程序重启,没达到10s鼠标不动则程序重启的要求。

    图 1

    改良后的解决方案:

             经过改良,同样为了达到10s鼠标不动则程序重启的要求,我们设计了计时器的间隔时间为1s,并添加鼠标没移动的计数器,计数器达到10才执行程序重启。实现是这样的:每隔1s检测鼠标是否移动,如果不移动则计数器加1,如果中途鼠标移动,则计数器清零,要达到计数器计数为10,则要10次鼠标检测中鼠标都不移动,这样从鼠标停止移动,到计数器达到10,刚好是10s,能够达到10s鼠标不动则程序重启的要求。具体实现代码如下(注意此代码是添加在App.xaml.cs中的):

    /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            private DispatcherTimer mousePositionTimer;    //长时间不操作该程序退回到登录界面的计时器
            private Point mousePosition;    //鼠标的位置
            private int checkCount = 0;   //检测鼠标位置的次数
    
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);  //启动程序
                mousePosition = GetMousePoint();  //获取鼠标坐标
    
                mousePositionTimer = new DispatcherTimer();
                mousePositionTimer.Tick += new EventHandler(MousePositionTimedEvent);
                mousePositionTimer.Interval = new TimeSpan(0, 0, 1);     //每隔10秒检测一次鼠标位置是否变动
                mousePositionTimer.Start();
            }
    
            private void MousePositionTimedEvent(object sender, EventArgs e)
            {
                if (!HaveUsedTo())
                {
                    checkCount++;    //检测到鼠标没移动,checkCount + 1  
                    if (checkCount == 10)
                    {
                        checkCount = 0;
                        mousePositionTimer.Stop();
                        //重新启动此程序
                        System.Windows.Forms.Application.Restart();
                        Application.Current.Shutdown();
                    }
    
                }
                else
                {
                    checkCount = 0;     //检测到鼠标移动,重新计数
                }
            }
    
            //判断鼠标是否移动
            private bool HaveUsedTo()
            {
                Point point = GetMousePoint();
                if (point == mousePosition)
                {
                    return false;
                }
                mousePosition = point;
                return true;
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            private struct MPoint
            {
                public int X;
                public int Y;
    
                public MPoint(int x, int y)
                {
                    this.X = x;
                    this.Y = y;
                }
            }
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern bool GetCursorPos(out MPoint mpt);
     
            /// 获取当前屏幕鼠标位置   
            public Point GetMousePoint()
            {
                MPoint mpt = new MPoint();
                GetCursorPos(out mpt);
                Point p = new Point(mpt.X, mpt.Y);
                return p;
            } 
        }


    二、鼠标焦点长时间不在此程序中

     

    要用到Activated和Deactivated事件【2】:当Application中的一个top level窗体获得焦点时触发Activated事件,也就是应用程序被激活时。当用户从本应用程序切换到其他应用程序时触发Deactivated事件。具体代码如下:

    App.xaml中加入Activated和Deactivated事件;

    App.xaml.cs中:

    /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            private DispatcherTimer deactivatedTimer;   //当焦点不在此程序上时计时器
    
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);  //启动程序
                deactivatedTimer = new DispatcherTimer();
                deactivatedTimer.Tick += new EventHandler(deactivatedTimer_Tick);
                deactivatedTimer.Interval = new TimeSpan(0, 0, 10);   //如果焦点不在此程序中时,过10s程序自动重启
            }
    
            private void deactivatedTimer_Tick(object sender, EventArgs e)
            {
                deactivatedTimer.Stop();
                //重新启动此程序
                System.Windows.Forms.Application.Restart();
                Application.Current.Shutdown();
            }
    
            private void Application_Activated(object sender, EventArgs e)
            {
                deactivatedTimer.Stop();
            }
    
            private void Application_Deactivated(object sender, EventArgs e)
            {
                deactivatedTimer.Start();
            }
            
        }

    三、综合两种情况

    本文开始时已经提出,判断程序是否长时间无人操作有两个依据,即鼠标长时间不动和鼠标焦点长时间不在此程序中,于是本文综合了两种情况,做到了真实实现程序长时间无人操作的响应。具体代码如下:

    App.xaml 中加入 Activated和 Deactivated事件;

    App.xaml.cs中:

    /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            private DispatcherTimer mousePositionTimer;    //长时间不操作该程序退回到登录界面的计时器
            private Point mousePosition;    //鼠标的位置
            private int checkCount = 0;   //检测鼠标位置的次数
    
            private DispatcherTimer deactivatedTimer;   //当焦点不在此程序上时计时器
    
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);  //启动程序
                mousePosition = GetMousePoint();  //获取鼠标坐标
    
                mousePositionTimer = new DispatcherTimer();
                mousePositionTimer.Tick += new EventHandler(MousePositionTimedEvent);
                mousePositionTimer.Interval = new TimeSpan(0, 0, 1);     //每隔10秒检测一次鼠标位置是否变动
                mousePositionTimer.Start();
    
                deactivatedTimer = new DispatcherTimer();
                deactivatedTimer.Tick += new EventHandler(deactivatedTimer_Tick);
                deactivatedTimer.Interval = new TimeSpan(0, 0, 10);   //如果焦点不在此程序中时,过10s程序自动重启
            }
    
            private void MousePositionTimedEvent(object sender, EventArgs e)
            {
                if (!HaveUsedTo())
                {
                    checkCount++;    //检测到鼠标没移动,checkCount + 1  
                    if (checkCount == 10)
                    {
                        checkCount = 0;
                        mousePositionTimer.Stop();
                        //重新启动此程序
                        System.Windows.Forms.Application.Restart();
                        Application.Current.Shutdown();
                    }
    
                }
                else
                {
                    checkCount = 0;     //检测到鼠标移动,重新计数
                }
            }
    
            private void deactivatedTimer_Tick(object sender, EventArgs e)
            {
                deactivatedTimer.Stop();
                //重新启动此程序
                System.Windows.Forms.Application.Restart();
                Application.Current.Shutdown();
            }
    
            //鼠标焦点回到此程序
            private void Application_Activated(object sender, EventArgs e)
            {
                mousePositionTimer.Start();
                deactivatedTimer.Stop();
            }
    
            //鼠标焦点离开此程序
            private void Application_Deactivated(object sender, EventArgs e)
            {
                mousePositionTimer.Stop();
                deactivatedTimer.Start();
            }
    
            //判断鼠标是否移动
            private bool HaveUsedTo()
            {
                Point point = GetMousePoint();
                if (point == mousePosition)
                {
                    return false;
                }
                mousePosition = point;
                return true;
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            private struct MPoint
            {
                public int X;
                public int Y;
    
                public MPoint(int x, int y)
                {
                    this.X = x;
                    this.Y = y;
                }
            }
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern bool GetCursorPos(out MPoint mpt);
    
            /// 获取当前屏幕鼠标位置   
            public Point GetMousePoint()
            {
                MPoint mpt = new MPoint();
                GetCursorPos(out mpt);
                Point p = new Point(mpt.X, mpt.Y);
                return p;
            } 
    
        }


    参考:

    【1】      http://blog.csdn.net/yysyangyangyangshan/article/details/8621395

    【2】      http://www.cnblogs.com/luluping/archive/2011/05/13/2045875.html

    代码下载地址:http://download.csdn.net/detail/xiaoxiong345064855/6658825




  • 相关阅读:
    单例设计模式
    C#做窗体皮肤
    常用的数组的操作
    C#调试方法
    Timer
    程序对对象的字段的代码简写
    nginx upstream的几种配置方式
    ava如何实现系统监控、系统信息收集、sigar开源API的学习(转)
    vsftpd 被动模式与主动模式
    MySQL安装详解(V5.5 For Windows)
  • 原文地址:https://www.cnblogs.com/riasky/p/3459030.html
Copyright © 2020-2023  润新知