public Form1()
{
InitializeComponent();
}
#region Other
public delegate int HookProc(int nCode, int wParam, IntPtr lParam);//委托
static int hHook = 0;//获取钩子静态变量,初始化0
public const int WH_KEYBOARD_LL = 13;//底层钩子
//LowLevel键盘截获,如果是WH_KEYBOARD=2,并不能对系统键盘截取,Acrobat Reader会在你截取之前获得键盘。
HookProc KeyBoardHookProcedure;
//键盘结构 原型
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode; //定一个虚拟键码。该代码必须有一个价值的范围1至254 。
public int scanCode; // 指定的硬件扫描码的关键。
public int flags; // 键标志
public int time; // 指定的时间戳记的这个讯息。
public int dwExtraInfo; // 指定额外信息相关的信息。
} SinnerCode.SinnerCode Sn = new SinnerCode.SinnerCode();
private string WindowsFromTitle = null;//获取拳皇窗口标题 #endregion #region API
//安装钩子 最好设置非托管约定
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
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); //用作与安装时THREADID
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId(); //进程模版
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name); //寻找目标进程窗口
[DllImport("USER32.DLL")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); //设置进程窗口到最前
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
#endregion #region 自定义事件
public void Hook_Start()
{ // 安装键盘钩子
if (hHook == 0)
{
KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
hHook = SetWindowsHookEx(WH_KEYBOARD_LL,
KeyBoardHookProcedure,
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
//Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0])是不行的,获取到的是0,会失败,这就是为什么需要定义GetModuleHandle的原因,注意的是IntPtr的特定句柄类型。
//如果设置钩子失败.
if (hHook == 0)
{
Hook_Clear();
throw new Exception("设置Hook失败!");
}
}
} //卸载键盘钩子
public void Hook_Clear()
{
bool retKeyboard = true;
if (hHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hHook);
hHook = 0;
}
//如果去掉钩子失败.
if (!retKeyboard) throw new Exception("卸载钩子失败!");
} //这里可以添加自己想要的信息处理
public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
//问题①
WinIoSys Sw_Key = new WinIoSys();//这局代码应该做全局变量,但做了之后无法调用..?因为Sw_Key.InitSuperKeys()用了之后要关闭,暂时不知道如何解决.
Sw_Key.InitSuperKeys();
KeyboardHookStruct kbh = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
if (kbh.vkCode == (int)Keys.S && (int)Control.ModifierKeys == (int)Keys.Control) // 截获Ctrl+S
{
return 1; }
if (kbh.vkCode == (int)Keys.Y
&& (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt) //截获Ctrl+Alt+Y
{ //MessageBox.Show("不能全部保存!");
return 1;
}
//以下是测试部分
if (kbh.vkCode == (int)Keys.L)
{
Sw_Key.KeyDown(WinIoSys.Key.VK_S);
Thread.Sleep(100);
Sw_Key.KeyDown(WinIoSys.Key.VK_D);
Thread.Sleep(100);
Sw_Key.KeyUp(WinIoSys.Key.VK_S);
Thread.Sleep(100);
Sw_Key.KeyUp(WinIoSys.Key.VK_D);
Thread.Sleep(10);
Sw_Key.KeyPress(WinIoSys.Key.VK_J, 200);
return 0;
} }
return CallNextHookEx(hHook, nCode, wParam, lParam);
//问题②
//程序运行后sdj三个键会输入两次,把button1代码注释,留下Hook_Start()可进任意窗口行测试.
//return CallNextHookEx(hHook, nCode, wParam, lParam);这句改为:
//return 1,会只按下L,而return0的话会执行lsdjsdj
}
#endregion private void button1_Click(object sender, EventArgs e)
{
Sn.GetProcessTitle();
for (int i = 0; i < Sn.IsProcess.Length; i++)
{
大侠们。。来吧。最后34分了解决问题2就可以了。。
解决方案 »
- 为何我的txtpassword无法显示其value值?
- 请问:如何把记录集转换为实体类,然后把实体类存放到ArrayList中?谢谢!
- 在.net2.0下调用有返回值的存储过程,如何获取其返回值?
- Enterprise Library Configuration 2.0哪里有下呀?
- 如何通过VSS管理,ASP.NET的项目开发
- 如何让VS2005把引用的程序集放到子目录中?
- Web应用问题
- error CS1567: 生成 Win32 资源时出错: 读取图标“D:\Documents and Settings\suniltg\Desktop\xp1\Windows XP Users Settings.ico”时出
- 哪儿有网络编程原理的网站?
- 谁能跟我说说DataSet,DataTable,DataRow等等关于数据的用法?
- UI线程间操作无效问题
- 没有Web站点,SL怎么加载进浏览器中去的
{
asd += 1;
if (kbh.vkCode == (int)Keys.L)
{
Sw_Key.KeyDown(WinIoSys.Key.VK_S);
Thread.Sleep(100);
Sw_Key.KeyDown(WinIoSys.Key.VK_D);
Thread.Sleep(100);
Sw_Key.KeyUp(WinIoSys.Key.VK_S);
Thread.Sleep(100);
Sw_Key.KeyUp(WinIoSys.Key.VK_D);
Thread.Sleep(10);
Sw_Key.KeyPress(WinIoSys.Key.VK_J, 200);
return 1;
}
}
else
{
asd += 1;
}
我改成了这样在记事本输出是不会出现两次了,但是在其他窗口,比如KOF拳皇。。就不会按下sdj这3个键了只有在记事本上能输出sdj。来人吧这问题我已经问了两次了
很多程序,特别是游戏,为了准求对键盘鼠标输入的快速反应,使用了IO的DX技术(就是说KOF拳皇直接到键盘的中断端口去读取输入,参见相关资料),而不是一般的程序那样(例如记事本)从操作系统的消息队列里获取。可能这个是输出不了的原因。
问题是在于我用的判断方法是不对的。屏蔽的上一个钩子应该就是按下sdj的,而后面的那个是跟复制粘贴一样。。感觉是这样。。