Хук клавиатуры - C#
Формулировка задачи:
вот хороший клавиатурный хук, который я использую для отлова клавиши PrtSc(код ниже).
При нажатии данной клавиши, как вы, наверное, догадались, я делаю скриншот экрана и далее обрабатываю его.
Только вот одно "но":
Все работает на отлично, но в некоторых играх(например dota 2) каким-то волшебным образом получается скриншот рабочего стола. Может быть данная тема уже обсуждалась, но помогите незнайке)
И еще одна менее значимая проблемка, которую я уже затрагивал на этом форме, но вразумительного ответа не последовало:
моя прога свернута в трее и я вместо клавиши PrtSc могу назначить другу в настройках. Но как сделать, чтобы нажатие клавиши передавалось только в мою программу, но не передавалось системе. Т.е. если я назначаю клавишу, а потом нажимаю на нее, то моя прога срабатывает на отлично, только вот эта клавиша срабатывает и в системе.
от NickoTin:
Этот↑
вопрос продолжайте в старой теме.using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Hooks
{
public static class KBDHook
{
#region Declarations
public delegate void HookKeyPress ( LLKHEventArgs e );
public static event HookKeyPress KeyUp;
public static event HookKeyPress KeyDown;
[StructLayout(LayoutKind.Sequential)]
struct KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public KBDLLHOOKSTRUCTFlags flags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum KBDLLHOOKSTRUCTFlags : int
{
LLKHF_EXTENDED = 0x01,
LLKHF_INJECTED = 0x10,
LLKHF_ALTDOWN = 0x20,
LLKHF_UP = 0x80,
}
static IntPtr hHook = IntPtr.Zero;
static IntPtr hModule = IntPtr.Zero;
static bool hookInstall = false;
static bool localHook = true;
static API.HookProc hookDel;
#endregion
/// <summary>
/// Hook install method.
/// </summary>
public static void InstallHook()
{
if (IsHookInstalled) return;
hModule = Marshal.GetHINSTANCE(AppDomain.CurrentDomain.GetAssemblies()[0].GetModules()[0]);
hookDel = new API.HookProc(HookProcFunction);
if (localHook)
hHook = API.SetWindowsHookEx(API.HookType.WH_KEYBOARD,
hookDel, IntPtr.Zero, AppDomain.GetCurrentThreadId());
else
hHook = API.SetWindowsHookEx(API.HookType.WH_KEYBOARD_LL,
hookDel, hModule, 0);
if (hHook != IntPtr.Zero)
hookInstall = true;
else
throw new Win32Exception("Can't install low level keyboard hook!");
}
/// <summary>
/// If hook installed return true, either false.
/// </summary>
public static bool IsHookInstalled
{
get { return hookInstall && hHook != IntPtr.Zero; }
}
/// <summary>
/// Module handle in which hook was installed.
/// </summary>
public static IntPtr ModuleHandle
{
get { return hModule; }
}
/// <summary>
/// If true local hook will installed, either global.
/// </summary>
public static bool LocalHook
{
get { return localHook; }
set
{
if (value != localHook)
{
if (IsHookInstalled)
throw new Win32Exception("Can't change type of hook than it install!");
localHook = value;
}
}
}
/// <summary>
/// Uninstall hook method.
/// </summary>
public static void UnInstallHook()
{
if (IsHookInstalled)
{
if (!API.UnhookWindowsHookEx(hHook))
throw new Win32Exception("Can't uninstall low level keyboard hook!");
hHook = IntPtr.Zero;
hModule = IntPtr.Zero;
hookInstall = false;
}
}
/// <summary>
/// Hook process messages.
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
static IntPtr HookProcFunction ( int nCode, IntPtr wParam, [In] IntPtr lParam ) {
if (nCode == 0) {
LLKHEventArgs args = null;
if (localHook) {
bool pressed = false;
if (lParam.ToInt32() >> 31 == 0)
pressed = true;
Keys keys = (Keys)wParam.ToInt32();
args = new LLKHEventArgs(keys, pressed, 0U, 0U);
if (pressed) {
if (KeyUp != null)
KeyUp(args);
} else {
if (KeyDown != null)
KeyDown(args);
}
} else {
KBDLLHOOKSTRUCT kbd = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
bool pressed = false;
if (wParam.ToInt32() == 0x100 || wParam.ToInt32() == 0x104)
pressed = true;
Keys keys = (Keys)kbd.vkCode;
args = new LLKHEventArgs(keys, pressed, kbd.time, kbd.scanCode);
if (pressed) {
if (KeyUp != null)
KeyUp(args);
} else {
if (KeyDown != null)
KeyDown(args);
}
}
if (args != null && args.Hooked)
return (IntPtr)1;
}
return API.CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
public class LLKHEventArgs
{
Keys keys;
bool pressed;
uint time;
uint scCode;
public LLKHEventArgs(Keys keys, bool pressed, uint time, uint scanCode)
{
this.keys = keys;
this.pressed = pressed;
this.time = time;
this.scCode = scanCode;
}
/// <summary>
/// Key.
/// </summary>
public Keys Keys
{ get { return keys; } }
/// <summary>
/// Is key pressed or no.
/// </summary>
public bool IsPressed
{ get { return pressed; } }
/// <summary>
/// The time stamp for this message, equivalent to what GetMessageTime would return for this message.
/// </summary>
public uint Time
{ get { return time; } }
/// <summary>
/// A hardware scan code for the key.
/// </summary>
public uint ScanCode
{ get { return scCode; } }
/// <summary>
/// Is user hook key.
/// </summary>
public bool Hooked { get; set; }
}
static class API
{
public delegate IntPtr HookProc(int nCode, IntPtr wParam, [In] IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, [In] IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn,
IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
}
}Решение задачи: «Хук клавиатуры»
textual
Листинг программы
[DllImport("gdi32.dll")]
static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
[DllImport("gdi32.dll")]
static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("gdi32.dll")]
static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr ptr);
private Bitmap GetScreen()
{
var sz = Screen.PrimaryScreen.Bounds.Size;
var hDesk = GetDesktopWindow();
var hSrce = GetWindowDC(hDesk);
var hDest = CreateCompatibleDC(hSrce);
var hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
var hOldBmp = SelectObject(hDest, hBmp);
BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, rop: CopyPixelOperation.CaptureBlt | CopyPixelOperation.SourceCopy);
var bmp = Image.FromHbitmap(hBmp);
SelectObject(hDest, hOldBmp);
DeleteObject(hBmp);
DeleteDC(hDest);
ReleaseDC(hDesk, hSrce);
return bmp;
}