读书人

兑现winform定时锁定功能

发布时间: 2013-04-02 12:35:26 作者: rapoo

实现winform定时锁定功能
简单来说,我有个程序,用到两个form,mainform点击可以产生subform,两个form上都有textbox之类的控件。
现在要检测在这个程序中鼠标和键盘没有操作的时间达到1分钟的时候锁定这个程序(弹出另一个form以实现锁定功能)。
现在的问题在于
1.两个form在最前的时候移动鼠标或按下键盘
2.在两个form的控件范围内移动鼠标或使用键盘输入
这两种情况下都会重置程序的timer

如果控件和form太多,工作会很繁琐
我是新手……希望能够得到一种全局的解决方法……
[解决办法]


1.要实现锁定系统不让别人用,可以调用系统锁定API函数来实现

//引入API函数
[DllImport("user32 ")]
public static extern bool LockWorkStation();//这个是调用windows的系统锁定

在需要的时候直接写LockWorkStation();就可以啦!不信试试看!

2.API函数锁定键盘及鼠标

[DllImport("user32.dll")]
static extern void BlockInput(bool Block);

需要的时候就直接写:

BlockInput(true);//锁定鼠标及键盘
BlockInput(false);//解除键盘鼠标锁定

但是这种方式还是不能锁定ctrl+alt+delete,也就是还可以打开任务管理器,怎么办呢?

请看下面的方法:

3.屏蔽ctrl+alt+delete

FileStream fs =
new FileStream(Environment.ExpandEnvironmentVariables(
"%windir%\\system32\\taskmgr.exe"), FileMode.Open);
//byte[] Mybyte = new byte[(int)MyFs.Length];
//MyFs.Write(Mybyte, 0, (int)MyFs.Length);
//用文件流打开任务管理器应用程序而不关闭文件流就会阻止打开任务管理器
//MyFs.Close();




呵呵,大家可以自己试试看,可以在此基础上面再修改增加些其他的东西!

下面给出所有代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;

namespace 锁屏
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//引入API函数
[DllImport("user32 ")]
//这个是调用windows的系统锁定
public static extern bool LockWorkStation();
[DllImport("user32.dll")]
static extern void BlockInput(bool Block);

private void lockTaskmgr()//锁定任务管理器
{
FileStream fs =
new FileStream(Environment.ExpandEnvironmentVariables(
"%windir%\\system32\\taskmgr.exe"), FileMode.Open);
//byte[] Mybyte = new byte[(int)MyFs.Length];
//MyFs.Write(Mybyte, 0, (int)MyFs.Length);


//MyFs.Close();
//用文件流打开任务管理器应用程序而不关闭文件流就会阻止打开任务管理器
}

private void lockAll()
{
BlockInput(true);//锁定鼠标及键盘
}

private void Form1_Load(object sender, EventArgs e)
{
//this.lockAll();
this.lockTaskmgr();
}

private void btnUnlock_Click(object sender, EventArgs e)
{
if (txtPwd.Text == "19880210")
{
BlockInput(false);
Application.Exit();
}
else
{
MessageBox.Show("密码错误!", "消息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
txtPwd.Text = "";
txtPwd.Focus();
}
}
}
}



[解决办法]
这里有个土办法供参考:
1)Form中建立一个ManuResetEvent 对象_LockForm;
1) 系统运行时,启动一个单独的线程, 如下

ThreadCheckOper()
{
while(true &&! _IsColose)
{
_LockForm.Reset();

if(!_LockForm.WaitOne(1000)) //没有收到解除阻塞信号,表示没有界面操作
{
//弹出锁定窗体
}
}
}


然后重写Form的WndProc()方法,收到信号就_LockForm.Set()解除阻塞。

这样就可以简单清晰的实现你的功能。



[解决办法]
引用:
引用:

然后重写Form的WndProc()方法,收到信号就_LockForm.Set()解除阻塞。


我想知道收到信号是怎么实现的,在每个form、每个控件中的鼠标键盘事件中都添加一个_LockForm.Set()么?
有没有直接判断整个系统的鼠标键盘操作的方法?

所有的事件都是先传给WndProc(),再由form进行处理的,你可以查查鼠标及键盘的message号,判断一下就行。
------解决方案--------------------


可以自己写一个继承自Form的类,在里面加入通用的鼠标、键盘响应函数,然后让其他的WinForm继承自这个Form,可以减少代码量。
这只是个想法,希望能有所启发
[解决办法]


public partial class Form1 : Form, IMessageFilter
{
public Form1()
{
InitializeComponent();

Application.AddMessageFilter(this);
this.timer.Interval = 1000;
this.timer.Tick += delegate
{
if (Environment.TickCount - this.lastInput > 10 * 1000)
{
this.timer.Stop();
MessageBox.Show("10秒没有按键或鼠标点击");
}
};
this.timer.Start();
}

Timer timer = new Timer();
int lastInput = Environment.TickCount;
public bool PreFilterMessage(ref Message msg)
{
const int WM_LBUTTONDOWN = 0x201;
const int WM_KEYDOWN = 0x100;
switch (msg.Msg)
{
case WM_LBUTTONDOWN:
case WM_KEYDOWN:
this.lastInput = Environment.TickCount;
break;

}
return false;
}
}

[解决办法]
我是这样实现的:


首先定义一些变量
#region -程序保护

/// <summary>
/// 程序保护超时计时,默认20分钟没人操作本程序,则跳出锁定窗口
/// </summary>
private int m_nDelayProtectedFrm = 0;

/// <summary>
/// 程序保护提示,锁定窗口的对象,一个小Form窗口,可以重入密码恢复主窗口,也可以直接退出
/// </summary>
private RunProtect RunProtectFrm = null;

/// <summary>
/// 保护状态
/// </summary>


private bool m_bProtectState = false;

#endregion

第一,Form类实现消息筛选接口
public partial class Main : ImeFrm,IMessageFilter

第二,构造函数添加
Application.AddMessageFilter(this);

第四,实现消息筛选接口
/// <summary>
/// 消息拦截接口实现
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public bool PreFilterMessage(ref Message m)
{
// 我这里主要检测了是否有鼠标、键盘消息,如果没有则认为没有人操作本程序,你可以添加更多的检测
if (m.Msg == (int)Msgs.WM_KEYDOWN
[解决办法]
m.Msg == (int)Msgs.WM_MOUSEMOVE
[解决办法]
m.Msg == (int)Msgs.WM_LBUTTONDOWN
[解决办法]
m.Msg == (int)Msgs.WM_SYSKEYDOWN/*主要检测Alt+*键*/)
{
// 只要相应的动作,就不启用程序超时保护
this.m_nDelayProtectedFrm = 0;

}
return false;
}

第五,使用计时器
/// <summary>
/// 统一的计时检测,每秒一次
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TimerCtrl(object sender, EventArgs e)
{
//标志每次都累加,但是只要有人用就会被消息筛选清零的,
this.m_nDelayProtectedFrm++;
//如果指定时间内没人操作本程序,则隐藏主窗口,弹出锁定窗口,等待用户输入密码解锁
if (this.m_nDelayProtectedFrm >= CommonGenerator.DT_DelayProtectedSpace && this.RunProtectFrm == null )
{
this.SetMainFrmState(false);
this.RunProtectFrm = new RunProtect();
this.RunProtectFrm.Owner = this;


this.RunProtectFrm.ShowDialog();
this.RunProtectFrm.Dispose();
this.RunProtectFrm = null;
}
}

读书人网 >C#

热点推荐