I have a situation where I'm trying to send a mouse-click when the ctrl key is pressed.
What I'm finding is that the application that receives the mouse click event is interpreting the ctrl key as down.
What can I do to release the ctrl key in my code before sending my mouse event?
I'm using mouse_event to send the LeftDown message, if that's a useful clue.
Thanks!
Return true from this overridden method in your control if you want to prevent the default behaviour:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Ctrl)
{
//send mouse event
return true;
}
}
Try using keybd_event() before using mouse_event:
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int extraInfo);
[DllImport("user32.dll")]
static extern short MapVirtualKey(int wCode, int wMapType);
// ...
keybd_event((int)Keys.ControlKey, (byte)MapVirtualKey((int)Keys.ControlKey, 0), 2, 0); // Control Up
// ... call mouse_event() ...
Thanks for the answers. I was afraid that someone would assume I was working with a WinForms control :)
I found the Windows Input Simulator library (http://inputsimulator.codeplex.com/) was able to get me what I needed. I use that to send the "key up" message before I do the "mouse down" message, and everything works great.
Thanks again for the answers!
I couldn't find any solution except moving the cursor by Cursor class, clicking with mouse_event then moving the cursor to its old position. I am playing with SendInput function right now but still no chance for a good solution. Any advice?
You should use Win32 API.
Use pInvoked SendMessage from user32.dll
pInvoked Function
Then read about mouse events:
Mouse Input on msdn
And then read about: System events and Mouse Mess.......
Also there is lots of info:
Info
Here's an example following the approach Hooch suggested.
I created a form which contains 2 buttons. When you click upon the first button, the position of the second button is resolved (screen coördinates). Then a handle for this button is retrieved. Finally the SendMessage(...) (PInvoke) function is used to send a click event without moving the mouse.
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "WindowFromPoint",
CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr WindowFromPoint(Point point);
private const int BM_CLICK = 0x00F5;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Specify the point you want to click
var screenPoint = this.PointToScreen(new Point(button2.Left,
button2.Top));
// Get a handle
var handle = WindowFromPoint(screenPoint);
// Send the click message
if (handle != IntPtr.Zero)
{
SendMessage( handle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
}
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Hi", "There");
}
}
I couldn't find any solution except moving the cursor by Cursor class, clicking with mouse_event then moving the cursor to its old position. I am playing with SendInput function right now but still no chance for a good solution. Any advice?
You should use Win32 API.
Use pInvoked SendMessage from user32.dll
pInvoked Function
Then read about mouse events:
Mouse Input on msdn
And then read about: System events and Mouse Mess.......
Also there is lots of info:
Info
Here's an example following the approach Hooch suggested.
I created a form which contains 2 buttons. When you click upon the first button, the position of the second button is resolved (screen coördinates). Then a handle for this button is retrieved. Finally the SendMessage(...) (PInvoke) function is used to send a click event without moving the mouse.
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "WindowFromPoint",
CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr WindowFromPoint(Point point);
private const int BM_CLICK = 0x00F5;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Specify the point you want to click
var screenPoint = this.PointToScreen(new Point(button2.Left,
button2.Top));
// Get a handle
var handle = WindowFromPoint(screenPoint);
// Send the click message
if (handle != IntPtr.Zero)
{
SendMessage( handle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
}
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Hi", "There");
}
}
As stated in title, I have a form that doesn't have any control on itself (so I can't focus it!!! damn).
I keep it controlless because I need to show images on background and I need to move it by keeping mouse clicked.
Are there any way to detect the keyup event when this is the foreground window?should I use a global hook (and check which is the foreground image obviusly)?
Any simplier workaround?I tested with an hidden control but it's not working.
The problem of putting a control with opacity = 0 brings the possibility to "miss" the MouseDown and MouseUp events (because they could happen over the control instead of the form, but I can still redirect them)
Any suggestion?
Here is the question where I picked some resources:
Fire Form KeyPress event
Can't you just set the Form's KeyPreview to true and use the Form's KeyUp Event? (or am i missing something?)
I would override OnKeyUp as it seems to be exactly what you are asking for. Here is an example of popping up a Message Box when the Escape key is released.
protected override void OnKeyUp(KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("Escape was pressed");
e.Handled = true;
}
base.OnKeyUp(e);
}
It looks that you are seeking for GlobalHook. Please have a look at SetWindowsHookEx Native Api. You can easily write your Pinvoke statements.
Here is an example from pinvoke.net
using System.Windows.Forms;
public class MyClass
{
private HookProc myCallbackDelegate = null;
public MyClass()
{
// initialize our delegate
this.myCallbackDelegate = new HookProc(this.MyCallbackFunction);
// setup a keyboard hook
SetWindowsHookEx(HookType.WH_KEYBOARD, this.myCallbackDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
}
[DllImport("user32.dll")]
protected static extern IntPtr SetWindowsHookEx(HookType code, HookProc func, IntPtr hInstance, int threadID);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private int MyCallbackFunction(int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0) {
//you need to call CallNextHookEx without further processing
//and return the value returned by CallNextHookEx
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
// we can convert the 2nd parameter (the key code) to a System.Windows.Forms.Keys enum constant
Keys keyPressed = (Keys)wParam.ToInt32();
Console.WriteLine(keyPressed);
//return the value returned by CallNextHookEx
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
}
Okay, so basically I want to be able to retrieve keyboard text. Like entering text into a text field or something. I'm only writing my game for windows.
I've disregarded using Guide.BeginShowKeyboardInput because it breaks the feel of a self contained game, and the fact that the Guide always shows XBOX buttons doesn't seem right to me either. Yes it's the easiest way, but I don't like it.
Next I tried using System.Windows.Forms.NativeWindow. I created a class that inherited from it, and passed it the Games window handle, implemented the WndProc function to catch WM_CHAR (or WM_KEYDOWN) though the WndProc got called for other messages, WM_CHAR and WM_KEYDOWN never did. So I had to abandon that idea, and besides, I was also referencing the whole of Windows forms, which meant unnecessary memory footprint bloat.
So my last idea was to create a Thread level, low level keyboard hook. This has been the most successful so far. I get WM_KEYDOWN message, (not tried WM_CHAR yet) translate the virtual keycode with Win32 funcation MapVirtualKey to a char. And I get my text! (I'm just printing with Debug.Write at the moment)
A couple problems though. It's as if I have caps lock on, and an unresponsive shift key. (Of course it's not however, it's just that there is only one Virtual Key Code per key, so translating it only has one output) and it adds overhead as it attaches itself to the Windows Hook List and isn't as fast as I'd like it to be, but the slowness could be more due to Debug.Write.
Has anyone else approached this and solved it, without having to resort to an on screen keyboard? or does anyone have further ideas for me to try?
thanks in advance.
Question asked by Jimmy
Maybe I'm not understanding the question, but why can't you use the XNA Keyboard and KeyboardState classes?
My comment:
It's because though you can read keystates, you can't get access to typed text as and how it is typed by the user.
So let me further clarify. I want to implement being able to read text input from the user as if they are typing into textbox is windows. The keyboard and KeyboardState class get states of all keys, but I'd have to map each key and combination to it's character representation. This falls over when the user doesn't use the same keyboard language as I do especially with symbols (my double quotes is shift + 2, while american keyboards have theirs somewhere near the return key).
it seems my window hook was the way to go, just the reason I wasn't getting WM_CHAR is because the XNA message pump doesn't do translate message.
Adding TranslateMessage in whenever I received a WM_KEYDOWN message meant I got my WM_CHAR message, I then used this to fire a character typed event in my MessageHook class which my KeyboardBuffer class had subscribed to, which then buffers that to a text buffer :D (or StringBuilder, but the result is the same)
So I have it all working as I want.
Many thanks to Jimmy for a link to a very informative thread.
For adding a windows hook in XNA
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
/* Author: Sekhat
*
* License: Public Domain.
*
* Usage:
*
* Inherit from this class, and override the WndProc function in your derived class,
* in which you handle your windows messages.
*
* To start recieving the message, create an instance of your derived class, passing in the
* window handle of the window you want to listen for messages for.
*
* in XNA: this would be the Game.Window.Handle property
* in Winforms Form.Handle property
*/
namespace WindowsHookExample
{
public abstract class WindowsHook : IDisposable
{
IntPtr hHook;
IntPtr hWnd;
// Stored here to stop it from getting garbage collected
Win32.WndProcDelegate wndProcDelegate;
public WindowsHook(IntPtr hWnd)
{
this.hWnd = hWnd;
wndProcDelegate = WndProcHook;
CreateHook();
}
~WindowsHook()
{
Dispose(false);
}
private void CreateHook()
{
uint threadId = Win32.GetWindowThreadProcessId(hWnd, IntPtr.Zero);
hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_CALLWNDPROC, wndProcDelegate, IntPtr.Zero, threadId);
}
private int WndProcHook(int nCode, IntPtr wParam, ref Win32.Message lParam)
{
if (nCode >= 0)
{
Win32.TranslateMessage(ref lParam); // You may want to remove this line, if you find your not quite getting the right messages through. This is here so that WM_CHAR is correctly called when a key is pressed.
WndProc(ref lParam);
}
return Win32.CallNextHookEx(hHook, nCode, wParam, ref lParam);
}
protected abstract void WndProc(ref Win32.Message message);
#region Interop Stuff
// I say thankya to P/Invoke.net.
// Contains all the Win32 functions I need to deal with
protected static class Win32
{
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
}
public struct Message
{
public IntPtr lparam;
public IntPtr wparam;
public uint msg;
public IntPtr hWnd;
}
/// <summary>
/// Defines the windows proc delegate to pass into the windows hook
/// </summary>
public delegate int WndProcDelegate(int nCode, IntPtr wParam, ref Message m);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowsHookEx(HookType hook, WndProcDelegate callback,
IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref Message m);
[DllImport("coredll.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string module);
[DllImport("user32.dll", EntryPoint = "TranslateMessage")]
public extern static bool TranslateMessage(ref Message m);
[DllImport("user32.dll")]
public extern static uint GetWindowThreadProcessId(IntPtr window, IntPtr module);
}
#endregion
#region IDisposable Members
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
if (disposing)
{
// Free managed resources here
}
// Free unmanaged resources here
if (hHook != IntPtr.Zero)
{
Win32.UnhookWindowsHookEx(hHook);
}
}
#endregion
}
}
I used the solution from this gamedev.net post and it works great :)
Here's a simple way, IMO, to have the space, back, A-Z and then the special chars !,#,#,$,%,^,&,*,(,). (Note, you need to import System.Linq) Here are the fields:
Keys[] keys;
bool[] IskeyUp;
string[] SC = { ")" , "!", "#", "#", "$", "%", "^", "&", "*", "("};//special characters
Constructor:
keys = new Keys[38];
Keys[] tempkeys;
tempkeys = Enum.GetValues(typeof(Keys)).Cast<Keys>().ToArray<Keys>();
int j = 0;
for (int i = 0; i < tempkeys.Length; i++)
{
if (i == 1 || i == 11 || (i > 26 && i < 63))//get the keys listed above as well as A-Z
{
keys[j] = tempkeys[i];//fill our key array
j++;
}
}
IskeyUp = new bool[keys.Length]; //boolean for each key to make the user have to release the key before adding to the string
for (int i = 0; i < keys.Length; i++)
IskeyUp[i] = true;
And Finally, the update method:
string result = "";
public override void Update(GameTime gameTime)
{
KeyboardState state = Keyboard.GetState();
int i = 0;
foreach (Keys key in keys)
{
if (state.IsKeyDown(key))
{
if (IskeyUp[i])
{
if (key == Keys.Back && result != "") result = result.Remove(result.Length - 1);
if (key == Keys.Space) result += " ";
if (i > 1 && i < 12)
{
if (state.IsKeyDown(Keys.RightShift) || state.IsKeyDown(Keys.LeftShift))
result += SC[i - 2];//if shift is down, and a number is pressed, using the special key
else result += key.ToString()[1];
}
if (i > 11 && i < 38)
{
if (state.IsKeyDown(Keys.RightShift) || state.IsKeyDown(Keys.LeftShift))
result += key.ToString();
else result += key.ToString().ToLower(); //return the lowercase char is shift is up.
}
}
IskeyUp[i] = false; //make sure we know the key is pressed
}
else if (state.IsKeyUp(key)) IskeyUp[i] = true;
i++;
}
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
}
Hopefull this well help. I personally thought it was easier to use than the hooks, and this also can easily be modified for special results (such as shuffling the keys).
Maybe I'm not understanding the question, but why can't you use the XNA Keyboard and KeyboardState classes?
This page is on top of google result about WM_CHAR interception in xna, so i leave here some note. Maybe this will be useful for other (if they will be able to understand my English =)) ).
I try code with windowshook from Sekhat, but seems there should be WH_GETMESSAGE passed to SetWindowsHookEx instead Win32.HookType.WH_CALLWNDPROC (only with WH_GETMESSAGE code lparaw will point to Win32.Message ).
Also there is sometime duplicated messages (with wparam 0).
(look here - http://msdn.microsoft.com/en-us/library/ms644981%28v=VS.85%29.aspx
something about PM_NOREMOVE/PM_REMOVE in WPARAM )
When i add something like this
if (nCode >= 0 && wParam == 1)
{
Win32.TranslateMessage(ref lParam);
WndProc(ref lParam);
}
wm_keypress wm_char duplication stopped (i supose 1 is PM_NOREMOVE or PM_REMOVE).
P.S.
nuclex variant now show 404 page, but can be viewed with webarchive.
nuclex variant works, but it cause broken mouseWheel processing from native XNA MouseState (on XNA 3.1) =(