适用于 Citrix 的 SendKeys 替代方案

发布于 2024-10-17 14:31:21 字数 2151 浏览 1 评论 0原文

我最近为客户开发了一个虚拟键盘应用程序。该程序几乎适用于所有程序,但某些命令(如 {ENTER}{DEL})不适用于 Citrix。是否有 SendKeys 的解决方法或替代方案?

编辑1:我尝试了SendInput方法(Windows输入模拟器使用SendInput),DEL键以及箭头键仍然不起作用。但是 ENTER 键可以使用。

编辑2:解决了。使用两个不同版本的 Citrix 进行测试。 这个问题对我帮助很大。

Citrix 瘦客户端使用扫描码 keybd_event 的参数,即使 MS 说 它未使用,应该为 0。您需要 还提供物理扫描码 以便 Citrix 客户端获取它。 Citrix客户端也有重大问题 与生成的键盘输入 发送输入API。

我修补了 Windows 输入模拟器 中的代码:

// Function used to get the scan code
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);


/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press</param>
public static void SimulateKeyPress(VirtualKeyCode keyCode)
{
    var down = new INPUT();
    down.Type = (UInt32)InputType.KEYBOARD;
    down.Data.Keyboard = new KEYBDINPUT();
    down.Data.Keyboard.Vk = (UInt16)keyCode;
    // Scan Code here, was 0
    down.Data.Keyboard.Scan = (ushort) MapVirtualKey((UInt16)keyCode, 0);
    down.Data.Keyboard.Flags = 0;
    down.Data.Keyboard.Time = 0;
    down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

    var up = new INPUT();
    up.Type = (UInt32)InputType.KEYBOARD;
    up.Data.Keyboard = new KEYBDINPUT();
    up.Data.Keyboard.Vk = (UInt16)keyCode;
    // Scan Code here, was 0
    up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
    up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KEYUP;
    up.Data.Keyboard.Time = 0;
    up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

    INPUT[] inputList = new INPUT[2];
    inputList[0] = down;
    inputList[1] = up;

    var numberOfSuccessfulSimulatedInputs = SendInput(2, 
         inputList, Marshal.SizeOf(typeof(INPUT)));
    if (numberOfSuccessfulSimulatedInputs == 0) 
       throw new Exception(
       string.Format("The key press simulation for {0} was not successful.", 
       keyCode));
}

I recently developed a virtual keyboard application for a customer. The program is working fine with almost all programs, but certain commands like {ENTER} or {DEL} are not working with Citrix. Is there are workaround or an alternative to SendKeys?

Edit 1: I tried the SendInput method (Windows Input Simulator uses SendInput) and the DEL key as well as the arrow keys are still not working. The ENTER key works however.

Edit 2: Solved it. Tested with two different versions of Citrix. This question helped me a lot.:

Citrix thin clients uses the scancode
param of keybd_event even when MS says
it is unused and should be 0. You need
to supply the physical scancode aswell
for the citrix client to get it.
Citrix client also has major problem
with keyboard input generated with the
SendInput API.

I patched the code in Windows Input Simulator:

// Function used to get the scan code
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);


/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press</param>
public static void SimulateKeyPress(VirtualKeyCode keyCode)
{
    var down = new INPUT();
    down.Type = (UInt32)InputType.KEYBOARD;
    down.Data.Keyboard = new KEYBDINPUT();
    down.Data.Keyboard.Vk = (UInt16)keyCode;
    // Scan Code here, was 0
    down.Data.Keyboard.Scan = (ushort) MapVirtualKey((UInt16)keyCode, 0);
    down.Data.Keyboard.Flags = 0;
    down.Data.Keyboard.Time = 0;
    down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

    var up = new INPUT();
    up.Type = (UInt32)InputType.KEYBOARD;
    up.Data.Keyboard = new KEYBDINPUT();
    up.Data.Keyboard.Vk = (UInt16)keyCode;
    // Scan Code here, was 0
    up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
    up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KEYUP;
    up.Data.Keyboard.Time = 0;
    up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

    INPUT[] inputList = new INPUT[2];
    inputList[0] = down;
    inputList[1] = up;

    var numberOfSuccessfulSimulatedInputs = SendInput(2, 
         inputList, Marshal.SizeOf(typeof(INPUT)));
    if (numberOfSuccessfulSimulatedInputs == 0) 
       throw new Exception(
       string.Format("The key press simulation for {0} was not successful.", 
       keyCode));
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

醉生梦死 2024-10-24 14:31:21

尝试使用 Windows 输入模拟器。 不确定它是否支持 Citrix,但它比 SendKeys 更强大。

Try using Windows Input Simulator. Not sure if it supports Citrix but it is much more powerfull compared to SendKeys.

无法回应 2024-10-24 14:31:21

尝试通过 P-Invoke 签名利用 API 调用(内容已编辑:这是现在的工作示例 - 我通过单击按钮将字符“a”发送到文本框):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime;
using System.Runtime.InteropServices;

namespace Test2
{
    public partial class Form1 : Form
    {
        [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);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Focus();
            INPUT Input = new INPUT();

            Input.type = 1;
            Input.ki.wVk = 0x41;  //ASCII for letter 'A'
            Input.ki.dwFlags = 0;  //Key is pressed down
            Input.ki.dwExtraInfo = IntPtr.Zero;
            IntPtr pInput;
            pInput = Marshal.AllocHGlobal(Marshal.SizeOf(Input));

            Marshal.StructureToPtr(Input, pInput, false);
            SendInput(1, pInput, Marshal.SizeOf(Input));
            Input.ki.dwFlags = 2;  //Key is released on the keyboard

            Marshal.StructureToPtr(Input, pInput, false);
            SendInput(1, pInput, Marshal.SizeOf(Input));
        }
    }
}

Try to utilize API call wia P-Invoke signature (Content edited: this is now working example - I'm sending character 'a' to the textBox, on the click of a button) :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime;
using System.Runtime.InteropServices;

namespace Test2
{
    public partial class Form1 : Form
    {
        [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);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Focus();
            INPUT Input = new INPUT();

            Input.type = 1;
            Input.ki.wVk = 0x41;  //ASCII for letter 'A'
            Input.ki.dwFlags = 0;  //Key is pressed down
            Input.ki.dwExtraInfo = IntPtr.Zero;
            IntPtr pInput;
            pInput = Marshal.AllocHGlobal(Marshal.SizeOf(Input));

            Marshal.StructureToPtr(Input, pInput, false);
            SendInput(1, pInput, Marshal.SizeOf(Input));
            Input.ki.dwFlags = 2;  //Key is released on the keyboard

            Marshal.StructureToPtr(Input, pInput, false);
            SendInput(1, pInput, Marshal.SizeOf(Input));
        }
    }
}
方觉久 2024-10-24 14:31:21

我还尝试使用 Windows InputSimulator 库控制 Citrix 应用程序。上面的代码看起来很有希望,因此我将其更新为与最新版本的 InputSimulator 一起使用(其中您使用 sim.Keyboard.Keypress 而不是 InputSimulator.SimulateKeyPress)。这是我添加到 InputSimulator 的代码,我很高兴地报告它按预期工作,并解决了我以前认为不可能的问题。非常感谢。

在 IKeyboardSimulator.cs 中:

    /// <summary>
    /// Simulates the key press gesture for the specified key.
    /// </summary>
    /// <param name="keyCode">The <see cref="VirtualKeyCode"/> for the key.</param>
    IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode);

在 KeyboardSimulator.cs 中:

    using System.Runtime.InteropServices;

    .
    .
    .

    // CITRIX HACK
    // Function used to get the scan code
    [DllImport("user32.dll")]
    static extern uint MapVirtualKey(uint uCode, uint uMapType);

    [DllImport("User32.dll")]
    private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] input, int structSize);


    /// <summary>
    /// Calls the Win32 SendInput method ...
    /// </summary>
    /// <param name="keyCode">The VirtualKeyCode to press</param>
    public IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode) //prev public static void
    {
        var down = new INPUT();
        down.Type = (UInt32)InputType.Keyboard;
        down.Data.Keyboard = new KEYBDINPUT();
        down.Data.Keyboard.KeyCode = (UInt16)keyCode; //prev .Keyboard.Vk
        // Scan Code here, was 0
        down.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
        down.Data.Keyboard.Flags = 0;
        down.Data.Keyboard.Time = 0;
        down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        var up = new INPUT();
        up.Type = (UInt32)InputType.Keyboard;
        up.Data.Keyboard = new KEYBDINPUT();
        up.Data.Keyboard.KeyCode = (UInt16)keyCode;
        // Scan Code here, was 0
        up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
        up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KeyUp;
        up.Data.Keyboard.Time = 0;
        up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        INPUT[] inputList = new INPUT[2];
        inputList[0] = down;
        inputList[1] = up;

        var numberOfSuccessfulSimulatedInputs = SendInput(2,
             inputList, Marshal.SizeOf(typeof(INPUT)));
        if (numberOfSuccessfulSimulatedInputs == 0)
            throw new Exception(
            string.Format("The key press simulation for {0} was not successful.",
            keyCode));
        return this;
    }

I'm also attempting to control a citrix application using the windows InputSimulator library. Your code above looked promising, so I updated it to work with the latest version of InputSimulator (where you use sim.Keyboard.Keypress rather than InputSimulator.SimulateKeyPress). Here is the code that I added to InputSimulator, and I am delighted to report that it works as expected, and solves a problem that I previously thought was not possible. Thanks so much.

In IKeyboardSimulator.cs:

    /// <summary>
    /// Simulates the key press gesture for the specified key.
    /// </summary>
    /// <param name="keyCode">The <see cref="VirtualKeyCode"/> for the key.</param>
    IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode);

In KeyboardSimulator.cs:

    using System.Runtime.InteropServices;

    .
    .
    .

    // CITRIX HACK
    // Function used to get the scan code
    [DllImport("user32.dll")]
    static extern uint MapVirtualKey(uint uCode, uint uMapType);

    [DllImport("User32.dll")]
    private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] input, int structSize);


    /// <summary>
    /// Calls the Win32 SendInput method ...
    /// </summary>
    /// <param name="keyCode">The VirtualKeyCode to press</param>
    public IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode) //prev public static void
    {
        var down = new INPUT();
        down.Type = (UInt32)InputType.Keyboard;
        down.Data.Keyboard = new KEYBDINPUT();
        down.Data.Keyboard.KeyCode = (UInt16)keyCode; //prev .Keyboard.Vk
        // Scan Code here, was 0
        down.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
        down.Data.Keyboard.Flags = 0;
        down.Data.Keyboard.Time = 0;
        down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        var up = new INPUT();
        up.Type = (UInt32)InputType.Keyboard;
        up.Data.Keyboard = new KEYBDINPUT();
        up.Data.Keyboard.KeyCode = (UInt16)keyCode;
        // Scan Code here, was 0
        up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0);
        up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KeyUp;
        up.Data.Keyboard.Time = 0;
        up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        INPUT[] inputList = new INPUT[2];
        inputList[0] = down;
        inputList[1] = up;

        var numberOfSuccessfulSimulatedInputs = SendInput(2,
             inputList, Marshal.SizeOf(typeof(INPUT)));
        if (numberOfSuccessfulSimulatedInputs == 0)
            throw new Exception(
            string.Format("The key press simulation for {0} was not successful.",
            keyCode));
        return this;
    }
定格我的天空 2024-10-24 14:31:21

对于Windows输入模拟器解决方案,您可以直接修改源代码,以便内置函数将使用虚拟键发送扫描码。

InputBuilder.cs:

using System.Runtime.InteropServices;
.
.
.
[DllImport("user32.dll")]
static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
.
.
.
public InputBuilder AddKeyDown(VirtualKeyCode keyCode)
{
    var down =
        new INPUT
        {
            Type = (UInt32)InputType.Keyboard,
            Data =
                    {
                        Keyboard =
                            new KEYBDINPUT
                                {
                                    KeyCode = (UInt16) keyCode,
                                    Scan = (UInt16)MapVirtualKeyEx((UInt16)keyCode, 0, IntPtr.Zero),
                                    Flags = IsExtendedKey(keyCode) ? (UInt32) KeyboardFlag.ExtendedKey : (UInt32) KeyboardFlag.ScanCode,
                                    Time = 0,
                                    ExtraInfo = IntPtr.Zero
                                }
                    }
            };

    _inputList.Add(down);
    return this;
}
.
.
.
public InputBuilder AddKeyUp(VirtualKeyCode keyCode)
{
    var up =
        new INPUT
            {
                Type = (UInt32) InputType.Keyboard,
                Data =
                    {
                        Keyboard =
                            new KEYBDINPUT
                                {
                                    KeyCode = (UInt16) keyCode,
                                    Scan = (UInt16)MapVirtualKeyEx((UInt16)keyCode, 0,IntPtr.Zero),
                                    Flags = (UInt32) (IsExtendedKey(keyCode)
                                                          ? KeyboardFlag.KeyUp | KeyboardFlag.ExtendedKey
                                                          : KeyboardFlag.KeyUp | KeyboardFlag.ScanCode),
                                    Time = 0,
                                    ExtraInfo = IntPtr.Zero
                                }
                    }
            };

    _inputList.Add(up);
    return this;
}
.
.
.
public InputBuilder AddCharacter(char character)
{
    bool shiftChr = ((UInt16)VkKeyScanEx(character, IntPtr.Zero) >> 8).Equals(1);
    if (shiftChr)
    {
        AddKeyDown(VirtualKeyCode.VK_SHIFT);
    }

    UInt16 scanCode = shiftChr ? (UInt16)MapVirtualKeyEx((UInt16)(VkKeyScanEx(character, IntPtr.Zero) & 0xff),0,IntPtr.Zero) : (UInt16)MapVirtualKeyEx((UInt16)VkKeyScanEx(character, IntPtr.Zero), 0, IntPtr.Zero);

    var down = new INPUT
                   {
                       Type = (UInt32)InputType.Keyboard,
                       Data =
                           {
                               Keyboard =
                                   new KEYBDINPUT
                                       {
                                           KeyCode = 0,
                                           Scan = scanCode,
                                           Flags = (UInt32)KeyboardFlag.ScanCode,
                                           Time = 0,
                                           ExtraInfo = IntPtr.Zero
                                       }
                           }
                   };

    var up = new INPUT
                 {
                     Type = (UInt32)InputType.Keyboard,
                     Data =
                         {
                             Keyboard =
                                 new KEYBDINPUT
                                     {
                                         KeyCode = 0,
                                         Scan = scanCode,
                                         Flags =
                                             (UInt32)(KeyboardFlag.KeyUp | KeyboardFlag.ScanCode),
                                         Time = 0,
                                         ExtraInfo = IntPtr.Zero
                                     }
                         }
                 };

    _inputList.Add(down);
    _inputList.Add(up);

    if (shiftChr)
    {
        AddKeyUp(VirtualKeyCode.VK_SHIFT);
    }

    return this;
}

通过这些更改,TextEntryKeyPressModifiedKeyStroke 将发送与传入的虚拟键关联的扫描代码。

For the windows input simulator solution, you can modify the source code directly so that the built in functions will send scan codes with the virtual keys.

InputBuilder.cs:

using System.Runtime.InteropServices;
.
.
.
[DllImport("user32.dll")]
static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
.
.
.
public InputBuilder AddKeyDown(VirtualKeyCode keyCode)
{
    var down =
        new INPUT
        {
            Type = (UInt32)InputType.Keyboard,
            Data =
                    {
                        Keyboard =
                            new KEYBDINPUT
                                {
                                    KeyCode = (UInt16) keyCode,
                                    Scan = (UInt16)MapVirtualKeyEx((UInt16)keyCode, 0, IntPtr.Zero),
                                    Flags = IsExtendedKey(keyCode) ? (UInt32) KeyboardFlag.ExtendedKey : (UInt32) KeyboardFlag.ScanCode,
                                    Time = 0,
                                    ExtraInfo = IntPtr.Zero
                                }
                    }
            };

    _inputList.Add(down);
    return this;
}
.
.
.
public InputBuilder AddKeyUp(VirtualKeyCode keyCode)
{
    var up =
        new INPUT
            {
                Type = (UInt32) InputType.Keyboard,
                Data =
                    {
                        Keyboard =
                            new KEYBDINPUT
                                {
                                    KeyCode = (UInt16) keyCode,
                                    Scan = (UInt16)MapVirtualKeyEx((UInt16)keyCode, 0,IntPtr.Zero),
                                    Flags = (UInt32) (IsExtendedKey(keyCode)
                                                          ? KeyboardFlag.KeyUp | KeyboardFlag.ExtendedKey
                                                          : KeyboardFlag.KeyUp | KeyboardFlag.ScanCode),
                                    Time = 0,
                                    ExtraInfo = IntPtr.Zero
                                }
                    }
            };

    _inputList.Add(up);
    return this;
}
.
.
.
public InputBuilder AddCharacter(char character)
{
    bool shiftChr = ((UInt16)VkKeyScanEx(character, IntPtr.Zero) >> 8).Equals(1);
    if (shiftChr)
    {
        AddKeyDown(VirtualKeyCode.VK_SHIFT);
    }

    UInt16 scanCode = shiftChr ? (UInt16)MapVirtualKeyEx((UInt16)(VkKeyScanEx(character, IntPtr.Zero) & 0xff),0,IntPtr.Zero) : (UInt16)MapVirtualKeyEx((UInt16)VkKeyScanEx(character, IntPtr.Zero), 0, IntPtr.Zero);

    var down = new INPUT
                   {
                       Type = (UInt32)InputType.Keyboard,
                       Data =
                           {
                               Keyboard =
                                   new KEYBDINPUT
                                       {
                                           KeyCode = 0,
                                           Scan = scanCode,
                                           Flags = (UInt32)KeyboardFlag.ScanCode,
                                           Time = 0,
                                           ExtraInfo = IntPtr.Zero
                                       }
                           }
                   };

    var up = new INPUT
                 {
                     Type = (UInt32)InputType.Keyboard,
                     Data =
                         {
                             Keyboard =
                                 new KEYBDINPUT
                                     {
                                         KeyCode = 0,
                                         Scan = scanCode,
                                         Flags =
                                             (UInt32)(KeyboardFlag.KeyUp | KeyboardFlag.ScanCode),
                                         Time = 0,
                                         ExtraInfo = IntPtr.Zero
                                     }
                         }
                 };

    _inputList.Add(down);
    _inputList.Add(up);

    if (shiftChr)
    {
        AddKeyUp(VirtualKeyCode.VK_SHIFT);
    }

    return this;
}

With these changes TextEntry, KeyPress, and ModifiedKeyStroke will send the scan codes associated with the virtual keys passed in.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文