- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在使用 InputSimulator v0.1.0.0 模拟远程桌面上的按键和/或鼠标事件。基本按键(例如按“a”)有效,但特殊字符(如“tab”、“enter”)无效。我模拟输入文本:
InputSimulator.SimulateTextEntry("blabla");
但以下仅适用于本地:
InputSimulator.SimulateKeyPress(VirtualKeyCode.TAB);
或
InputSimulator.SimulateKeyPress(VirtualKeyCode.RETURN);
我在网上搜索了工作示例,但没有找到任何有用的东西。有人知道如何让它发挥作用吗?
提前致谢!
------------------------自己的答案-------------------- --------------
再谷歌搜索之后,我找到了这篇文章:
http://www.pinvoke.net/default.aspx/user32.keybd_event
其中有一个很好的代码,它没有解决 InputSimulator 问题,但正是我需要的。这是代码,以及我是如何使用它的:
[StructLayout(LayoutKind.Sequential)]
public struct KEYBOARD_INPUT
{
public const uint Type = 1;
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
};
[StructLayout(LayoutKind.Explicit)]
struct KEYBDINPUT
{
[FieldOffset(0)]
public ushort wVk;
[FieldOffset(2)]
public ushort wScan;
[FieldOffset(4)]
public uint dwFlags;
[FieldOffset(8)]
public uint time;
[FieldOffset(12)]
public IntPtr dwExtraInfo;
};
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
};
[StructLayout(LayoutKind.Explicit)]
struct INPUT
{
[FieldOffset(0)]
public int type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
};
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, IntPtr pInput, int cbSize);
这就是我如何称呼“按 TAB”事件:
keybd_event(0x09, 0x0f, 0, 0); // Tab Press
keybd_event(0x09, 0x0f, 0x0002, 0);
最佳答案
按照建议,我复制我的解决方案作为答案。我希望这些对任何处理类似问题的人有所帮助。 :) 解决方案有点长,但问题不仅是“如何以编程方式按下按钮”,还有“如何通过远程桌面使其工作”和“如何制定通用解决方案”对于不同的键盘'。嗯,我不是 100% 确定最后一个问题已经完全解决,但下面的解决方案可能会用于进一步的开发。我也知道代码不是最优的,有时甚至很丑陋,但我仍在测试和开发它! :)
//m_text is the whole text i want to write. It may contain special characters,
//like 'enter', 'tab', lower/upper-case chars, and chars with shit/alt is
//pressed, like ';'.
//Test with this string, its difficult-enough. :)
string m_text = "123qweQWE;{tab}!{eNTer}*|";
IntPtr keyboardLayout = GetKeyboardLayout(0);
while (!string.IsNullOrWhiteSpace(m_text))
{
int m_Index = 0;
//Enter, tab and similar keys are in {} brackets
//(for example {tab}). We get the 'tab' from the
//string and pass this to our method. Key combinations
//are separated by a '+' like {alt+tab+tab}, from this
//we will get 'press the alt, then press the tab, then
//press the tab again'.
if (m_text[m_Index] == '{')
{
#region [ Special chars ]
string m_SubString = m_text.Substring(
m_Index + 1, m_text.IndexOf("}") - 1);
string[] m_Splitted = m_SubString.Split(new char[] { '+' });
for (int i = 0; i < m_Splitted.Length; i++)
{
//If the string is longer than 1 char it means we are processing a tab-like key.
if (m_Splitted[i].Length > 1)
PressSpecial(m_Splitted[i]);
else
{
//If the char is 1-char-long, it means we previously pressed a tab-like key,
//and now we press a simple key, like in the case of {altgr+w}.
//Get the virtual key of the char.
short vKey = VkKeyScanEx(
char.Parse(m_Splitted[i]), keyboardLayout);
//Get the low byte from the virtual key.
byte m_LOWBYTE = (Byte)(vKey & 0xFF);
//Get the scan code of the key.
byte sScan = (byte)MapVirtualKey(m_LOWBYTE, 0);
//Press the key.
//Key down event, as indicated by the 3rd parameter that is 0.
keybd_event(m_LOWBYTE, sScan, 0, 0);
}
}
Application.DoEvents();
//We have pressed all the keys we wanted, now release them in backward-order
//when pressing alt+tab we beed to release them in tab-alt order! The logic is the same.
for (int i = m_Splitted.Length - 1; i > -1; i--)
{
if (m_Splitted[i].Length > 1)
ReleaseSpecial(m_Splitted[i]);
else
{
short vKey = VkKeyScanEx(
char.Parse(m_Splitted[i]), keyboardLayout);
byte m_LOWBYTE = (Byte)(vKey & 0xFF);
byte sScan = (byte)MapVirtualKey(m_LOWBYTE, 0);
//Key up event, as indicated by the 3rd parameter that is 0x0002.
keybd_event(m_LOWBYTE, sScan, 0x0002, 0); //Key up
}
}
Application.DoEvents();
#endregion
//We do not use the '{' and '}' brackets, thats why the '+2'. :)
m_Index = m_SubString.Length + 2;
}
else
{
#region [ One char ]
short vKey = VkKeyScanEx(m_text[m_Index], keyboardLayout);
//Hi-byte indicates if we need to press shift, alt or other similar keys.
byte m_HIBYTE = (Byte)(vKey >> 8);
byte m_LOWBYTE = (Byte)(vKey & 0xFF);
byte sScan = (byte)MapVirtualKey(m_LOWBYTE, 0);
//Press the special key if needed.
if ((m_HIBYTE == 1))
PressShift();
else if ((m_HIBYTE == 2))
PressControl();
else if ((m_HIBYTE == 4))
PressAlt();
else if ((m_HIBYTE == 6))
PressAltGr();
//Press, then release the key.
keybd_event(m_LOWBYTE, sScan, 0, 0); //Key down
keybd_event(m_LOWBYTE, sScan, 0x0002, 0); //Key up
//Release the special key if needed.
if ((m_HIBYTE == 1))
ReleaseShift();
else if ((m_HIBYTE == 2))
ReleaseControl();
else if ((m_HIBYTE == 4))
ReleaseAlt();
else if ((m_HIBYTE == 6))
ReleaseAltGr();
#endregion
//Get the next char from the string.
m_Index++;
}
//Remove the already processed chars from the string.
if (m_Index < m_text.Length)
m_text = m_text.Substring(m_Index);
else
m_text = string.Empty;
}
所以,这就是处理字符串的逻辑。让我们看看将处理事件的辅助方法:
按下和释放特殊键是一样的,只是前两个参数不同。查看msdn获取enter,tab,alt,altgr等的虚拟和扫码...
#region [ Press shift ]
private void PressShift()
{
//0xA0 is the virtual key of 'shift'.
//0x2A is the scan code of 'shift'.
keybd_event(0xA0, 0x2A, 0, 0);
}
#endregion
#region [ Release shift ]
private void ReleaseShift()
{
keybd_event(0xA0, 0x2A, 0x0002, 0);
}
#endregion
PressSpecial 与上面的代码类似,所以它也可以用于shift。我将其中的一些分成不同的方法,因为对我来说更容易看到我在代码中使用的内容(对我来说使用'PressShift();'而不是'PressSpecial(“shift”)';更容易)。 :)
private void PressSpecial(string p_Special)
{
switch (p_Special.ToLower()) //<-- use lower version!
{
case "home":
keybd_event(0x24, 0x47, 0, 0);
break;
case "end":
keybd_event(0x23, 0x4F, 0, 0);
break;
//Do the same for any key you need (enter, tab, page up, etc...).
//Remember to get the proper virtual- and scan codes for each keys!
}
}
ReleaseSpecial 与PressSpecial 相同,但第3 个参数为0x0002。
private void ReleaseSpecial(string p_Special)
{
switch (p_Special.ToLower())
{
case "home":
keybd_event(0x24, 0x47, 0x0002, 0);
break;
case "end":
keybd_event(0x23, 0x4F, 0x0002, 0);
break;
}
}
最后,这里是 dll 导入方法。如果您愿意,可以将它们放入静态类中:
[DllImport("user32.dll", EntryPoint = "keybd_event", CharSet = CharSet.Auto,
ExactSpelling = true)]
public static extern void keybd_event(byte vk, byte scan, int flags, int extrainfo);
[DllImport("user32.dll")]
public static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
public static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MapVirtualKey(int uCode, int uMapType);
关于c# - 如何使用InputSimulator模拟远程桌面上的特定按键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17525377/
我正在使用 InputSimulator 来模拟按键和鼠标点击。到目前为止,我测试过的每个键都可以使用,但鼠标按钮除外。我这样发送它们: private void button2_Click(obje
我想模拟外部程序的键盘点击。我试过 SendMessage、PostMessage、SendKeys,但它们不会将键发送到一个特定程序。所以我想试试 SendInput,我已经为 SendInput
我正在努力弄清楚为什么下面的函数只会将我的鼠标从 0、0 屏幕坐标移动到我的最终目的地,即使 Cursor.Position 正在返回正确的屏幕坐标。如果有人能启发我,我将不胜感激。 public v
在 Visual Studio 2013 中,我安装了一个名为“InputSimulator”的 C# 包。这样做之后,我看到一个名为“WindowsInput”的新引用被添加到我的项目中。 (即 W
我是一名优秀的程序员,十分优秀!