.NET 3.x Исключение при блоке клавиши Win - C#
Формулировка задачи:
Вообщем понадобилось мне отключить клавишу Win (в разумных целях), так вот при нажатие первый раз блочит, при повторном, выдает исключение, и всё накрывается разом)
Сам класс:
Исключение:
Есть ли у кого нибудь рабочий пример: или же как бороться..?
using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Diagnostics; internal class WinBlock { [StructLayout(LayoutKind.Sequential)] private struct KBDLLHOOKSTRUCT { public Keys key; public int scanCode; public int flags; public int time; public IntPtr extra; } private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool UnhookWindowsHookEx(IntPtr hook); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string name); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern short GetAsyncKeyState(Keys key); private IntPtr ptrHook; private LowLevelKeyboardProc objKeyboardProcess; private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp) { if (nCode >= 0) { KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT)); if (objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.RWin) { return (IntPtr)1; } } return CallNextHookEx(ptrHook, nCode, wp, lp); } private delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, IntPtr lParam); public void SetHook() { ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule; objKeyboardProcess = new LowLevelKeyboardProc(captureKey); ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0); } public void Unhook() { if (ptrHook != IntPtr.Zero) { UnhookWindowsHookEx(ptrHook); ptrHook = IntPtr.Zero; } } }
Обнаружено событие CallbackOnCollectedDelegate Message: Был произведен обратный вызов делегата типа "WinBlock+LowLevelKeyboardProc::Invoke", полученного сборщиком мусора. Это может привести к сбоям приложения, а также к повреждению или утрате данных. При передаче делегатов в неуправляемый код управляемое приложение должно поддерживать их существование, пока не будет гарантировано, что они больше никогда не будут вызваны.
Решение задачи: «.NET 3.x Исключение при блоке клавиши Win»
textual
Листинг программы
private void button1_Click(object sender, EventArgs e) { WinBlock.SetHook(); } private void button2_Click(object sender, EventArgs e) { WinBlock.Unhook(); } internal static class WinBlock { [StructLayout(LayoutKind.Sequential)] private struct KBDLLHOOKSTRUCT { public Keys key; public int scanCode; public int flags; public int time; public IntPtr extra; } private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool UnhookWindowsHookEx(IntPtr hook); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string name); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern short GetAsyncKeyState(Keys key); private static IntPtr ptrHook; private static LowLevelKeyboardProc objKeyboardProcess; //тут зафиксируем на всякий случай private static GCHandle gcObjKeyboardProcess = GCHandle.Alloc(objKeyboardProcess); private static IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp) { if (nCode >= 0) { KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT)); if (objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.RWin) { return (IntPtr)1; } } return CallNextHookEx(ptrHook, nCode, wp, lp); } //Зачем дважды объявил? //private delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, IntPtr lParam); public static void SetHook() { ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule; objKeyboardProcess = new LowLevelKeyboardProc(captureKey); ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0); } public static void Unhook() { if (ptrHook != IntPtr.Zero) { UnhookWindowsHookEx(ptrHook); ptrHook = IntPtr.Zero; } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д