use*_*575 1 c# pinvoke winapi keyboard-hook
我使用的是Windows 8.我尝试使用c#禁用Windows Key,例如http://tamas.io/c-disable-ctrl-alt-del-alt-tab-alt-f4-start-menu-and-so-on/.它没有错误,但Windows键未被禁用.如何用C#禁用Windows Key?
这是我的代码.
namespace TestDisable
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, int hMod, int dwThreadId);
[DllImport("user32", EntryPoint = "UnhookWindowsHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int UnhookWindowsHookEx(int hHook);
public delegate int LowLevelKeyboardProcDelegate(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
[DllImport("user32", EntryPoint = "CallNextHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int CallNextHookEx(int hHook, int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
public const int WH_KEYBOARD_LL = 13;
/*code needed to disable start menu*/
[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);
private const int SW_HIDE = 0;
private const int SW_SHOW = 1;
public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public static int intLLKey;
public int LowLevelKeyboardProc(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam)
{
bool blnEat = false;
try
{
switch (wParam)
{
case 256:
case 257:
case 260:
case 261:
//Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key,
blnEat = ((lParam.vkCode == 9) && (lParam.flags == 32)) // alt+tab
| ((lParam.vkCode == 27) && (lParam.flags == 32)) // alt+esc
| ((lParam.vkCode == 27) && (lParam.flags == 0)) // ctrl+esc
| ((lParam.vkCode == 91) && (lParam.flags == 1)) // left winkey
| ((lParam.vkCode == 92) && (lParam.flags == 1))
| ((lParam.vkCode == 73) && (lParam.flags == 0));
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
if (blnEat == true)
{
return 1;
}
else
{
return CallNextHookEx(0, nCode, wParam, ref lParam);
}
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button1_Click(object sender, EventArgs e)
{
try
{
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您没有执行任何错误检查.在编辑中,您添加代码以捕获Win32函数引发的异常.但Win32函数不会引发异常.相反,他们通过返回值来传达成功与失败.
在这种情况下intLLKey返回为0.这表明失败.挂钩未设置.让我们添加一些错误检查:
intLLKey = SetWindowsHookEx(...);
if (intLLKey == 0)
throw new Win32Exception();
Run Code Online (Sandbox Code Playgroud)
现在,您将看到文本引发的异常:
指定的模块无法找到.
这是ERROR_MOD_NOT_FOUND.大概是因为你提供的模块句柄不被识别为与你传递的钩子proc函数指针相关联.这是托管程序集的常见问题,其中interop委托是在运行时动态创建的.
这是一种可能的解决方案.首先,修复你的p/invoke声明:
public delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32", EntryPoint = "UnhookWindowsHookEx", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32", EntryPoint = "CallNextHookEx", SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
Run Code Online (Sandbox Code Playgroud)
然后获取模块句柄并调用SetWindowsHookEx如下:
using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
{
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(curModule.ModuleName), 0);
}
if (intLLKey.ToInt64() == 0)
{
throw new Win32Exception();
}
Run Code Online (Sandbox Code Playgroud)
由于我所做的所有类型更改,您还必须修复大量编译错误,主要与使用IntPtr指针大小的句柄值有关.就是这样HHOOK.intLLKey你打电话时也必须通过CallNextHookEx.通过这些更改,您的代码会挂钩键盘事件.这些方面的东西:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32", EntryPoint = "UnhookWindowsHookEx", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32", EntryPoint = "CallNextHookEx", SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
public const int WH_KEYBOARD_LL = 13;
/*code needed to disable start menu*/
[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);
private const int SW_HIDE = 0;
private const int SW_SHOW = 1;
public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public static IntPtr intLLKey;
public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
{
bool blnEat = false;
try
{
switch (wParam.ToInt64())
{
case 256:
case 257:
case 260:
case 261:
//Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key,
blnEat = ((lParam.vkCode == 9) && (lParam.flags == 32)) // alt+tab
| ((lParam.vkCode == 27) && (lParam.flags == 32)) // alt+esc
| ((lParam.vkCode == 27) && (lParam.flags == 0)) // ctrl+esc
| ((lParam.vkCode == 91) && (lParam.flags == 1)) // left winkey
| ((lParam.vkCode == 92) && (lParam.flags == 1))
| ((lParam.vkCode == 73) && (lParam.flags == 0));
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
if (blnEat == true)
{
return (IntPtr)1;
}
else
{
return CallNextHookEx(intLLKey, nCode, wParam, ref lParam);
}
}
private void button1_Click(object sender, EventArgs e)
{
using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
{
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(curModule.ModuleName), 0);
}
if (intLLKey.ToInt64() == 0)
{
throw new Win32Exception();
}
}
}
Run Code Online (Sandbox Code Playgroud)
故事的道德启示?检查错误.
| 归档时间: |
|
| 查看次数: |
2314 次 |
| 最近记录: |