触发操作系统以编程方式复制(ctrl + c或Ctrl-x)

时间:2010-05-22 02:44:08

标签: c# windows api sendkeys

我正在制作一个触发剪切和粘贴的程序

粘贴我没问题(我只是将一个字符串转储到剪贴板中)

Cut and or Copys被证明有点困难

我所拥有的程序没有聚焦,并且有几个热键注册了os CTRL + ALT + 2 CTRL + ALT + 3 等)

我想用它来触发Windows复制在焦点窗口中突出显示的任何内容

我尝试过做一个sendkeys

SendKeys.Send("^c");

但是,如果完全停止工作,那似乎工作了一两次。

是否有更好的方法来尝试触发窗口来处理不同窗口中突出显示的内容

2 个答案:

答案 0 :(得分:13)

执行此操作的一种方法是使用Win32 SendInput函数。使用SendInput,您必须模拟按键事件和按键事件,以便按下完整的按键进行注册。要模拟 CTRL + C ,你必须这样做:

  • CTRL 按键
  • C key down
  • C key up
  • CTRL key up

pinvoke.net有一些使用SendInput的例子。要注意的一个问题是密钥是否已被按下。如果密钥尚未关闭,您可以使用GetAsyncKeyState仅模拟按键事件。

下面是一些示例代码,说明如何模拟 CTRL + C 。使用下面的代码,您可以简单地调用Keyboard.SimulateKeyStroke('c', ctrl: true);请注意,这就像用户按字面按 CTRL + C 一样,因此活动应用程序将按原样运行当这样的事件发生时总是这样做(即如果没有任何东西正常复制,那么也不会用这种方法复制任何东西)。

编辑:请参阅下面关于批量发送输入的David的评论。下面的代码应该通过对SendInput的单个调用发送整个输入事件序列,以避免与实际用户输入事件交错(和误解释)。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;

namespace SimulateKeys
{
    static class Keyboard
    {
        public static void SimulateKeyStroke(char key, bool ctrl = false, bool alt = false, bool shift = false)
        {
            List<ushort> keys = new List<ushort>();

            if (ctrl)
                keys.Add(VK_CONTROL);

            if (alt)
                keys.Add(VK_MENU);

            if (shift)
                keys.Add(VK_SHIFT);

            keys.Add(char.ToUpper(key));

            INPUT input = new INPUT();
            input.type = INPUT_KEYBOARD;
            int inputSize = Marshal.SizeOf(input);

            for (int i = 0; i < keys.Count; ++i)
            {
                input.mkhi.ki.wVk = keys[i];

                bool isKeyDown = (GetAsyncKeyState(keys[i]) & 0x10000) != 0;

                if (!isKeyDown)
                    SendInput(1, ref input, inputSize);
            }

            input.mkhi.ki.dwFlags = KEYEVENTF_KEYUP;
            for (int i = keys.Count - 1; i >= 0; --i)
            {
                input.mkhi.ki.wVk = keys[i];
                SendInput(1, ref input, inputSize);
            }
        }

        [DllImport("user32.dll")]
        static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

        [DllImport("user32.dll")]
        static extern short GetAsyncKeyState(ushort vKey);

        struct MOUSEINPUT
        {
            public int dx;
            public int dy;
            public uint mouseData;
            public uint dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        struct KEYBDINPUT
        {
            public ushort wVk;
            public ushort wScan;
            public uint dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        struct HARDWAREINPUT
        {
            public int uMsg;
            public short wParamL;
            public short wParamH;
        }

        [StructLayout(LayoutKind.Explicit)]
        struct MOUSEKEYBDHARDWAREINPUT
        {
            [FieldOffset(0)]
            public MOUSEINPUT mi;

            [FieldOffset(0)]
            public KEYBDINPUT ki;

            [FieldOffset(0)]
            public HARDWAREINPUT hi;
        }

        struct INPUT
        {
            public int type;
            public MOUSEKEYBDHARDWAREINPUT mkhi;
        }

        const int INPUT_KEYBOARD = 1;
        const uint KEYEVENTF_KEYUP = 0x0002;

        const ushort VK_SHIFT = 0x10;
        const ushort VK_CONTROL = 0x11;
        const ushort VK_MENU = 0x12;
    }

    class Program
    {
        static void Main(string[] args)
        {
            Thread.Sleep(3000);
            Keyboard.SimulateKeyStroke('c', ctrl: true);
        }
    }
}

答案 1 :(得分:1)

如果您可以从焦点窗口中获取所选文本(可能更容易解决),那么最好使用SetText类的System.Windows.Forms.Clipboard方法。