【问题标题】:I can't disable Windows Key with C#我无法使用 C# 禁用 Windows 键
【发布时间】:2014-03-14 10:40:10
【问题描述】:

我使用的是 Windows 8。我尝试使用 c# 禁用 Windows 键,例如 http://tamas.io/c-disable-ctrl-alt-del-alt-tab-alt-f4-start-menu-and-so-on/ 。它没有错误,但没有禁用 Windows 键。如何使用 C# 禁用 Windows 键?

这是我的代码。

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);
        }
    }
}

【问题讨论】:

  • “没有错误”。你怎么知道的?您没有检查错误。
  • 现在我将 try catch 放入 LowLevelKeyboardProc()、Form1_Load() 和 button1_Click() 中。它不显示错误。在 VC# 输出中也没有错误。但是当我按下 Winsdows 键时它仍然显示开始。
  • 您没有检查错误。 Windows API 函数不会引发异常。您是否阅读过您调用的函数的文档?专注于返回值部分。

标签: c# winapi pinvoke keyboard-hook


【解决方案1】:

您没有执行任何错误检查。在您的编辑中,您添加代码以捕获由 Win32 函数引发的异常。但 Win32 函数不会引发异常。相反,它们通过返回值来传达成功和失败。

在这种情况下,intLLKey 将作为 0 返回。这表明失败。没有设置钩子。让我们添加一些错误检查:

intLLKey = SetWindowsHookEx(...);
if (intLLKey == 0)
    throw new Win32Exception();

现在您将看到文本引发的异常:

找不到指定的模块。

这是ERROR_MOD_NOT_FOUND。大概是因为您提供的模块句柄未被识别为与您传递的钩子 proc 函数指针相关联。这是在运行时动态创建互操作委托的托管程序集的常见问题。

这是一种可能的解决方案。首先,修复你的 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);

然后获取模块句柄并像这样调用SetWindowsHookEx

using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
{
    intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(curModule.ModuleName), 0);
}
if (intLLKey.ToInt64() == 0)
{
    throw new Win32Exception();
}

由于我所做的所有类型更改,您还必须修复许多编译错误,主要与将IntPtr 用于指针大小的句柄值有关。即HHOOK。当您调用CallNextHookEx 时,您还必须传递intLLKey。通过这些更改,您的代码将挂钩键盘事件。大致如下:

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();
        }
    }
}

故事的寓意?检查错误。

【讨论】:

    猜你喜欢
    • 2010-11-15
    • 2019-01-24
    • 2011-02-05
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    相关资源
    最近更新 更多