C# 实现电脑锁屏功能

在进行winform软件开发时,需要实现锁屏功能。本文就主要介绍此功能实现方式。

实现思路

  • 此功能分三个界面,分别是操作界面、锁屏界面、解锁界面
  • 操作员在操作界面输入锁屏密码,并启动锁屏功能。锁屏界面显示
  • 解锁时,操作员点击锁屏界面,解锁界面显示,操作员输入解锁密码,锁屏界面关闭,主画面显示

知识点

钩子机制

钩子是Windows操作系统提供的消息处理机制平台,应用程序可通过设置回调函数监视指定窗口消息,钩子可在消息到达目标窗口前捕获键盘、鼠标等输入事件,处理函数可修改消息内容或终止传递流程,可以理解为监视窗口和键盘、鼠标等动作,并根据此动作,执行其他功能,比如屏蔽键盘、记录键盘按下、窗体关闭等。实现代码如下:

csharp 复制代码
 private IntPtr pKeyboardHook = IntPtr.Zero;//键盘钩子句柄
 //钩子委托声明
 public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
 private HookProc KeyboardHookProcedure;//键盘钩子委托实例,不能省略变量
 public const int idHook = 13;//底层键盘钩子
 //安装钩子
 [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
 public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr pInstance, int threadID);
 //卸载钩子
 [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
 public static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);

 //键盘钩子处理函数
 private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
 {
     KeyMSG m = (KeyMSG)Marshal.PtrToStructure(lParam, typeof(KeyMSG));//键盘消息处理
     if (pKeyboardHook != IntPtr.Zero)//判断钩子句柄是否为空
     {
         switch (((Keys)m.vkCode))//判断按键
         {
             case Keys.LWin://键盘左侧的Win键
             case Keys.RWin://键盘右侧的Win键
             case Keys.Delete://Delete键
             case Keys.Alt://Alt键
             case Keys.Escape: //Esc键
             case Keys.F4: //F4键
             case Keys.Control://Ctrl键
             case Keys.Tab://Tab键
                 return 1;//不执行任何操作
         }
     }
     return 0;
 }
 //安装钩子方法
 public bool InsertHook()
 {
     IntPtr pIn = (IntPtr)4194304;//将4194304转换为句柄
     if (this.pKeyboardHook == IntPtr.Zero)//不存在钩子时
     {
         //创建钩子
         this.KeyboardHookProcedure = new HookProc(KeyboardHookProc);
         //使用SetWindowsHookEx函数安装钩子
         this.pKeyboardHook = SetWindowsHookEx(idHook, KeyboardHookProcedure, pIn, 0);
         if (this.pKeyboardHook == IntPtr.Zero)//如果安装钩子失败
         {
             this.UnInsertHook();//卸载钩子
             return false;
         }
     }
     return true;
 }
 //卸载钩子方法
 public bool UnInsertHook()
 {
     bool result = true;
     if (this.pKeyboardHook != IntPtr.Zero)//如果存在钩子
     {
         //使用UnhookWindowsHookEx函数卸载钩子
         result = (UnhookWindowsHookEx(this.pKeyboardHook) && result);
         this.pKeyboardHook = IntPtr.Zero;//清空指针
     }
     return result;
 }
 //键盘消息处理结构
 [StructLayout(LayoutKind.Sequential)]
 public struct KeyMSG
 {
     public int vkCode;//键盘按键
 }

泛型集合

List 本功能用到泛型集合,在锁屏功能中作用是将所有的窗体保存到集合中,然后解锁后,全部关闭,避免出现窗体未全部关闭。并且此泛型集合作为全局静态变量。

csharp 复制代码
public static List<Form> listforms = new List<Form>();//窗体集合,主要用来在锁屏及解锁时使用

Process

由于winform是基于windows系统开发的,在锁屏阶段,为避免通过热键等其他方式绕过锁屏功能,需要定时监督windows系统进程,确保在锁屏阶段,windows系统无法执行其他操作。

关于Process,本文只介绍进程的启动和关闭。详细功能可参考官方文档。

csharp 复制代码
using System;
using System.Diagnostics;

class Program
{
static void Main()
{
//启动notepad
Process process = Process.Start("notepad.exe");
System.Threading.Thread.Sleep(2000); // 等待2秒
process.Kill();//关闭notepad
}
}

Cursor

代表用于绘制鼠标指针的图像。

本文主要介绍Cursor的属性Clip:

获取或设置表示光标的剪辑矩形的边界。

csharp 复制代码
Cursor.Clip = new Rectangle(x, y, size.Width, size.Height);//设置鼠标指针的边界

作用主要是当开始解锁时,限制鼠标活动范围只在解锁界面。

size

存储一个有序整数对,用于指定 Height 和 Width。

csharp 复制代码
Cursor.Clip = new Rectangle(x, y, size.Width, size.Height);//设置鼠标指针的边界

窗体数据传送

在进行winform开发时,会需要将数据通过窗体传递,其传递机制为:

假定有窗体A和窗体B,现在需要将窗体A的数据传递给窗体B

  • 在窗体B定义公共变量,tagA和TagB
  • 在窗体A引用窗体B的两个变量,并将数据发送给这两个变量
    其实也可以加载事件。

关键代码

  • 窗体A:锁屏操作界面
csharp 复制代码
 Frm_LScreen Frm_LScreen = new Frm_LScreen();

 private void button1_Click(object sender, EventArgs e)
 {
     if(textBox2.Text.Trim()== ""||textBox3.Text.Trim() =="")
     {
         MessageBox.Show("请输入锁屏密码!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
         return;
     }
     else
     {
         if(textBox2.Text.Trim()==textBox3.Text.Trim())
         {
             Frm_LScreen.size = this.Size;//
             Frm_LScreen.x = this.Location.X;
             Frm_LScreen.y = this.Location.Y;
             Frm_LScreen.infos = textBox1.Text.Trim();
             Frm_LScreen.pwd = textBox2.Text.Trim();
             this.Hide();
             Operator.listforms.Add(Frm_LScreen);
             Frm_LScreen.ShowDialog();
         }
         else
         {
             MessageBox.Show("输入的两次密码不一致", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
             return;
         }
     }
 }

 private void button2_Click(object sender, EventArgs e)
 {
     this.Close();
 }

 private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
 {
     if(e.KeyChar==13)
     {
         button1.Focus();
     }
 }
  • 窗体2:锁屏界面
csharp 复制代码
  #region  公共变量
  public Size size;//记录窗体的大小
  public int x;
  public int y;
  public string infos;
  public string pwd;
  MyHook myHook=new MyHook ();
  #endregion

  private void Frm_LScreen_Load(object sender, EventArgs e)
  {
      label1.Location = new Point(x, y - 50);
      label1.Text = infos;
      base.Opacity = 0.5;//设置窗体透明度
      myHook.InsertHook();//安装钩子,记录输入锁屏密码
  }

  private void Frm_LScreen_MouseMove(object sender, MouseEventArgs e)
  {
      Cursor.Clip = new Rectangle(x, y, size.Width, size.Height);//设置鼠标指针的边界
  }

  private void Frm_LScreen_MouseClick(object sender, MouseEventArgs e)
  {
      Frm_UnLock frm_UnLock = new Frm_UnLock();
      frm_UnLock.x = x;
      frm_UnLock.y = y;
      frm_UnLock.infos = infos;
      frm_UnLock.pwd = pwd;
      Operator.listforms.Add(frm_UnLock);
      frm_UnLock.ShowDialog();
  }

  private void timer1_Tick(object sender, EventArgs e)
  {
      Process[] processes = Process.GetProcesses();//获取运行的所有进程名
      foreach(Process p in processes)
      {
          try
          {
              if(p.ProcessName.ToLower().Trim()=="taskmgr")
              {
                  p.Kill();//停止进程
                  Cursor.Clip = new Rectangle(x, y, size.Width, size.Height);
                  return;
              }
          }
          catch
          {
              return;
          }
      }
  }

  private void Frm_LScreen_FormClosing(object sender, FormClosingEventArgs e)
  {
      myHook.UnInsertHook();//卸载钩子,解锁屏幕
      timer1.Stop();
  }
  • 窗体3:解锁界面
csharp 复制代码
 #region  公共变量
 public int x;
 public int y;
 public string infos;
 public string pwd;
 #endregion

 private void Frm_UnLock_Load(object sender, EventArgs e)
 {
     this.TopMost = true;
     this.Location=new Point(x, y);
     label1.Text = infos;
 }

 private void button1_Click(object sender, EventArgs e)
 {
     if(textBox1.Text==pwd)
     {
         foreach(Form item in Operator.listforms)
         {
             item.Close();
             item.Dispose();
         }
         this.Close();
     }
     else
     {
         label1.Text = "密码输入错误,请重新输入";
     }
 }

 private void button2_Click(object sender, EventArgs e)
 {
     this.TopMost=false;
     this.Close();
 }
相关推荐
chilavert3181 小时前
技术演进中的开发沉思-230 Ajax:Prototype.js 重构原生 DOM
开发语言·前端·javascript
csbysj20201 小时前
SVN 标签
开发语言
2501_930707781 小时前
如何在 C# 中分离饼图的某个区域
开发语言·c#
c#上位机1 小时前
halcon图像膨胀—dilation1
图像处理·算法·c#·halcon
缺点内向1 小时前
如何在C#中添加Excel文档属性?
开发语言·数据库·c#·.net·excel
金舟软件1 小时前
电脑开机启动项的管理方法,5个方法可任意调整,可批量关闭!
windows·电脑·软件需求
Howie Zphile1 小时前
做移动端的 Next.js 项目,可以选哪些 UI?
开发语言·javascript·ui
qq_296544651 小时前
安卓手机投屏电脑端教程,手机投屏教程,可以手机和电脑互传文件。电脑管理手机文件和APP等操作
android·智能手机·电脑
无限进步_1 小时前
C语言文件操作函数解析
c语言·开发语言·数据库·c++·后端·visual studio