0

我有一个要加载的主表单,当 20 分钟过去后,出于安全原因,我希望打开一个登录表单。我想验证正确的用户正在使用该软件,所以我考虑过使用计时器并给计时器一个 20 分钟的间隔。这是我的代码:

private void timer1_Tick_1(object sender, EventArgs e)
{
    foreach (Form f in Application.OpenForms)
    {
        if (f.Name != "login2")
        {
            login2 lss = new login2();
            lss.ShowDialog(); 
        } 
    }
}

这里的问题是它每 20 分钟打开一次表单。这意味着如果用户没有做任何事情,它只是显示一个又一个登录表单,导致出现多个登录表单,这是我不想要的。我已经使用了循环,但它仍然无法正常工作。我不知道为什么。

除此之外,我是否可以实现如果表单空闲 20 分钟然后显示登录表单并且 id 不空闲然后不显示登录表单的功能?实施起来容易吗?我不希望有任何复杂性,因为我是第一次接触 c# 的新手

4

2 回答 2

1

如果您正在寻找的是在一段时间不活动后有效地将用户从您的应用程序中注销(或至少看起来像是被注销),那么您可以 p/invokeGetLastInputInfo以满足您的要求。

在 Timer 滴答事件中,您可以使用GetLastInputInfo返回最后一次检测到任何用户输入的时间。从 Environment.TickCount 中减去它会给你不活动的时间。如果它符合您注销用户的标准,那么您可以显示您的登录表单。

[DllImport("User32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

[StructLayout(LayoutKind.Sequential)]
internal struct LASTINPUTINFO
{
    public uint cbSize;
    public uint dwTime;
}

private void timer1_Tick_1(object sender, EventArgs e)
{
    var lastInputInfo = new LASTINPUTINFO();
    lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);

    GetLastInputInfo(ref lastInputInfo);

    int inactivityThreshold = 20 * 60 * 1000;

    if ((Environment.TickCount - lastInputInfo.dwTime) > inactivityThreshold)
    {
        login2 lss = new login2();
        lss.ShowDialog(); 
    } 
}

要解决表单出现多次的问题,只需使用布尔值来指示您当前是否正在登录用户,并将其用作您是否显示登录表单的标准的一部分。

于 2013-01-13T13:42:43.957 回答
1

首先,添加一个函数来重置你的计时器:

private void ResetTimer()
{
    timer1.Stop();
    timer1.Start();
}

调用时,它将重置计时器。

其次,为避免打开多个对话框,请使用相同的实例。将该登录表单的实例添加为类成员,然后使用它而不是每次都创建新的:

login2 lss = new login2();
private void timer1_Tick(object sender, EventArgs e)
{
    if (!lss.Visible)
    {
        lss.ShowDialog();
        ResetTimer();
    }
}

如您所见,它将调用对话框,并且仅在它不可见时才调用以避免错误。它还会在用户退出对话框后重置计时器。

最后,要让它仅在“空闲”时倒计时,您需要在有任何操作时重置计时器。简单的情况是表单中每个控件的鼠标移动和按键:

this.Controls.Cast<Control>().ToList().ForEach(c =>
{
    c.MouseMove += (s1, e1) => ResetTimer();
    c.KeyPress += (s1, e1) => ResetTimer();
});

在主窗体的 Load 事件中,这将为所有控件分配事件处理程序,但如果您有嵌套控件,则必须使用递归来获取所有控件。

于 2013-01-13T13:59:33.017 回答