As part of a media player application I'm working on, I want to hook global key presses for media control keys (play, skip forward, skip back, etc).
I've been searching for about 2 hours now trying to find a solution - but I couldn't find one that worked. I found several Stack Overflow answers about the same thing, but none of them worked.
I tried the MouseKeyHook NuGet package, but it would never fire the event. I tried the FMUtils.KeyboardHook package too, but the same thing happened, except it printed in the console that it shut down the hook right after starting it - and I have no idea why, even after looking at the source code.
I tried to get this codeproject project http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H but I couldn't even run the demo, both the demos just threw weird errors that I couldn't trace.
My question is, what is a known-to-work way of capturing keyboard presses in .NET 4.0 that I can use to capture keyboard presses when my WinForms application isn't focused?
Here is the code I have been using for several projects for the last X years. Should work with no issues (for any .NET version on Windows).
public class KeyboardHook : IDisposable
{
bool Global = false;
public delegate void LocalKeyEventHandler(Keys key, bool Shift, bool Ctrl, bool Alt);
public event LocalKeyEventHandler KeyDown;
public event LocalKeyEventHandler KeyUp;
public delegate int CallbackDelegate(int Code, int W, int L);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct KBDLLHookStruct
{
public Int32 vkCode;
public Int32 scanCode;
public Int32 flags;
public Int32 time;
public Int32 dwExtraInfo;
}
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(HookType idHook, CallbackDelegate lpfn, int hInstance, int threadId);
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, int lParam);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int GetCurrentThreadId();
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
}
private int HookID = 0;
CallbackDelegate TheHookCB = null;
//Start hook
public KeyboardHook(bool Global)
{
this.Global = Global;
TheHookCB = new CallbackDelegate(KeybHookProc);
if (Global)
{
HookID = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, TheHookCB,
0, //0 for local hook. eller hwnd til user32 for global
0); //0 for global hook. eller thread for hooken
}
else
{
HookID = SetWindowsHookEx(HookType.WH_KEYBOARD, TheHookCB,
0, //0 for local hook. or hwnd to user32 for global
GetCurrentThreadId()); //0 for global hook. or thread for the hook
}
}
bool IsFinalized = false;
~KeyboardHook()
{
if (!IsFinalized)
{
UnhookWindowsHookEx(HookID);
IsFinalized = true;
}
}
public void Dispose()
{
if (!IsFinalized)
{
UnhookWindowsHookEx(HookID);
IsFinalized = true;
}
}
//The listener that will trigger events
private int KeybHookProc(int Code, int W, int L)
{
KBDLLHookStruct LS = new KBDLLHookStruct();
if (Code < 0)
{
return CallNextHookEx(HookID, Code, W, L);
}
try
{
if (!Global)
{
if (Code == 3)
{
IntPtr ptr = IntPtr.Zero;
int keydownup = L >> 30;
if (keydownup == 0)
{
if (KeyDown != null) KeyDown((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
if (keydownup == -1)
{
if (KeyUp != null) KeyUp((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
//System.Diagnostics.Debug.WriteLine("Down: " + (Keys)W);
}
}
else
{
KeyEvents kEvent = (KeyEvents)W;
Int32 vkCode = Marshal.ReadInt32((IntPtr)L); //Leser vkCode som er de første 32 bits hvor L peker.
if (kEvent != KeyEvents.KeyDown && kEvent != KeyEvents.KeyUp && kEvent != KeyEvents.SKeyDown && kEvent != KeyEvents.SKeyUp)
{
}
if (kEvent == KeyEvents.KeyDown || kEvent == KeyEvents.SKeyDown)
{
if (KeyDown != null) KeyDown((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
if (kEvent == KeyEvents.KeyUp || kEvent == KeyEvents.SKeyUp)
{
if (KeyUp != null) KeyUp((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
}
}
catch (Exception)
{
//Ignore all errors...
}
return CallNextHookEx(HookID, Code, W, L);
}
public enum KeyEvents
{
KeyDown = 0x0100,
KeyUp = 0x0101,
SKeyDown = 0x0104,
SKeyUp = 0x0105
}
[DllImport("user32.dll")]
static public extern short GetKeyState(System.Windows.Forms.Keys nVirtKey);
public static bool GetCapslock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.CapsLock)) & true;
}
public static bool GetNumlock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.NumLock)) & true;
}
public static bool GetScrollLock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.Scroll)) & true;
}
public static bool GetShiftPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.ShiftKey);
if (state > 1 || state < -1) return true;
return false;
}
public static bool GetCtrlPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.ControlKey);
if (state > 1 || state < -1) return true;
return false;
}
public static bool GetAltPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.Menu);
if (state > 1 || state < -1) return true;
return false;
}
}
Test app:
static class Program
{
[STAThread]
static void Main()
{
var kh = new KeyboardHook(true);
kh.KeyDown += Kh_KeyDown;
Application.Run();
}
private static void Kh_KeyDown(Keys key, bool Shift, bool Ctrl, bool Alt)
{
Debug.WriteLine("The Key: " + key);
}
}
It could do with some code cleanup, but I have not bothered as it works.
Here is a fixed version of the class that doesn't give access violation error:
public class KeyboardHook : IDisposable
{
bool Global = false;
public delegate void ErrorEventHandler(Exception e);
public delegate void LocalKeyEventHandler(Keys key, bool Shift, bool Ctrl, bool Alt);
public event LocalKeyEventHandler KeyDown;
public event LocalKeyEventHandler KeyUp;
public event ErrorEventHandler OnError;
public delegate int CallbackDelegate(int Code, IntPtr W, IntPtr L);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct KBDLLHookStruct
{
public Int32 vkCode;
public Int32 scanCode;
public Int32 flags;
public Int32 time;
public Int32 dwExtraInfo;
}
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr SetWindowsHookEx(HookType idHook, CallbackDelegate lpfn, IntPtr hInstance, int threadId);
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(IntPtr idHook);
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int GetCurrentThreadId();
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
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
}
private IntPtr HookID = IntPtr.Zero;
CallbackDelegate TheHookCB = null;
//Start hook
public KeyboardHook(bool Global)
{
this.Global = Global;
TheHookCB = new CallbackDelegate(KeybHookProc);
if (Global)
{
IntPtr hInstance = LoadLibrary("User32");
HookID = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, TheHookCB,
hInstance, //0 for local hook. or hwnd to user32 for global
0); //0 for global hook. eller thread for hooken
}
else
{
HookID = SetWindowsHookEx(HookType.WH_KEYBOARD, TheHookCB,
IntPtr.Zero, //0 for local hook. or hwnd to user32 for global
GetCurrentThreadId()); //0 for global hook. or thread for the hook
}
}
public void test()
{
if (OnError != null) OnError(new Exception("test"));
}
bool IsFinalized = false;
~KeyboardHook()
{
if (!IsFinalized)
{
UnhookWindowsHookEx(HookID);
IsFinalized = true;
}
}
public void Dispose()
{
if (!IsFinalized)
{
UnhookWindowsHookEx(HookID);
IsFinalized = true;
}
}
[STAThread]
//The listener that will trigger events
private int KeybHookProc(int Code, IntPtr W, IntPtr L)
{
KBDLLHookStruct LS = new KBDLLHookStruct();
if (Code < 0)
{
return CallNextHookEx(HookID, Code, W, L);
}
try
{
if (!Global)
{
if (Code == 3)
{
IntPtr ptr = IntPtr.Zero;
int keydownup = L.ToInt32() >> 30;
if (keydownup == 0)
{
if (KeyDown != null) KeyDown((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
if (keydownup == -1)
{
if (KeyUp != null) KeyUp((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
//System.Diagnostics.Debug.WriteLine("Down: " + (Keys)W);
}
}
else
{
KeyEvents kEvent = (KeyEvents)W;
Int32 vkCode = Marshal.ReadInt32((IntPtr)L); //Leser vkCode som er de første 32 bits hvor L peker.
if (kEvent != KeyEvents.KeyDown && kEvent != KeyEvents.KeyUp && kEvent != KeyEvents.SKeyDown && kEvent != KeyEvents.SKeyUp)
{
}
if (kEvent == KeyEvents.KeyDown || kEvent == KeyEvents.SKeyDown)
{
if (KeyDown != null) KeyDown((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
if (kEvent == KeyEvents.KeyUp || kEvent == KeyEvents.SKeyUp)
{
if (KeyUp != null) KeyUp((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
}
}
catch (Exception e)
{
if (OnError != null) OnError(e);
//Ignore all errors...
}
return CallNextHookEx(HookID, Code, W, L);
}
public enum KeyEvents
{
KeyDown = 0x0100,
KeyUp = 0x0101,
SKeyDown = 0x0104,
SKeyUp = 0x0105
}
[DllImport("user32.dll")]
static public extern short GetKeyState(System.Windows.Forms.Keys nVirtKey);
public static bool GetCapslock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.CapsLock)) & true;
}
public static bool GetNumlock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.NumLock)) & true;
}
public static bool GetScrollLock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.Scroll)) & true;
}
public static bool GetShiftPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.ShiftKey);
if (state > 1 || state < -1) return true;
return false;
}
public static bool GetCtrlPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.ControlKey);
if (state > 1 || state < -1) return true;
return false;
}
public static bool GetAltPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.Menu);
if (state > 1 || state < -1) return true;
return false;
}
}
Related
I have this Global Keyhook I found somewhere online which worked perfectly. Then when I updated to .NET 7.0 and Visual Studio 7.4, and migrated from UWP to the Windows App SDK with the .NET Upgrade Assistant It broke with an AccessViolationException!
Code:
public class KeyboardHook : IDisposable
{
bool Global = false;
public delegate void LocalKeyEventHandler(Keys key, bool Shift, bool Ctrl, bool Alt);
public event LocalKeyEventHandler KeyDown;
public event LocalKeyEventHandler KeyUp;
public delegate int CallbackDelegate(int Code, int W, int L);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct KBDLLHookStruct
{
public Int32 vkCode;
public Int32 scanCode;
public Int32 flags;
public Int32 time;
public Int32 dwExtraInfo;
}
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(HookType idHook, CallbackDelegate lpfn, int hInstance, int threadId);
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32", CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, int lParam);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int GetCurrentThreadId();
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
}
private int HookID = 0;
CallbackDelegate TheHookCB = null;
//Start hook
public KeyboardHook(bool Global)
{
this.Global = Global;
TheHookCB = new CallbackDelegate(KeybHookProc);
if (Global)
{
HookID = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, TheHookCB,
0, //0 for local hook. eller hwnd til user32 for global
0); //0 for global hook. eller thread for hooken
}
else
{
HookID = SetWindowsHookEx(HookType.WH_KEYBOARD, TheHookCB,
0, //0 for local hook. or hwnd to user32 for global
GetCurrentThreadId()); //0 for global hook. or thread for the hook
}
}
bool IsFinalized = false;
~KeyboardHook()
{
if (!IsFinalized)
{
UnhookWindowsHookEx(HookID);
IsFinalized = true;
}
}
public void Dispose()
{
if (!IsFinalized)
{
UnhookWindowsHookEx(HookID);
IsFinalized = true;
}
}
//The listener that will trigger events
private int KeybHookProc(int Code, int W, int L)
{
//KBDLLHookStruct LS = new KBDLLHookStruct();
if (Code < 0)
{
return CallNextHookEx(HookID, Code, W, L);
}
try
{
if (!Global)
{
if (Code == 3)
{
IntPtr ptr = IntPtr.Zero;
int keydownup = L >> 30;
if (keydownup == 0)
{
if (KeyDown != null) KeyDown((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
if (keydownup == -1)
{
if (KeyUp != null) KeyUp((Keys)W, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
//System.Diagnostics.Debug.WriteLine("Down: " + (Keys)W);
}
}
else
{
KeyEvents kEvent = (KeyEvents)W;
Int32 vkCode = Marshal.ReadInt32((IntPtr)L); //Error here!
if (kEvent != KeyEvents.KeyDown && kEvent != KeyEvents.KeyUp && kEvent != KeyEvents.SKeyDown && kEvent != KeyEvents.SKeyUp)
{
}
if (kEvent == KeyEvents.KeyDown || kEvent == KeyEvents.SKeyDown)
{
if (KeyDown != null) KeyDown((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
if (kEvent == KeyEvents.KeyUp || kEvent == KeyEvents.SKeyUp)
{
if (KeyUp != null) KeyUp((Keys)vkCode, GetShiftPressed(), GetCtrlPressed(), GetAltPressed());
}
}
}
catch (Exception)
{
//Ignore all errors...
}
return CallNextHookEx(HookID, Code, W, L);
}
public enum KeyEvents
{
KeyDown = 0x0100,
KeyUp = 0x0101,
SKeyDown = 0x0104,
SKeyUp = 0x0105
}
[DllImport("user32.dll")]
static public extern short GetKeyState(System.Windows.Forms.Keys nVirtKey);
public static bool GetCapslock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.CapsLock)) & true;
}
public static bool GetNumlock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.NumLock)) & true;
}
public static bool GetScrollLock()
{
return Convert.ToBoolean(GetKeyState(System.Windows.Forms.Keys.Scroll)) & true;
}
public static bool GetShiftPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.ShiftKey);
if (state > 1 || state < -1) return true;
return false;
}
public static bool GetCtrlPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.ControlKey);
if (state > 1 || state < -1) return true;
return false;
}
public static bool GetAltPressed()
{
int state = GetKeyState(System.Windows.Forms.Keys.Menu);
if (state > 1 || state < -1) return true;
return false;
}
}
Error:
System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
- $exception {"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."} System.AccessViolationException
+ Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
HResult -2147467261 int
HelpLink null string
+ InnerException null System.Exception
Message "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." string
Source null string
StackTrace null string
TargetSite null System.Reflection.MethodBase
+ Static members
+ Non-Public members
I have tried to try{} catch{} the exception but it didn't work
............................................................
EDIT: 23/NOV/2022:
............................................................
I have restored the project through the backup to it's original state, and instead added the Windows App SDK through NuGet and this error vanishes. Can anyone explain why?
I have a MouseHook class that I got, And I created an event with it, but it's randomly stopping sending input to the event for some reason, Its sending the location/buttons for a couple of seconds to minutes but for some reason it just stops randomly
I created and event like that
MouseHook mouse = new MouseHook();
mouse.OnMouseActivity += new System.Windows.Forms.MouseEventHandler(Mouse_OnMouseActivity);
mouse.Start();
And that's how I notice (For some reasong after couple of seconds-minutes it just stops sending input)
void Mouse_OnMouseActivity(object sender, System.Windows.Forms.MouseEventArgs e)
{
num++;
Console.WriteLine(num);
}
and that's the class:
public class MouseHook
{
private const int WM_MOUSEMOVE = 0x200;
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_RBUTTONDOWN = 0x204;
private const int WM_MBUTTONDOWN = 0x207;
private const int WM_LBUTTONUP = 0x202;
private const int WM_RBUTTONUP = 0x205;
private const int WM_MBUTTONUP = 0x208;
private const int WM_LBUTTONDBLCLK = 0x203;
private const int WM_RBUTTONDBLCLK = 0x206;
private const int WM_MBUTTONDBLCLK = 0x209;
public event System.Windows.Forms.MouseEventHandler OnMouseActivity;
static int hMouseHook = 0;
public const int WH_MOUSE_LL = 14;
HookProc MouseHookProcedure;
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hWnd;
public int wHitTestCode;
public int dwExtraInfo;
}
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
public MouseHook()
{
}
~MouseHook()
{
Stop();
}
public void Start()
{
if (hMouseHook == 0)
{
MouseHookProcedure = new HookProc(MouseHookProc);
//hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProcedure, Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]), 0);
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
if (hMouseHook == 0)
{
Stop();
throw new Exception("SetWindowsHookEx failed.");
}
}
}
public void Stop()
{
bool retMouse = true;
if (hMouseHook != 0)
{
retMouse = UnhookWindowsHookEx(hMouseHook);
hMouseHook = 0;
}
if (!(retMouse)) throw new Exception("UnhookWindowsHookEx failed.");
}
private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if ((nCode >= 0) && (OnMouseActivity != null))
{
MouseButtons button = MouseButtons.None;
int clickCount = 0;
switch (wParam)
{
case WM_LBUTTONDOWN:
button = MouseButtons.Left;
clickCount = 1;
break;
case WM_LBUTTONUP:
button = MouseButtons.Left;
clickCount = 2;
break;
case WM_LBUTTONDBLCLK:
button = MouseButtons.Left;
clickCount = 3;
break;
case WM_RBUTTONDOWN:
button = MouseButtons.Right;
clickCount = 4;
break;
case WM_RBUTTONUP:
button = MouseButtons.Right;
clickCount = 5;
break;
case WM_RBUTTONDBLCLK:
button = MouseButtons.Right;
clickCount = 6;
break;
}
MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
System.Windows.Forms.MouseEventArgs e = new System.Windows.Forms.MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, 0);
OnMouseActivity(this, e);
}
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
}
I'm new to c#/winforms and i wanted to get mouse state as an int to check it in an "if" statement. (For exemple, left click)
So I found a global mouse hook [Here][1], wich works great.
But i don't understand how i can get the mouse state as an int, i searched for a long time on forums and wikis.
I've an error when i create an int in the hookCallback, where the click state is checked (If i understanded as well)
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MouseHook.Start();
MouseHook.MouseAction += ne
w EventHandler(Event);
}
private void Event(object sender, EventArgs e) { Console.WriteLine("Left mouse click!"); }
}
public static class MouseHook
{
public static event EventHandler MouseAction = delegate { };
public static void Start()
{
_hookID = SetHook(_proc);
}
public static void stop()
{
UnhookWindowsHookEx(_hookID);
}
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
MouseAction(null, new EventArgs());
******** public int LeftClick = 1; *********
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
Add my class to your project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows.Input;
namespace Hector.Framework.Utils
{
public class Peripherals
{
public class Mouse
{
public static int X
{
get => Cursor.Position.X;
}
public static int Y
{
get => Cursor.Position.Y;
}
public static void MoveToPoint(int X, int Y)
{
Win32.SetCursorPos(X, Y);
}
public static void Hide()
{
Cursor.Hide();
}
public static void Show()
{
Cursor.Show();
}
public static bool IsHidden
{
get => Cursor.Current == null;
}
/// <summary>
/// ButtonNumber: 0-None 1-Left 2-Middle 3-Right 4-XButton1 5-XButton2
/// </summary>
public static bool MouseButtonIsDown(int ButtonNumber)
{
bool outValue = false;
bool isLeft = Control.MouseButtons == MouseButtons.Left;
bool isRight = Control.MouseButtons == MouseButtons.Right;
bool isMiddle = Control.MouseButtons == MouseButtons.Middle;
bool isXButton1 = Control.MouseButtons == MouseButtons.XButton1;
bool isXButton2 = Control.MouseButtons == MouseButtons.XButton2;
switch (ButtonNumber)
{
case 0:
outValue = false;
break;
case 1:
outValue = isLeft;
break;
case 2:
outValue = isMiddle;
break;
case 3:
outValue = isRight;
break;
case 4:
outValue = isXButton1;
break;
case 5:
outValue = isXButton2;
break;
}
return outValue;
}
/// <summary>
/// This function is in Alpha Phase
/// </summary>
/// <param name="FocusedControl">The control that is scrolled; If the control has no focus, it will be applied automatically</param>
/// <param name="FontSize">This is used to calculate the number of pixels to move, its default value is 20</param>
static int delta = 0;
static int numberOfTextLinesToMove = 0;
static int numberOfPixelsToMove = 0;
public static bool GetWheelValues(Control FocusedControl, out int Delta, out int NumberOfTextLinesToMove, out int NumberOfPixelsToMove, int FontSize = 20)
{
try
{
if (FocusedControl == null) throw new NullReferenceException("The FocusedControl can not bel null");
if (!FocusedControl.Focused) FocusedControl.Focus();
FocusedControl.MouseWheel += (object sender, MouseEventArgs e) =>
{
delta = e.Delta;
numberOfTextLinesToMove = e.Delta * SystemInformation.MouseWheelScrollLines / 120;
numberOfPixelsToMove = numberOfTextLinesToMove * FontSize;
};
Delta = delta;
NumberOfTextLinesToMove = numberOfTextLinesToMove;
NumberOfPixelsToMove = numberOfPixelsToMove;
return true;
}
catch
{
Delta = 0;
NumberOfTextLinesToMove = 0;
NumberOfPixelsToMove = numberOfPixelsToMove;
return false;
}
}
private class Win32
{
[DllImport("User32.Dll")]
public static extern long SetCursorPos(int x, int y);
[DllImport("User32.Dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT point);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
}
}
}
}
Then where you need to check the mouse's status, write the following:
bool MouseLeftButton = Hector.Framework.Utils.Peripherals.Mouse.MouseButtonIsDown(1);
Remember: While selected button is pressed, bool is true, when button released, bool is false
The ButtonNumbers:
0 - None,
1 - Left,
2 - Middle,
3 - Right,
4 - XButton1,
5 - XButton2
I need to programmatically detect whether my computer (Windows 7 / 8) supports wake timers. So far I have done the following:
Guid activePowerScheme = GetActivePowerSchemeGuid();
IntPtr ptrActiveGuid = IntPtr.Zero;
uint buffSize = 0;
uint res = PowerReadACValue(IntPtr.Zero, ref activePowerScheme, ref ApplicationConstants.SLEEPGUID, ref ApplicationConstants.WAKETIMERGUID, IntPtr.Zero, IntPtr.Zero, ref buffSize);
if (res == 0)
{
IntPtr ptrName = IntPtr.Zero;
try
{
ptrName = Marshal.AllocHGlobal((int)buffSize);
res = PowerReadACValue(IntPtr.Zero, ref activePowerScheme, ref ApplicationConstants.SLEEPGUID, ref ApplicationConstants.WAKETIMERGUID, IntPtr.Zero, ptrName, ref buffSize);
byte[] ba = new byte[buffSize];
Marshal.Copy(ptrName, ba, 0, (int)buffSize);
int retVal = BitConverter.ToInt32(ba, 0);
if (retVal == 0)
{
return true;
}
else
{
return false;
}
}
catch(Exception exp)
{
Logger.LogException(exp);
return false;
}
finally
{
if (ptrName != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptrName);
}
}
}
return false;
This works most of the time, but when I reset my power plan settings, this doesn't work well (inconsistent). I also tried the following:
Guid currentPowerSchemeGuid = GetActivePowerSchemeGuid();
RegistryKey currentPowerSchemeKey = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\" + currentPowerSchemeGuid.ToString());
if (currentPowerSchemeKey != null)
{
RegistryKey sleepRegKey = currentPowerSchemeKey.OpenSubKey(ApplicationConstants.SLEEPGUID.ToString());
currentPowerSchemeKey.Close();
if (sleepRegKey != null)
{
RegistryKey wakeTimerRegKey = sleepRegey.OpenSubKey(ApplicationConstants.WAKETIMERGUID.ToString());
sleepRegKey.Close();
if (wakeTimerRegKey != null)
{
wakeTimerRegKey.Close();
currentPowerSchemeKey.Close();
return true;
}
else
{
currentPowerSchemeKey.Close();
return false;
}
}
else
{
currentPowerSchemeKey.Close();
return false;
}
}
else
{
return false;
}
This doesn't work on reset of power plan settings, the wake timer GUID registry key gets cleared. Is there a proper way I can detect if my system supports wake timers?
According to arx, tried the following code and it works.
public static bool IsWakeTimerSupported()
{
IntPtr timerHandle = CreateWaitableTimer(IntPtr.Zero, true, "Wait Timer 1");
uint retVal = GetLastError();
if (timerHandle != IntPtr.Zero)
{
CancelWaitableTimer(timerHandle);
CloseHandle(timerHandle);
timerHandle = IntPtr.Zero;
}
//SUCCESS
if (retVal == 0)
{
return true;
}
else
{
return false;
}
}
The CancelWaitableTimer(timerHandle) can be ignored as the MSDN documentation says to use CloseHandle.
EDIT:
public static bool IsWakeTimerSupported()
{
IntPtr timerHandle = CreateWaitableTimer(IntPtr.Zero, true, "Wait Timer 1");
long interval = 0;
int retVal = 0;
if (timerHandle != IntPtr.Zero)
{
SetWaitableTimer(timerHandle, ref interval, 0, IntPtr.Zero, IntPtr.Zero, true);
retVal = Marshal.GetLastWin32Error();
WaitableTimer.CancelWaitableTimer(timerHandle);
try
{
Win32.CloseHandle(timerHandle);
}
catch (Exception exp)
{
Logger.LogException(exp);
}
timerHandle = IntPtr.Zero;
}
//SUCCESS
if (retVal == 0)
{
return true;
}
else
{
return false;
}
}
According to this article, http://blogs.msdn.com/b/adam_nathan/archive/2003/04/25/56643.aspx we shoud never use GetLastError through PInvoke.
Using the powrprof.dll library worked for me:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Namespace {
public static class PowerOptions {
// src: https://msdn.microsoft.com/en-us/library/windows/desktop/hh448380%28v=vs.85%29.aspx
private readonly static Guid HIGH_PERFORMANCE = new Guid("8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"); // aka MIN_POWER_SAVINGS
private readonly static Guid BALANCED = new Guid("381b4222-f694-41f0-9685-ff5bb260df2e"); // aka TYPICAL_POWER_SAVINGS
private readonly static Guid POWER_SAVER = new Guid("a1841308-3541-4fab-bc81-f71556f20b4a"); // aka MAX_POWER_SAVINGS
private readonly static Guid ACDC_POWER_SOURCE = new Guid("5d3e9a59-e9D5-4b00-a6bd-ff34ff516548");
private readonly static Guid SLEEP_SUBCATEGORY = new Guid("238C9FA8-0AAD-41ED-83F4-97BE242C8F20");
private readonly static Guid WAKE_TIMERS = new Guid("bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d");
public static String GetCurrentPowerPlanFriendlyName() {
IntPtr ptrActiveGuid = IntPtr.Zero;
int ret = PowerGetActiveScheme(IntPtr.Zero, ref ptrActiveGuid);
if (ret == 0) {
uint buffSize = 0;
ret = PowerReadFriendlyName(IntPtr.Zero, ptrActiveGuid, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref buffSize);
if (ret == 0) {
if (buffSize == 0)
return "";
IntPtr ptrName = Marshal.AllocHGlobal((int) buffSize);
ret = PowerReadFriendlyName(IntPtr.Zero, ptrActiveGuid, IntPtr.Zero, IntPtr.Zero, ptrName, ref buffSize);
if (ret == 0) {
String name = Marshal.PtrToStringUni(ptrName);
Marshal.FreeHGlobal(ptrName);
return name;
}
Marshal.FreeHGlobal(ptrName);
}
}
throw new Win32Exception(ret, "GetCurrentPowerPlanFriendlyName");
}
public static PowerStatus GetPowerStatus() {
PowerStatus ps = new PowerStatus();
if (!GetSystemPowerStatus(ref ps))
throw new Win32Exception(Marshal.GetLastWin32Error(), "GetPowerStatus");
return ps;
}
public static bool GetWakeTimersEnabled(PowerSource powerSource = PowerSource.Current, PowerPlan powerPlan = PowerPlan.Current) {
int ret = 0;
if (powerSource == PowerSource.Current) {
PowerStatus ps = GetPowerStatus();
if (ps.ACLineStatus == PowerLineStatus.Online)
powerSource = PowerSource.PluggedIn;
else
powerSource = PowerSource.OnBattery;
}
if (ret == 0) {
if (powerPlan == PowerPlan.Current) {
IntPtr ptrPowerPlan = IntPtr.Zero;
ret = PowerGetActiveScheme(IntPtr.Zero, ref ptrPowerPlan);
if (ret == 0) {
uint value = 0;
if (powerSource == PowerSource.PluggedIn)
ret = PowerReadACValueIndex(IntPtr.Zero, ptrPowerPlan, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value);
else
ret = PowerReadDCValueIndex(IntPtr.Zero, ptrPowerPlan, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value);
if (ret == 0) {
return (value == 1);
}
}
}
else {
Guid guid = GetGuid(powerPlan);
uint value = 0;
if (powerSource == PowerSource.PluggedIn)
ret = PowerReadACValueIndex(IntPtr.Zero, guid, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value);
else
ret = PowerReadDCValueIndex(IntPtr.Zero, guid, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value);
if (ret == 0) {
return (value == 1);
}
}
}
throw new Win32Exception(ret, "GetWakeTimersEnabled");
}
public static Guid GetGuid(PowerPlan powerPlan) {
if (powerPlan == PowerPlan.Balanced)
return BALANCED;
if (powerPlan == PowerPlan.HighPerformance)
return HIGH_PERFORMANCE;
if (powerPlan == PowerPlan.PowerSaver)
return POWER_SAVER;
throw new ArgumentException("Not a standard power plan: " + powerPlan);
}
[DllImport("powrprof.dll", SetLastError = true)]
public static extern int PowerWriteACValueIndex(IntPtr RootPowerKey, Guid SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, uint AcValueIndex);
[DllImport("powrprof.dll", SetLastError = true)]
private static extern int PowerReadACValueIndex(IntPtr RootPowerKey, IntPtr SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex);
[DllImport("powrprof.dll", SetLastError = true)]
private static extern int PowerReadACValueIndex(IntPtr RootPowerKey, Guid SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex);
[DllImport("powrprof.dll", SetLastError = true)]
private static extern int PowerReadDCValueIndex(IntPtr RootPowerKey, IntPtr SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex);
[DllImport("powrprof.dll", SetLastError = true)]
private static extern int PowerReadDCValueIndex(IntPtr RootPowerKey, Guid SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex);
[DllImport("powrprof.dll", SetLastError = true)]
private static extern int PowerGetActiveScheme(IntPtr UserRootPowerKey, ref IntPtr ActivePolicyGuid);
[DllImport("powrprof.dll", SetLastError = true)]
private static extern int PowerReadFriendlyName(IntPtr RootPowerKey, IntPtr SchemeGuid, IntPtr SubGroupOfPowerSettingsGuid, IntPtr PowerSettingGuid, IntPtr Buffer, ref uint BufferSize);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetSystemPowerStatus(ref PowerStatus lpSystemPowerStatus);
}
public enum PowerPlan {
Current,
HighPerformance,
Balanced,
PowerSaver,
}
public enum PowerSource {
Current,
OnBattery,
PluggedIn
}
public struct PowerStatus {
///<summary>The AC power status.</summary>
public PowerLineStatus ACLineStatus;
///<summary>The battery charge status.</summary>
public PowerChargeStatus BatteryFlag;
///<summary>Returns a value between [0 to 100] or 255 if unknown.</summary>
public byte BatteryLifePercent;
///<summary>Returns a value that indicates if the system is currently conserving power.</summary>
public PowerSaveStatus SystemStatusFlag;
///<summary>Number of seconds of battery life remaining, or -1 if unknown.</summary>
public int BatteryLifeTime;
///<summary>Number of seconds of batter life on a full charge, or -1 if unknown.</summary>
public int BatteryFullLifeTime;
}
public enum PowerLineStatus : byte {
Offline = 0,
Online = 1,
Unknown = 255,
}
[Flags]
public enum PowerChargeStatus : byte {
High = 1,
Low = 2,
Critical = 4,
Charging = 8,
NoBattery = 128,
Unknown = 255,
}
public enum PowerSaveStatus : byte {
Off = 0,
On = 1,
}
}
I have a swf inside a html page. If I open it with IE or FF and put it into full screen I can exit full screen with the ESC button.
Now if i try this with my WinForms app and WebBrowser (or ShockWave Flash Object) it's not working??
Any ideas?
I know it's late but Ctrl + W does the trick for me
As outlined here there is a problem with Windows Forms' ActiveX container support. The keyboard message does not get passed to the Flash player.
The solution I've come up with (based on code from here) is to write a keyboard hook to catch the Escape key and to pass a message to the Flash window to close if it's active.
First, there's the KeyHook class which provides the plumbing to listen for the Escape key.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Your.Utility
{
public class KeyBordHook
{
private const int WM_KEYDOWN = 0x100;
private const int WM_KEYUP = 0x101;
private const int WM_SYSKEYDOWN = 0x104;
private const int WM_SYSKEYUP = 0x105;
//Global event
public event KeyEventHandler OnKeyDownEvent;
public event KeyEventHandler OnKeyUpEvent;
public event KeyPressEventHandler OnKeyPressEvent;
private static int hKeyboardHook = 0;
private const int WH_KEYBOARD_LL = 13; //keyboard hook constant
private HookProc KeyboardHookProcedure; // declare keyhook event type
//declare keyhook struct
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
[DllImport("user32")]
private static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
[DllImport("user32")]
private static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
private List<Keys> preKeys = new List<Keys>();
public KeyBordHook()
{
Start();
}
~KeyBordHook()
{
Stop();
}
public void Start()
{
//install keyboard hook
if (hKeyboardHook == 0)
{
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
//hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
Process curProcess = Process.GetCurrentProcess();
ProcessModule curModule = curProcess.MainModule;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(curModule.ModuleName), 0);
if (hKeyboardHook == 0)
{
Stop();
throw new Exception("SetWindowsHookEx ist failed.");
}
}
}
public void Stop()
{
bool retKeyboard = true;
if (hKeyboardHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
}
//if unhook failed
if (!(retKeyboard)) throw new Exception("UnhookWindowsHookEx failed.");
}
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
{
KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
if (IsCtrlAltShiftKeys(keyData) && preKeys.IndexOf(keyData) == -1)
{
preKeys.Add(keyData);
}
}
if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
OnKeyDownEvent(this, e);
}
if (OnKeyPressEvent != null && wParam == WM_KEYDOWN)
{
byte[] keyState = new byte[256];
GetKeyboardState(keyState);
byte[] inBuffer = new byte[2];
if (ToAscii(MyKeyboardHookStruct.vkCode,
MyKeyboardHookStruct.scanCode,
keyState,
inBuffer,
MyKeyboardHookStruct.flags) == 1)
{
KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);
OnKeyPressEvent(this, e);
}
}
if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
if (IsCtrlAltShiftKeys(keyData))
{
for (int i = preKeys.Count - 1; i >= 0; i--)
{
if (preKeys[i] == keyData)
{
preKeys.RemoveAt(i);
}
}
}
}
if (OnKeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
OnKeyUpEvent(this, e);
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
private Keys GetDownKeys(Keys key)
{
Keys rtnKey = Keys.None;
foreach (Keys keyTemp in preKeys)
{
switch (keyTemp)
{
case Keys.LControlKey:
case Keys.RControlKey:
rtnKey = rtnKey | Keys.Control;
break;
case Keys.LMenu:
case Keys.RMenu:
rtnKey = rtnKey | Keys.Alt;
break;
case Keys.LShiftKey:
case Keys.RShiftKey:
rtnKey = rtnKey | Keys.Shift;
break;
default:
break;
}
}
rtnKey = rtnKey | key;
return rtnKey;
}
private Boolean IsCtrlAltShiftKeys(Keys key)
{
switch (key)
{
case Keys.LControlKey:
case Keys.RControlKey:
case Keys.LMenu:
case Keys.RMenu:
case Keys.LShiftKey:
case Keys.RShiftKey:
return true;
default:
return false;
}
}
}
}
Next, you need to create an instance of the KeyHook class in your Windows Form ...
// inside Form class ...
private readonly KeyBordHook _keyBordHook = new KeyBordHook();
private void InitKeyHook()
{
_keyBordHook.OnKeyPressEvent += new KeyPressEventHandler(_KeyBordHook_OnKeyPressEvent);
_keyBordHook.Start();
}
void _KeyBordHook_OnKeyPressEvent(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == Convert.ToChar(Keys.Escape))
WindowHelper.CloseWindowIfActive("Flash");
}
public void StartKeyListening()
{
InitKeyHook();
}
public void StopKeyListening()
{
_keyBordHook.Stop();
}
And, the code to actually close the Flash Window...
public sealed class WindowHelper
{
[DllImport("USER32.dll", SetLastError = true)]
private static extern IntPtr GetForegroundWindow();
[DllImport("USER32.dll", SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
static uint WM_CLOSE = 0x10;
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("USER32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private static bool CloseWindow(IntPtr hWnd)
{
bool returnValue = PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
if (!returnValue)
throw new Win32Exception(Marshal.GetLastWin32Error());
return true;
}
public static void CloseWindowIfActive(string windowTitle)
{
const int nChars = 256;
StringBuilder buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, buff, nChars) <= 0) return;
if (buff.ToString().ToLower().IndexOf(windowTitle.ToLower()) > -1)
CloseWindow(handle);
}
}
I'm sure there's improvements to be made in all of the above but so far, this solution appears to work for me.
Note that this code allows you to record all key strokes across all apps so it's definitely overkill and may not be desirable to integrate into a customer bound application!
Did you try F11? That's the default for IE.