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
Related
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 trying to make a listener for reading data which comes from my barcode scanner.I made a keylogger but it catches keys that come from my laptop keyboard and barcode-scanner . I want to catch data which come only my barcode scanner. I don't know how can i do that so any suggestion can help me.
Here is my SetHook fonction maybe someone knows how can i focus to hid with editing that fonction.
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
Below is the code i have written for the same problem. The code works like,
In HookHandleProc, it is waiting the following keys to be downed in less than 50 ms
private const Keys HK_PRE = Keys.F5; //0x0007;
private const Keys HK_PRE_VALID = Keys.OemOpenBrackets;
If it's done, then we set _hookFlag = true, so again in HookHandleProc, we swallow keys into _buffer till
private const Keys HK_SUFF = Keys.Oemtilde; //0x000A;
So if you program your barcode reader to include these prefix and suffix values, you can know where the data comes from
Here is the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Keys = System.Windows.Forms.Keys;
namespace BarcodeScanner
{
public class CouldntHookException : Exception
{
public override string Message
{
get
{
return "barcode_input_handler couldnt add itself to the hook chain.";
}
}
public override string ToString()
{
return Message;
}
}
public class BarcodeHandler : IDisposable
{
private delegate long delLowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void delInput(string scanCode);
public event delInput InputEvent;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern long SetWindowsHookEx(int idHook,
delLowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(long hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern long CallNextHookEx(long hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
private const Keys HK_PRE = Keys.F5; //0x0007;
private const Keys HK_PRE_VALID = Keys.OemOpenBrackets;
private const Keys HK_SUFF = Keys.Oemtilde; //0x000A;
private long _hHook = 0;
private StringBuilder _buffer;
private bool _hookFlag;
private bool _hookValid;
delLowLevelKeyboardProc _procHook;
taglParam _lastKey;
struct taglParam
{
public int _vkCode, _scanCode, _flags, _time;
public taglParam(int vkCode, int scanCode, int flags, int time)
{ _vkCode = vkCode; _scanCode = scanCode; _flags = flags; _time = time; }
};
public BarcodeHandler()
{
_buffer = new StringBuilder(128);
_hookFlag = false;
_hookValid = false;
_procHook = new delLowLevelKeyboardProc(HookHandleProc);
_hHook = SetHook();
if (_hHook == 0)
throw new CouldntHookException();
}
~BarcodeHandler()
{
Dispose();
}
private long SetHook()
{
using (Process cp = Process.GetCurrentProcess())
using (ProcessModule cm = cp.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, _procHook,
GetModuleHandle(cm.ModuleName), 0);
}
}
private long HookHandleProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0 || wParam != (IntPtr)WM_KEYDOWN)
return CallNextHookEx(_hHook, nCode, wParam, lParam);
taglParam lp = (taglParam)Marshal.PtrToStructure(lParam, typeof(taglParam));
if (_hookFlag)
{
if ((Keys)lp._vkCode == HK_SUFF)
{
_hookFlag = false;
_hookValid = false;
//trigger event here
//use begininvoke instead of invoke ;)
InputEvent.Invoke(_buffer.ToString());
return -1;
}
_buffer.Append((char)lp._vkCode);
return -1;
}
else if ((Keys)lp._vkCode == HK_PRE)
{
_hookValid = true;
_lastKey = lp;
}
else if (_hookValid && (Keys)lp._vkCode == HK_PRE_VALID)
{
if (lp._time - _lastKey._time < 50)
{
_buffer.Clear();
_hookFlag = true;
return -1;
}
else
_hookValid = false;
}
return CallNextHookEx(_hHook, nCode, wParam, lParam);
}
private bool DeleteHook()
{
return UnhookWindowsHookEx(_hHook);
}
public void Dispose()
{
DeleteHook();
GC.SuppressFinalize(this);
}
}
}
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);
}
I want to add a possibility to type Cyrillic letters in my XNA-game.
I can't use default Input.KeyboardState because Input.Keys enum contains only English letters. So, I used keyboard-hook to handle Windows input. But it returns keycode, which can be used for English letters (because ASCII-code matches key-code), but don't work properly with Cyrillic. For "a-я" can be used 848 offset, but for more specific letters, like "і" or "ї" there are different values.
Is there efficient way to convert key-code into Cyrillic letter in ASCII? Or maybe there is solution without nasty keyboard-hook?
BTW, here keyboard-hook class listing:
#region EventArgs
public class CharacterEventArgs : EventArgs
{
private readonly char character;
private readonly int lParam;
private readonly int keyLayout;
public CharacterEventArgs(char character, int lParam, int keyLayout)
{
this.character = character;
this.lParam = lParam;
this.keyLayout = keyLayout;
}
#region Properties
public int KeyLayout
{
get { return keyLayout; }
}
public char Character
{
get { return character; }
}
public int Param
{
get { return lParam; }
}
public int RepeatCount
{
get { return lParam & 0xffff; }
}
public bool ExtendedKey
{
get { return (lParam & (1 << 24)) > 0; }
}
public bool AltPressed
{
get { return (lParam & (1 << 29)) > 0; }
}
public bool PreviousState
{
get { return (lParam & (1 << 30)) > 0; }
}
public bool TransitionState
{
get { return (lParam & (1 << 31)) > 0; }
}
#endregion
}
public class KeyEventArgs : EventArgs
{
private Keys keyCode;
public KeyEventArgs(Keys keyCode)
{
this.keyCode = keyCode;
}
public Keys KeyCode
{
get { return keyCode; }
}
}
#endregion
#region delegats
public delegate void CharEnteredHandler(object sender, CharacterEventArgs e);
public delegate void KeyEventHandler(object sender, KeyEventArgs e);
#endregion
public static class EventInput
{
#region events
/// <summary>
/// Event raised when a character has been entered.
/// </summary>
public static event CharEnteredHandler CharEntered;
/// <summary>
/// Event raised when a key has been pressed down. May fire multiple times due to keyboard repeat.
/// </summary>
public static event KeyEventHandler KeyDown;
/// <summary>
/// Event raised when a key has been released.
/// </summary>
public static event KeyEventHandler KeyUp;
#endregion
delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
static bool initialized;
static IntPtr prevWndProc;
static WndProc hookProcDelegate;
static IntPtr hIMC;
static GameWindow gameWindow;
#region constants
const int GWL_WNDPROC = -4;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_CHAR = 0x102;
const int WM_IME_SETCONTEXT = 0x0281;
const int WM_INPUTLANGCHANGE = 0x51;
const int WM_GETDLGCODE = 0x87;
const int WM_IME_COMPOSITION = 0x10f;
const int DLGC_WANTALLKEYS = 4;
#endregion
#region Win32-functions
//to handle input
[DllImport("Imm32.dll")]
static extern IntPtr ImmGetContext(IntPtr hWnd);
[DllImport("Imm32.dll")]
static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
[DllImport("user32.dll")]
static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
//to get keyboard layout
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowThreadProcessId(
[In] IntPtr hWnd,
[Out, Optional] IntPtr lpdwProcessId
);
[DllImport("user32.dll", SetLastError = true)]
static extern ushort GetKeyboardLayout(
[In] int idThread
);
#endregion
static ushort GetKeyboardLayout()
{
return GetKeyboardLayout(GetWindowThreadProcessId(gameWindow.Handle, IntPtr.Zero));
}
#region Initialize
/// <summary>
/// Initialize the TextInput with the given GameWindow.
/// </summary>
/// <param name="window">The XNA window to which text input should be linked.</param>
public static void Initialize(GameWindow window)
{
if (initialized)
throw new InvalidOperationException("TextInput.Initialize can only be called once!");
gameWindow = window;
hookProcDelegate = new WndProc(HookProc);
prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC,
(int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate));
hIMC = ImmGetContext(window.Handle);
initialized = true;
}
#endregion
static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
switch (msg)
{
case WM_GETDLGCODE:
returnCode = (IntPtr)(returnCode.ToInt32() | DLGC_WANTALLKEYS);
break;
case WM_KEYDOWN:
if (KeyDown != null)
KeyDown(null, new KeyEventArgs((Keys)wParam));
break;
case WM_KEYUP:
if (KeyUp != null)
KeyUp(null, new KeyEventArgs((Keys)wParam));
break;
case WM_CHAR:
if (CharEntered != null)
{
CharEntered(null, new CharacterEventArgs((char) wParam, lParam.ToInt32(), GetKeyboardLayout()));
}
break;
case WM_IME_SETCONTEXT:
if (wParam.ToInt32() == 1)
ImmAssociateContext(hWnd, hIMC);
break;
case WM_INPUTLANGCHANGE:
ImmAssociateContext(hWnd, hIMC);
returnCode = (IntPtr)1;
break;
}
return returnCode;
}
}
Have you considered using Windows Forms for character input? I don't speak Russian, but I can only assume that the KeyPress event must handle Cyrillic correctly in Russian locales, and it would be much simpler than pumping Windows messages yourself.
using System.Windows.Forms;
...
var form = (Form)Form.FromHandle(window.Handle);
form.KeyPress += form_KeyPress;
...
private void form_KeyPress(Object sender, KeyPressEventArgs e)
{
Console.WriteLine(e.KeyChar);
e.Handled = true;
}
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.