Sending specific keys on the Numpad like +, -, / or Enter (simulating a keypress)
I am working on a project where it is necessary to simulate key-presses to cause specific behaviours in a different application.
All is running well and fine, using the keybd_event function that is being imported (there might be better ways, but it is working fine).
Now I want to add specific support for all of the numpad.
Looking e. g. here http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx or in the System.Windows.Input.Key namespace, I can easily find keys for Num0..Num9, as well as for NumLock. But.. I cannot find anything for Num/, Num+, NumEnter etc.
I wrote a quick froms app to catch the keydown event, outputting the event paramters, and got some interesting results:
e.KeyCode NumLock e.KeyData NumLock e.KeyValue 144 e.Modifiers None
e.KeyCode Divide e.KeyData Divide e.KeyValue 111 e.Modifiers None
e.KeyCode Multiply e.KeyData Multiply e.KeyValue 106 e.Modifiers None
e.KeyCode Subtract e.KeyData Subtract e.KeyValue 109 e.Modifiers None 开发者_开发问答
e.KeyCode Add e.KeyData Add e.KeyValue 107 e.Modifiers None
e.KeyCode NumLock e.KeyData NumLock e.KeyValue 144 e.Modifiers None
e.KeyCode NumLock e.KeyData NumLock e.KeyValue 144 e.Modifiers None
e.KeyCode Divide e.KeyData Divide e.KeyValue 111 e.Modifiers None
e.KeyCode Multiply e.KeyData Multiply e.KeyValue 106 e.Modifiers None
e.KeyCode Subtract e.KeyData Subtract e.KeyValue 109 e.Modifiers None
e.KeyCode Add e.KeyData Add e.KeyValue 107 e.Modifiers None
e.KeyCode Return e.KeyData Return e.KeyValue 13 e.Modifiers None
The Num+ Key (and so on) seem to be keys that Windows calls function keys (like F18 for the Num+ key). So.. that is strange, but ok.
But.. I cannot distinguish the Enter-Key from the NumEnter Key. Those are different for my application, so I have to send specific key-codes for both.
And that is my question: how can I send an ordinary enter-key and how can I send a NumEnter key?
(I don't know whether it makes any difference, I am on a German keyboard layout.)
Thx for any ideas!
I found this here works for me !
protected override void WndProc(ref Message m)
{
if (m.Msg == 256 && m.WParam.ToInt32() == 13)
{ // WM_KEYDOWN == 256, Enter == 13
if ((m.LParam.ToInt32() >> 24) == 0)
{
MessageBox.Show("main enter pressed!");
}
else
{
MessageBox.Show("numpad enter pressed!");
}
}
else
{
base.WndProc(ref m);
}
}
thanks to andreas for providing the beginning of a solution. here's a more complete version:
[DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern bool GetGUIThreadInfo(uint idThread, out GUITHREADINFO lpgui);
public struct GUITHREADINFO
{
public int cbSize;
public int flags;
public int hwndActive;
public int hwndFocus;
public int hwndCapture;
public int hwndMenuOwner;
public int hwndMoveSize;
public int hwndCaret;
public System.Drawing.Rectangle rcCaret;
}
private void sendNumpadEnter()
{
bool keyDown = true; // true = down, false = up
const uint WM_KEYDOWN = 0x0100;
const uint WM_KEYUP = 0x0101;
const int VK_RETURN = 0x0D;
IntPtr handle = IntPtr.Zero;
// Obtain the handle of the foreground window (active window and focus window are only relative to our own thread!!)
IntPtr foreGroundWindow = GetForegroundWindow();
// now get process id of foreground window
uint processID;
uint threadID = GetWindowThreadProcessId(foreGroundWindow, out processID);
if (processID != 0)
{
// now get element with (keyboard) focus from process
GUITHREADINFO threadInfo = new GUITHREADINFO();
threadInfo.cbSize = Marshal.SizeOf(threadInfo);
GetGUIThreadInfo(threadID, out threadInfo);
handle = (IntPtr)threadInfo.hwndFocus;
}
int lParam = 1 << 24; // this specifies NumPad key (extended key)
lParam |= (keyDown) ? 0 : (1 << 30 | 1 << 31); // mark key as pressed if we use keyup message
PostMessage(handle, (keyDown) ? WM_KEYDOWN : WM_KEYUP, VK_RETURN, lParam); // send enter
}
Since you are talking about a the-other-way-round solution, detecting the event, and I want to raise it, I don't even have to override the WndProc. I can simply send my own messages.
From your solution, I had a look at SendMessage/PostMessage, and then WM_KEYDOWN and WM_KEYUP. The documentation actually gives you the info (if you look really really hard).
http://msdn.microsoft.com/en-us/library/ms646280(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/ms646281(v=vs.85).aspx
So my solution (compiles and now with finding the right window (where to enter the text)) is like this:
bool keyDown = true; // true = down, false = up
const uint WM_KEYDOWN = 0x0100;
const uint WM_KEYUP = 0x0101;
const int VK_RETURN = 0x0D;
IntPtr handle = IntPtr.Zero;
// Obtain the handle of the foreground window (active window and focus window are only relative to our own thread!!)
IntPtr foreGroundWindow = GetForegroundWindow();
// now get process id of foreground window
uint processID;
uint threadID = GetWindowThreadProcessId(foreGroundWindow, out processID);
if (processID != 0)
{
// now get element with (keyboard) focus from process
GUITHREADINFO threadInfo = new GUITHREADINFO();
threadInfo.cbSize = Marshal.SizeOf(threadInfo);
GetGUIThreadInfo(threadID, out threadInfo);
handle = (IntPtr)threadInfo.hwndFocus;
}
int lParam = 1 << 24; // this specifies NumPad key (extended key)
lParam |= (keyDown) ? 0 : (1 << 30 | 1 << 31); // mark key as pressed if we use keyup message
PostMessage(handle, (keyDown) ? WM_KEYDOWN : WM_KEYUP, VK_RETURN, lParam); // send enter
Hope it is useful to someone else as well. As was Vendetta's tip to me.
And.. if you do have a better solution, please say so!
精彩评论