这几天在研究C#,为什么会想学C#呢,因为在玩游戏的时候,想一键导入秘籍,嘿嘿,感觉会方便很多,比如“魔兽争霸3”,“罗马帝国3”,我原本是想用java做的,发现实现起来比较麻烦,因为java的本地编程能力不强,需要JNA来调用,所以没有用java,转而想用别的编程语言,后来想用QT,但QT配置起来也不怎么好,于是决定用C#,好了,言归正传,下面将贴上代码,会做详细的注释,主体是借鉴的别人的代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
namespace test
{
class KeyboardHookLib
{
//钩子类型:键盘
private const int WH_KEYBOARD_LL = 13;
//自己创建窗口按键
public const int WM_KEYDOWN = 0x100;
//全局系统按键
public const int WM_SYSKEYDOWN = 0x104;
//键盘处理事件委托.
private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
//客户端键盘处理事件
public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
//接收SetWindowsHookEx返回值
private static int _hHookValue = 0;
//勾子程序处理事件
private static HookHandle _KeyBoardHookProcedure;
//Hook结构
[StructLayout(LayoutKind.Sequential)]
public class HookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
//设置钩子
[DllImport("user32.dll")]
private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int
threadId);
//取消钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention =
CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
//调用下一个钩子
[DllImport("user32.dll")]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
//获取当前线程ID
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
//获取关联进程的主模块
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string name);
private IntPtr _hookWindowPtr = IntPtr.Zero;
//构造器
public KeyboardHookLib() { }
//外部调用的键盘处理事件,如果需要调用自己窗口建立的函数,则需要这行代码
//private static ProcessKeyHandle _clientMethod = null;
/// 安装勾子
//如果需要调用自己窗口建立的函数,则需要这行代码
// public void InstallHook(ProcessKeyHandle clientMethod)
//{
//如果需要调用自己窗口建立的函数,则需要这行代码
//_clientMethod = clientMethod;
/*
* _clientMethod 相当于一个发射的工具,
* 从钩子代码这儿调用到你自己窗口建立的函数那儿
* 我做的是个最简单的辅助,
* 所以不需要调用到自己的函数那儿,
* 所以就没有把创建它
*/
public void InstallHook()
{
// 安装键盘钩子
if (_hHookValue == 0)
{
//GetHookProc 是钩子内部调用的函数,当按下键盘时,
//会调用到这儿来,可以改变名字
_KeyBoardHookProcedure = new HookHandle(GetHookProc);
//得到线程
_hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
_hHookValue = SetWindowsHookEx(
WH_KEYBOARD_LL,
_KeyBoardHookProcedure,
_hookWindowPtr,
0);
//如果设置钩子失败.
if (_hHookValue == 0)
UninstallHook();
}
}
//取消钩子事件
public void UninstallHook()
{
if (_hHookValue != 0)
{
bool ret = UnhookWindowsHookEx(_hHookValue);
if (ret) _hHookValue = 0;
}
}
//钩子事件内部调用,调用_clientMethod方法转发到客户端应用。
private static int GetHookProc(int nCode, int wParam, IntPtr lParam)
{
//当nCode大于0,并且是按下事件时为1
if (nCode >= 0 && (wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN))
{
//转换结构
HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
//是否拦截按键的标识符,默认不拦截
bool handle = false;
switch ((Keys)hookStruct.vkCode)
{
//将拦截标识符置为拦截,向当前窗口发送一个回车,
//再发送greenisgood 10000,再发送一个回车
case Keys.F1: handle = true; SendKeys.Send("{ENTER}"); SendKeys.Send("greenisgood 10000"); SendKeys.Send("{ENTER}"); break;
}
/*
if (_clientMethod != null)
{
//调用客户提供的事件处理程序。
//_clientMethod(hookStruct, out handle);
//if (handle) return 1; //1:表示拦截键盘,return 退出
}
*/
if (handle) return 1;
}
return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
}
}
}
钩子管理类就OK了,那么,就只要在你自己的窗口安装钩子即可,代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace test
{
public partial class Form1 : Form
{
private KeyboardHookLib _keyboardHook = null;
//当运行程序默认安装钩子,也可以建一个按钮,手动安装
public Form1()
{
InitializeComponent();
_keyboardHook = new KeyboardHookLib();
//如果需要调用回来,安装钩子时把函数传过去
// _keyboardHook.InstallHook(this.newKeyPress);
_keyboardHook.InstallHook();
}
private void Form1_Load(object sender, EventArgs e)
{
}
// _clientMethod 便是调用到这个函数来
//private void newKeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle)
//{
//handle = true;
//Keys key = (Keys)hookStruct.vkCode;
//richTextBox1.Text += key.ToString();
// }
//窗口退出事件
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//卸载钩子
if (_keyboardHook != null) _keyboardHook.UninstallHook();
}
//右键菜单-退出事件
private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
{
//卸载钩子
if (_keyboardHook != null) _keyboardHook.UninstallHook();
Close();
}
//右键菜单
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
//还原窗体显示
WindowState = FormWindowState.Normal;
//**窗体并给予它焦点
this.Activate();
}
}
}
}
大功告成,最简单的钩子就OK了,暂时没有弄组合键,可以自己百度看一下,主体代码我也是百度的,自己研究明白了,才把代码贴在这儿的,大神勿喷,新手弄明白了点个赞,不明白的地方可以交流一下。