C# 如何在Windows窗体应用程序中触发自动注销?

C# 如何在Windows窗体应用程序中触发自动注销?,c#,winforms,C#,Winforms,我有一个Windows应用程序项目,用户可以使用其用户名和密码登录。我想这样做,当用户登录时,我将获得登录时间,如果用户在30分钟内没有使用应用程序,应用程序将再次将用户发送到登录屏幕。我怎样才能做到这一点呢?编辑:亚当是绝对正确的,我误解了这个问题,所以我删除了我原来的答案 要监视用户活动,可以创建一个自定义类,应用程序表单将从中继承。在那里,您可以订阅MouseMove和KeyDown事件(将属性设置为true),只要用户处于活动状态,就会引发这两个事件。然后,您可以创建一个,将到期时间设置

我有一个Windows应用程序项目,用户可以使用其用户名和密码登录。我想这样做,当用户登录时,我将获得登录时间,如果用户在30分钟内没有使用应用程序,应用程序将再次将用户发送到登录屏幕。我怎样才能做到这一点呢?

编辑:亚当是绝对正确的,我误解了这个问题,所以我删除了我原来的答案

要监视用户活动,可以创建一个自定义类,应用程序表单将从中继承。在那里,您可以订阅MouseMove和KeyDown事件(将属性设置为true),只要用户处于活动状态,就会引发这两个事件。然后,您可以创建一个,将到期时间设置为30分钟,并在检测到用户活动时使用Change()方法将其推迟

下面是一个示例实现:ObservedForm编写得相当通用,因此您可以更容易地看到模式

public class ObservedForm : Form
{
     public event EventHandler UserActivity;

     public ObservedForm()
     {
         KeyPreview = true;

         FormClosed += ObservedForm_FormClosed;
         MouseMove += ObservedForm_MouseMove;
         KeyDown += ObservedForm_KeyDown;
     }

     protected virtual void OnUserActivity(EventArgs e)
     {
         var ua = UserActivity;
         if(ua != null)
         {
              ua(this, e);
         }
     }

     private void ObservedForm_MouseMove(object sender, MouseEventArgs e)
     {
          OnUserActivity();
     }

     private void ObservedForm_KeyDown(object sender, KeyEventArgs e)
     {
          OnUserActivity();
     }

     private void ObservedForm_FormClosed(object sender, FormClosedEventArgs e)
     {
         FormClosed -= ObservedForm_FormClosed;
         MouseMove -= ObservedForm_MouseMove;
         KeyDown -= ObservedForm_KeyDown;
     }
}
现在,您可以订阅UserActivity事件,并执行所需的逻辑,例如:

private System.Threading.Timer timer = new Timer(_TimerTick, null, 1000 * 30 * 60, Timeout.Infinite);
private void _OnUserActivity(object sender, EventArgs e)
{
     if(timer != null)
     {
         // postpone auto-logout by 30 minutes
         timer.Change(1000 * 30 * 60, Timeout.Infinite);
     }
}

private void _TimerTick(object state)
{
    // the user has been inactive for 30 minutes; log him out
}
希望这有帮助


编辑#2:为了清晰起见,重新表述了部分解释,并将FormClosing事件的用法更改为FormClosing。

您必须为所有表单创建一个基类,该基类将拦截任何用户活动并存储上次活动时间。每次用户点击某物时,你都必须检查最后一次活动日期,并决定它是否是很久以前的

目前我不知道如何拦截,但我非常确定这是可能的(可能使用windows消息?

1.st:用户登录后,将时间戳存储在某个位置(例如,unix时间戳“1294230230”表示大约是2011年1月5日,12:24)
int sess_creation_time=now()*假设“now()”函数返回当前unix时间戳

2.nd:当用户尝试执行任何操作时,捕获此尝试的时间戳。
int temp_time=now()
现在,只需将这些值与所需的自动注销限制进行比较。 // compare here // a, temp_time - sess_creation_time => the difference, time of inactivity // 60*30 -> 60 seconds * 30 -> 30 minutes if( (temp_time - sess_creation_time) > (60*30) ) { // time of inactivity is higher than allowed, logout here logout(); } else { // session is still valid, do not forget to update its creation time sess_creation_time = now(); } //在这里比较 //a,temp_time-sess_creation_time=>差异,不活动时间 //60*30->60秒*30->30分钟 如果((临时时间-创建时间)>(60*30)) { //不活动时间高于允许的时间,请在此注销 注销(); } 其他的 { //会话仍然有效,请不要忘记更新其创建时间 sess_creation_time=now(); }

不要忘记,这不是用C/C++或C#编写的,但逻辑保持不变;-)

希望,这对您有所帮助这是解决此问题的简单方法。它工作得很好

using System;
using System.Windows.Forms;
namespace WindowsApplication1 {
    public partial class Form1 : Form, IMessageFilter {
        private Timer mTimer;
        private int mDialogCount;
        public Form1() {
            InitializeComponent();
            mTimer = new Timer();
            mTimer.Interval = 2000;
            mTimer.Tick += LogoutUser;
            mTimer.Enabled = true;
            Application.AddMessageFilter(this);
        }

        public bool PreFilterMessage(ref Message m) {
            // Monitor message for keyboard and mouse messages
            bool active = m.Msg == 0x100 || m.Msg == 0x101;  // WM_KEYDOWN/UP
            active = active || m.Msg == 0xA0 || m.Msg == 0x200;  // WM_(NC)MOUSEMOVE
            active = active || m.Msg == 0x10;  // WM_CLOSE, in case dialog closes
            if (active) {
                if (!mTimer.Enabled) label1.Text = "Wakeup";
                mTimer.Enabled = false;
                mTimer.Start();
            }
            return false;
        }

        private void LogoutUser(object sender, EventArgs e) {
            // No activity, logout user
            if (mDialogCount > 0) return;
            mTimer.Enabled = false;
            label1.Text = "Time'z up";
        }

        private void button1_Click(object sender, EventArgs e) {
            mDialogCount += 1;
            Form frm = new Form2();
            frm.ShowDialog();
            mDialogCount -= 1;
            mTimer.Start();
        }
    }
}

a怎么样?我同意科迪·格雷的观点。但从用户的角度来看,这将是非常令人讨厌的…不,我认为这是不够的,只是必须有其他东西控制用户操作键盘和鼠标操作。因为我的应用程序中有这么多表单。Form_活动事件和计时器类不足以满足此要求。一个限制是计时器忽略当前用户操作,并假设用户在超时发生之前只有一个设置窗口。超时通常是由于用户不活动造成的,在您的示例中,这是不符合要求的。@Adam:您完全正确,我没有足够仔细地阅读这个问题。请参阅我编辑的帖子。我找到了另一种解决方法。但你的方法看起来也不错。谢谢。我很想看到一个详细的解释,说明这对刚接触定制活动的人是如何起作用的。很棒的解决方案!当有活动时,为什么要禁用计时器?具体来说,
mTimer.Enabled=false
if(active)
块内部?这是一个例子,没有什么特别之处。其重新启动计时器:),我已更改逻辑。如果(激活),则禁用定时器,否则定时器启动。。当计时器勾号事件引发时,如果用户可以成功登录,则调用LoginDialog。。。像这样循环,对我来说没有任何意义。如果您正在启动计时器(调用其
Start
方法),似乎应该将计时器的
Enabled
属性设置为“true”,但是如果代码对您有效,不管怎样。如果有活动,我不想启动计时器,因为计时器勾号事件中有LoginDialog调用操作,因此必须启用false,若并没有活动,那个么定时器必须启动,然后调用LoginDialog进行登录操作并等待登录。成功了。是的,工作很好。泰·科迪·格雷嘿,这是我的密码。抄袭