首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用InputSimulator在远程桌面上模拟特定的按键?

如何使用InputSimulator在远程桌面上模拟特定的按键?
EN

Stack Overflow用户
提问于 2013-07-08 19:22:11
回答 1查看 9K关注 0票数 2

我目前正在使用InputSimulator v0.1.0.0来模拟远程桌面上的按键和/或鼠标事件。基本的按键(例如按'a')可以,但像'tab','enter‘这样的特殊字符就不行了。我使用以下命令模拟输入文本:

代码语言:javascript
复制
InputSimulator.SimulateTextEntry("blabla");

但以下操作仅在本地有效:

代码语言:javascript
复制
InputSimulator.SimulateKeyPress(VirtualKeyCode.TAB);

代码语言:javascript
复制
InputSimulator.SimulateKeyPress(VirtualKeyCode.RETURN);

我在网上搜索了工作示例,但没有找到任何有用的东西。有谁知道怎么让它工作吗?

提前感谢!

在谷歌了更多之后,我找到了这篇文章:

http://www.pinvoke.net/default.aspx/user32.keybd_event

其中有一个很好的代码,它不能解决InputSimulator问题,但恰好能解决我需要的问题。下面是代码,以及我是如何使用它的:

代码语言:javascript
复制
[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);

这就是我如何命名'press TAB‘事件的:

代码语言:javascript
复制
keybd_event(0x09, 0x0f, 0, 0); // Tab Press

keybd_event(0x09, 0x0f, 0x0002, 0);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-15 17:05:09

按照建议,我复制我的解决方案作为答案。我希望这些对任何解决类似问题的人都有帮助。:)解决方案有点长,但问题不仅仅是“如何通过编程按下按钮”,还有“如何通过远程桌面工作”和“如何为不同的键盘制作通用解决方案”。好吧,我不是百分之百确定最后一个问题是完全解决的,但是下面的解决方案可以用于进一步的开发。我也知道代码并不是最优的,有时甚至很难看,但我仍然在测试和开发它!:)

代码语言:javascript
复制
//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以获取回车、制表符、alt、altgr等的虚拟和扫描代码...

代码语言:javascript
复制
#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”);更容易)。:)

代码语言:javascript
复制
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相同,但第三个参数是0x0002。

代码语言:javascript
复制
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导入方法。如果愿意,您可以将它们放入静态类中:

代码语言:javascript
复制
[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);
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17525377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档