c#做一个锁屏软件

来源:互联网 发布:windows下方删工具栏 编辑:程序博客网 时间:2024/06/10 07:01

本文档于2015年4月13日更新,请读过本文以前版本的读者再看一下:

(重要更新)

锁屏软件是大多程序员(c#不应该叫程序员,应该叫码农)开发实战的第一个程序,所以难免都会遇到困难,所以笔者在这里详细讲解。

解刨锁屏软件

其实锁屏软件主要就是键盘钩子,限制鼠标,数据库(如果用ini,这个就可以不用)

那先来看一下键盘钩子吧

许多读者应该都知道,windows有许多快捷键,而我们不能让快捷键在锁屏时出来捣乱,所以我们需要用键盘钩子来屏蔽一些按键。

        //设置钩子
        [DllImport("user32.dll")]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadID);

        //卸载钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnHookWindowsHookEx(int idHook);

        //调用下一个钩子
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

        //返回指定模块的句柄
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

以上代码是引用的系统dll,因为.net里面好像没有提供键盘钩子,所以只能用系统的

键盘钩子核心代码:

 
#region
        HookProc KeyBoardProcedure;

        static int hHook = 0;//钩子函数的句柄

        public const int WH_KEYBOARD = 13;


        //钩子结构函数
        public struct KeyBoardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;

        }


        //安装键盘钩子
        public void HookStart()
        {
            if (hHook == 0)
            {
                //实例化一个HookProc对象
                KeyBoardProcedure = new HookProc(frmLockScreen.KeyBoardHookProc);

                //创建线程钩子
                hHook = Win32API.SetWindowsHookEx(WH_KEYBOARD, KeyBoardProcedure, Win32API.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);

                //如果设置线程钩子失败
                if (hHook == 0)
                {
                    HookClear();
                }
            }
        }

        //取消钩子
        public void HookClear()
        {
            bool rsetKeyboard = true;
            if (hHook != 0)
            {
                rsetKeyboard = Win32API.UnHookWindowsHookEx(hHook);
                hHook = 0;
            }
            if (!rsetKeyboard)
            {
                throw new Exception("取消钩子失败!");
            }
        }

        //对截获的键盘操作的处理
        public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));

                if (kbh.vkCode == 91)//截获左边WIN键
                {
                    return 1;
                }
                if (kbh.vkCode == 92)//截获右边WIN键
                {
                    return 1;
                }
                if (kbh.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control)//截获Ctrl+ESC键
                {
                    return 1;
                }
                if (kbh.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt)//截获ALT+F4
                {
                    return 1;
                }
                if (kbh.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt)//截获ALT+TAB
                {
                    return 1;
                }
                //......可以在这里做更多处理其实最主要的就是上面几个
            }

            return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam);
        }

        #endregion
//上面的代码取自我写的锁屏软件。
//但是我们需要在窗体加载前启动键盘钩子:
//HookStart();//启动Hook,截获键盘事件

//还需要把下面这句加在解决方案的文件里:

public delegate int HookProc(int nCode, int wParam, IntPtr lParam);

//这是定义委托,在这里不做详解,讲解的话够讲很久了。
//我来解析一下上面的代码,其中Win32API是引用键盘钩子的类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;</p><p>using System.Runtime.InteropServices;
using System.Drawing;</p><p>namespace LockScreen
{
    class Win32API
    {     

 #region DLL导入
        //设置钩子
        [DllImport("user32.dll")]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadID);        //卸载钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnHookWindowsHookEx(int idHook);        //调用下一个钩子
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);        //返回当前线程ID值
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();        //引入API函数,函数作用:将光标限制在矩形区域内
        [DllImport("user32")]
        public static extern long ClipCursor(out Rectangle rec);

#endregion
    }
}钩子调用完之后(就是用户输入密码,解除锁定之后),还需要卸载,所以需要调用自己写的HookClear函数,HookClear函数说白了就是检查有没有冲突,没有冲突的话就调用UnHookWindowsHookEx函数
这个Win32API类好像涉及了限制光标,外部函数等,那我就来讲一下:
限制光标是为了屏蔽那些“搞破坏”的软件,比如说酷屏,只要用户把鼠标移到它最小化的位置,它就会自动弹出来,所以我们需要限制光标
限制光这个库我们已经在Win32API类中引用了(只是引用,但没有调用,引用和调用不一样),但需要调用:
Rectangle rect = new Rectangle(pictureBox1.Left, pictureBox1.Top, pictureBox1.Width + pictureBox1.Left, pictureBox1.Height + pictureBox1.Top);
Win32API.ClipCursor(out rect);
pictureBox1本来是用来显示图片的,但我们为了方便(不再去计算需要局限在那一片范围的坐标),pictureBox1里面放用户输入信息的,(可以重叠),pictureBox1.Left,Top,Width,Height是获取PictureBox1所在的区域及大小的坐标。
Win32API类里面有一个ClipCursor函数,所以直接调用。
说起外部,笔者一下脑子都晕了,因为外部(extern)曾经令笔者头都大了,但其实很简单,真正理解了这个概念之后所有的雾水都没了
外部 extern是说明此函数已经在程序外部定义并编写了,在这里只需要声明即可。
也许你会问,哪里定义了?
[DllImport("user32")]这行代码就解决了,这行代码表示引用系统的user32库,引用之后就相当于定义了。
其实很多库系统都已经提供了,不需要再次去编写。
注意:锁屏的窗体有几个重要的属性需要设置:
Topmost:让窗体始终位于屏幕最顶端,//这个属性是为了防止其他软件干涉,如果其他软件以、一弹出来,那这个锁屏程序就相当于将没有Show一样。所以我们需要把这个属性设为True
FormClosing事件:在这个事件对应的函数里需要加一个if语句,为了避免程序在锁屏以后意外退出:如果已经输入了正确的密码,则return,如果没有,就要:e.cancel=true;   //阻止窗体关闭
还有两个很重要的地方:
1:任务管理器,对于许多没有提升至系统进程的软件,则任务管理器就是它们的终结者,锁屏软件也一样,但我们可以避免:锁屏时杀掉任务管理器
在这里,我们需要用一个Timer,每秒都执行关闭操作:
Tick函数如下:
private void KillTaskmgr_Tick(object sender, EventArgs e)
        {
            Process[] remoteAll = Process.GetProcessesByName("taskmgr");
            foreach (Process s in remoteAll)
            {
                s.Kill();     //关闭进程
            }
        }
还有,我们需要把这个Timer的刷新时间设置为100(毫秒,即0.1秒)
2:资源管理器,有了资源管理器,许多干扰锁屏程序的东西就拔地而出,
还是同上:
private void KillExplorer_Tick(object sender, EventArgs e)
        {
           FileStream FS = new FileStream("Kill_Explorer.bat", FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(FS);
            sw.WriteLine("@echo off");
            sw.WriteLine("taskkill /f /im explorer.exe");
            sw.Close();
            Process.Start(Application.StartupPath + "
\\Kill_Explorer.bat");
        }
但有的编译器编译出来后提示拒绝访问,这个就自己到网上查一下。
在用户输入密码正确以后,我们需要打开资源管理器,

直接用Process:

我的编译器编译出来是只打开一个窗口,所以这里做成批处理的形式:

FileStream FS = new FileStream("Start_Explorer.bat", FileMode.Create, FileAccess.Write);
                StreamWriter sw = new StreamWriter(FS);
                sw.WriteLine("@echo off");
                sw.WriteLine("explorer");
                sw.Close();

Process.Start(Environment.CurrentDirectory + "\\Start_Explorer.bat");

剩下的就是数据库了,数据库教程在网上有许多,在这里我就不给代码了。

谢谢大家阅读本文章。


1 0
原创粉丝点击