Есть участок кода где перехватываются клавиши и блокируются:
public IntPtr LowLevelKeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
var objKeyInfo = (KBDLLHOOKSTRUCT)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin)
{
return (IntPtr)1; // <WinKey>
}
else if (objKeyInfo.key == Keys.Alt || objKeyInfo.key == Keys.Tab)
{
return (IntPtr)1; // <Alt>+<Tab>
}
else if (objKeyInfo.key == Keys.Alt || objKeyInfo.key == Keys.Space)
{
return (IntPtr)1; // <Alt>+<Space>
}
else if (objKeyInfo.key == Keys.LControlKey || objKeyInfo.key == Keys.RControlKey || objKeyInfo.key == Keys.LShiftKey || objKeyInfo.key == Keys.RShiftKey || objKeyInfo.key == Keys.Escape)
{
return (IntPtr)1; // <Control>+<Shift>+<Escape>
}
else if (objKeyInfo.key == Keys.LControlKey || objKeyInfo.key == Keys.Alt || objKeyInfo.key == Keys.Delete)
{
return (IntPtr)1; // <Control>+<Alt>+<Del>
}
}
return CallNextHookEx(this.m_hHook, nCode, wParam, lParam);
}
Почему при таком подходе не все клавиши блокируются?
В Данном случае не блокируется это сочетание клавиш: ( Не видит клавишу Alt )
else if (objKeyInfo.key == Keys.LControlKey || objKeyInfo.key == Keys.Alt || objKeyInfo.key == Keys.Delete)
{
MessageBox.Show(objKeyInfo.key.ToString()); // Проверка какая клавиша нажата
return (IntPtr)1; // <Control>+<Alt>+<Del>
}
Просто для каждой блокировки клавиш выделять отдельный метод с отдельными клавишами для похукивания не айс.
Вызов хука - в классе SetHook():
public IntPtr m_hHook;
public void SetHook()
{
m_callback = LowLevelKeyboardHookProc;
m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, m_callback, GetModuleHandle(IntPtr.Zero), 0);
}
Попробовал так же сделать связку через: vkCode
int vkCode = Marshal.ReadInt32(lParam);
if (Keys.Control == Control.ModifierKeys || Keys.Delete == (Keys)vkCode || Keys.Alt == (Keys)vkCode)
{
MessageBox.Show(objKeyInfo.key.ToString());
return (IntPtr)1; // Ctrl + Alt + Delete
}
Просто Alt не хочет читать, подскажите почему такой баг возникает?
И есть ли решение данной проблемы?
[Новая проверка]
Пробую проверять так:
if ((objKeyInfo.flags & LLKHF_ALTDOWN) != 0 && vkCode == (uint)Keys.Control && vkCode == (uint)Keys.Delete)
{
return (IntPtr)1;
}
// или даже так:
if (Keys.Control == Control.ModifierKeys && (objKeyInfo.flags & LLKHF_ALTDOWN) != 0 && vkCode == (uint)Keys.Delete)
{
return (IntPtr)1;
}
Но всё ровно не блокируется именно это сочетание клавиш, хочу понять почему такое случается.
P.S: Система Windows 10 x64
Потому что вы не написали правильный код для блокировки этих сочетаний клавиш. Начать с того, что VK для нажатия клавиши ALT в хуке - на самом деле не Keys.Alt
, а Keys.LMenu
или Keys.RMenu
. Но даже если поменять VK на правильный, все равно условие if (objKeyInfo.key == Keys.Alt || objKeyInfo.key == Keys.Tab)
никак не может соответствовать "блокировать сочетание клавиш Alt+Tab" - вы блокируете вместо этого любые нажатия клавиш Alt и Tab!
Правильно это делается так:
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Windows.Forms;
namespace KeyboardHookSample
{
class Program
{
static KeyHooker k;
static void Main(string[] args)
{
k = new KeyHooker();
k.Start();
Console.CancelKeyPress += Console_CancelKeyPress;
Console.WriteLine("Hook installed...");
Application.Run();
}
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
k.Stop();
Application.Exit();
}
}
[StructLayout(LayoutKind.Sequential)]
public class KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public UIntPtr dwExtraInfo;
}
sealed class KeyHooker : IDisposable
{
//объявления типов, констант и функций Windows API
delegate IntPtr KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
const int WH_KEYBOARD_LL = 13;
const int HC_ACTION = 0;
const int WM_KEYDOWN = 0x0100;
const int WM_SYSKEYDOWN = 0x0104;
const uint LLKHF_ALTDOWN = 0x20;
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllToLoad);
IntPtr _hookID = IntPtr.Zero;
//начинает отслеживание событий клавиатуры
public void Start()
{
if (disposed) throw new ObjectDisposedException("KeyLogger");
if (_hookID != IntPtr.Zero) return;
_hookID = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookCallback, IntPtr.Zero, 0);
if (_hookID == IntPtr.Zero)
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error, "Failed to install hook! Error: " + error.ToString());
}
}
//останавливает отслеживание событий клавиатуры
public void Stop()
{
if (disposed) return;
if (_hookID == IntPtr.Zero) return;
UnhookWindowsHookEx(_hookID);
_hookID = IntPtr.Zero;
}
//вызывается Windows при нажатии клавиши
IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))
{
KBDLLHOOKSTRUCT khs = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
uint vkCode = khs.vkCode;
if ((khs.flags & LLKHF_ALTDOWN) != 0 && vkCode == (uint)Keys.Tab)
{
return (IntPtr)1; //Cancel Alt+Tab
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
bool disposed = false;
public void Dispose()
{
if (disposed) return;
Stop();
disposed = true;
GC.SuppressFinalize(this);
}
~KeyHooker()
{
Dispose();
}
}
}
Также следует помнить, что блокировку системных сочетаний клавиш нужно применять с осторожностью. Если полноэкранное приложение блокирует сочетания клавиш Alt+Tab и Ctrl+Alt+Delete, то в случае его зависания система становится полностью неработоспособной - ничего не остается, кроме как перезагружать системник кнопкой Reset.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Появилась проблема со считыванием большого файлаИндекс массива, в который записываются строки(array[i]), останавливается на 174 и всё
Можно как то получить папки из быстрого доступа проводника?
Не до конца понимаю, почему появляется ошибка
Вворачиваю в самопальный лаунчер для самопальных программ систему обновленияУ меня есть готовая процедура обновления, которая запускается...