Domanda

I use Windows 8 . I try to disable Windows Key with c# like this example http://tamas.io/c-disable-ctrl-alt-del-alt-tab-alt-f4-start-menu-and-so-on/ . It have no error but the Windows Key was not disable. How to disable Windows Key with C# ?

This is my code.

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);
        }
    }
}
È stato utile?

Soluzione

You are not performing any error checking. In your edit you add code to catch exceptions raised by the Win32 functions. But Win32 functions do not raise exceptions. Instead they communicate success and failure through their return value.

In this case intLLKey is being returned as 0. Which indicates failure. The hook was not set. Let's add some error checking:

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

Now you will see an exception raised with the text:

The specified module could not be found.

This is ERROR_MOD_NOT_FOUND. Presumably that's because the module handle that you supplied is not recognised as being associated with the hook proc function pointer that you passed. That's a common problem with managed assemblies where interop delegates are created on the fly at runtime.

Here's one possible solution. First of all, fix your p/invoke declarations:

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

And then get the module handle and call SetWindowsHookEx like this:

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

You'll also have to fix a lot of compilation errors due to all the type changes that I made, mostly relating to the use of IntPtr for pointer sized handle values. That is, HHOOK. You must also pass intLLKey when you call CallNextHookEx. With these changes, your code hooks keyboard events. Something along these lines:

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

Moral of the story? Check for errors.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top