how can i disable windows + d combination keys in windows forms - c#

i have a windows form which looks like a widget
i have to disable combination keys like alt+f4 win+d . because widget have no properties of minimize close with shortcut keys.
i have disabled the win+d keys in my widget but it disabled the shorcut for all the apps
what i have to do, is to only disable shorcut keys for my application like widget .
when some1 press any win+d then the background application like internet explorer(if open) will be minimized or maximized.
any idea how can i do that ?
like rain meter or like xwidget have the same properties! any idea how can they do that?

You can't do that in Winforms
You must create a Widget Project

You can use global keyboard hook, you can see an example of how to do it here,
Then just listen to win + d combination in your hook and in this case don't pass the call forward

public partial class MainForm : Form
{
readonly KeyboardFilter kbFilter = new KeyboardFilter(new Keys[]
{
Keys.LWin | Keys.D,
Keys.RWin | Keys.D,
Keys.LWin | Keys.X,
Keys.RWin | Keys.X,
Keys.Alt | Keys.F4
});
}
Be sure to use KeyboardFilter.Dispose() in the Form_Closing event.
KeyboardFilter class was taken from Here
class KeyboardFilter : IDisposable
{
private Keys[] mFilter;
private IntPtr mHook;
private readonly LowLevelKeyboardProc mProc;
public KeyboardFilter(Keys[] keysToFilter)
{
// Install hook
mFilter = keysToFilter;
ProcessModule mod = Process.GetCurrentProcess().MainModule;
mProc = KeyboardProc; // Avoid garbage collector problems
mHook = SetWindowsHookEx(13, mProc, GetModuleHandle(mod.ModuleName), 0);
if (mHook == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set hook");
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Release hook
if (mHook != IntPtr.Zero)
{
UnhookWindowsHookEx(mHook);
mHook = IntPtr.Zero;
}
}
}
~KeyboardFilter()
{
Dispose(false);
}
private IntPtr KeyboardProc(int nCode, IntPtr wp, IntPtr lp)
{
// Callback, filter key
if (nCode >= 0)
{
KBDLLHOOKSTRUCT info = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
foreach (Keys key in mFilter)
if ((key & Keys.KeyCode) == info.key && CheckModifier(key)) return (IntPtr)1;
}
return CallNextHookEx(mHook, nCode, wp, lp);
}
private static bool CheckModifier(Keys key)
{
// Check if modifier key in required state
if ((key & Keys.Control) == Keys.Control &&
GetAsyncKeyState(Keys.LControlKey) == 0 && GetAsyncKeyState(Keys.RControlKey) == 0) return false;
if ((key & Keys.Shift) == Keys.Shift &&
GetAsyncKeyState(Keys.LShiftKey) == 0 && GetAsyncKeyState(Keys.RShiftKey) == 0) return false;
if ((key & Keys.Alt) == Keys.Alt &&
GetAsyncKeyState(Keys.LMenu) == 0 && GetAsyncKeyState(Keys.RMenu) == 0) return false;
return true;
}
// P/Invoke declarations
[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);
}

Related

Remove the window from the taskbar in WinUI 3

I'm creating an app that needs UI but not show up inside the taskbar, I know exactly how to do this in, winforms and wpf, but the window object doesn't contain a ShowInTaskBar variable that I can just change.
I have tried NotifyIcon but that doesn't hide it from the taskbar, I also can't find any documentation on if this is even possible.
I only create a stack overflow question when I've spent more than 5 hours on this, so any help would be appreciated.
Nick showed me this post https://stackoverflow.com/a/551847/14724147
Just add the window handle to the win32 api and it will hide it from alt+tab and the taskbar
public MainWindow()
{
InitializeComponent();
IntPtr hWnd = WindowNative.GetWindowHandle(this);
int exStyle = (int)GetWindowLong(hWnd, (int)GetWindowLongFields.GWL_EXSTYLE);
exStyle |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW;
SetWindowLong(hWnd, (int)GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
}
#region Window styles
[Flags]
public enum ExtendedWindowStyles
{
// ...
WS_EX_TOOLWINDOW = 0x00000080,
// ...
}
public enum GetWindowLongFields
{
// ...
GWL_EXSTYLE = (-20),
// ...
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
int error = 0;
IntPtr result = IntPtr.Zero;
// Win32 SetWindowLong doesn't clear error on success
SetLastError(0);
if (IntPtr.Size == 4)
{
// use SetWindowLong
Int32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));
error = Marshal.GetLastWin32Error();
result = new IntPtr(tempResult);
}
else
{
// use SetWindowLongPtr
result = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);
error = Marshal.GetLastWin32Error();
}
if ((result == IntPtr.Zero) && (error != 0))
{
throw new System.ComponentModel.Win32Exception(error);
}
return result;
}
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
private static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);
private static int IntPtrToInt32(IntPtr intPtr)
{
return unchecked((int)intPtr.ToInt64());
}
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(int dwErrorCode);
#endregion

What do I put for the MouseDevice parameter in a MouseButtonEventArgs Constructor?

I'm creating an app in WPF c# that needs to be able to detect mouse click up and click down events separately. In order to do this, I use code for a Global Mouse Hook that I found online. the only problem with the code was that it used EventArgs as the EventHandler so it passed the same function everytime I sent MouseUp and MouseDown in. To fix this, I used the MouseButtonEventArgs constructor. The rpoblem I'm having now is that the constructor needs 3 parameters: MouseDevice, timestamp, and MouseButton for the constructor to actually work. I have figured out timestamp and MouseButton, but I don't know what to put for MouseDevice. What do I put here to make the constructor work? Here is my low level mousehook class code.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Input;
namespace KeystrokeDisplay
{
public static class MouseHook
{
public static event MouseEventHandler 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 MouseButtonEventArgs(mouse: ????????, timestamp: 0, button: MouseButton.Left));
}
if (nCode >= 0 && MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
MouseAction(null, new MouseButtonEventArgs(mouse: ????????, timestamp: 0, button: MouseButton.Left));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
public const int WH_MOUSE_LL = 14;
public enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
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);
}
}
How do I fix this? Also, I'm fairly new to c# so I might need some extra help understanding your answer.
I don't see any reason to use MouseEventHandler.
You want to detect mouse click up and click down events separately, so you can create two delegates for mouse click up and click down and pass own event arguments. You are only interested in which mouse button was pressed.
public delegate void MouseUpEventHandler(object sender, MyMouseEventArgs e);
public delegate void MouseDownEventHandler(object sender, MyMouseEventArgs e);
public class MyMouseEventArgs : EventArgs
{
public MouseButton MouseButton { get; }
public MyMouseEventArgs(MouseButton mouseButton)
{
MouseButton = mouseButton;
}
}
Then replace
public static event MouseEventHandler MouseAction = delegate { };
with
public static event MouseUpEventHandler MouseUpAction = delegate { };
public static event MouseDownEventHandler MouseDownAction = delegate { };
In HookCallback invoke MouseDownAction or MouseUpAction.
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));
MouseDownAction(null, new MyMouseEventArgs(MouseButton.Left));
}
if (nCode >= 0 && MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
MouseUpAction(null, new MyMouseEventArgs(MouseButton.Left));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

Disable a specific keys when a specific process detected C#

I'm trying to disable specific keys when a specific process is detected, but for a reason, it's not set the hook correctly so it's not working.
The code should do:
Detect if notepad.exe has been detected (already coded the function but i didnt write it here).
Now from the checking thread, it will start the hook thread which will implement a low-level keyboard hook to prevent the user from using specific keys into the target process.
here is the code that I'm using:
[StructLayout(LayoutKind.Sequential)]
private struct KBDLLHOOKSTRUCT
{
public Keys key;
public int scanCode;
public int flags;
public int time;
public IntPtr extra;
}
//System level functions to be used for hook and unhook keyboard input
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);
//Declaring Global objects
private static IntPtr ptrHook;
private static LowLevelKeyboardProc objKeyboardProcess;
private const int WH_KEYBOARD_LL = 13;
private const int VK_CONTROL = 0x11;
public void Control()
{
MessageBox.Show("Control thread has been started");
ProcessModule objCurrentModule = Process.GetProcessesByName("notepad")[0].MainModule;
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
}
public static IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
{
if (nCode >= 0)
{
KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
MessageBox.Show("ncode >=0 !");
if (objKeyInfo.key == Keys.G || objKeyInfo.key == Keys.H || objKeyInfo.key == Keys.S) // Disabling Windows keys
{
MessageBox.Show("One of the specific keys has been detected!");
return (IntPtr)1;
}
}
return CallNextHookEx(ptrHook, nCode, wp, lp);
}
public static void Dispose()
{
UnhookWindowsHookEx(ptrHook);
}
public static void Hide()
{
ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
}
public Form1()
{
InitializeComponent();
Thread cont = new Thread(Control);
cont.start();
}

Show location of Pointer

I'm trying to implement a screencast application and i need to show the location of mouse on click.
How can I show the location of the pointer(mouse) like there is default on windows with the CTRL key if you enable that option on (Mouse Properties-> Pointer Options -> Show location of pointer when I press the CTRL key)
Is there any good solution rather than just draw a circle on canvas with a storyboard to getting smaller and then disappear ?
You can get the mouse location using Cursor.Position
Then you can draw your circle around the the cursor location.
So if you need it by a key press like with the ctrl scenario you can bind an event listener for key press or if you need something constant you can set an event listener on the mouse move.
Hope it will help
Liron
After some time i did it with that code.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class MouseHook
{
public class MSLLHOOKSTRUCTEventArgs : EventArgs
{
private readonly MSLLHOOKSTRUCT _hookStruct;
public MSLLHOOKSTRUCTEventArgs(MSLLHOOKSTRUCT hookStruct)
{
_hookStruct = hookStruct;
}
public MSLLHOOKSTRUCT HookStruct
{
get { return _hookStruct; }
}
}
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseDown = delegate { };
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseUp = delegate { };
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseMove = delegate { };
public static bool Started { get; set; }
static MouseHook()
{
Started = false;
}
public static void Start()
{
Debug.WriteLine("MouseHook.Start");
_hookID = SetHook(_proc);
Started = true;
}
public static void Stop()
{
Debug.WriteLine("MouseHook.Stop");
UnhookWindowsHookEx(_hookID);
Started = false;
MouseDown = null;
MouseUp = null;
MouseMove = null;
}
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
IntPtr hook = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle("user32"), 0);
if (hook == IntPtr.Zero)
throw new System.ComponentModel.Win32Exception();
return hook;
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
if(MouseDown!=null)
MouseDown(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
else if (MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
{
if (MouseUp != null)
MouseUp(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
else
{
if (MouseMove != null)
MouseMove(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE = 7;
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)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public 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);
}

c# WebBrowser Flash fullscreen - ESC won't exit fullscreen

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.

Categories

Resources