Запуск ОС для копирования (ctrl + c или Ctrl-x) программно - PullRequest
4 голосов
/ 22 мая 2010

Я работаю над программой для запуска вырезки и вставки

Вставки, с которыми у меня нет проблем (я просто выкидываю строку в буфер обмена)

Вырезать или Копировать оказывается немного сложнее

Моя программа не в фокусе и имеет несколько горячих клавиш, зарегистрированных в ОС CTRL + ALT + 2 CTRL + ALT + 3 и т. Д.)

, который я хочу использовать, чтобы заставить Windows копировать все, что выделено в окне, которое сфокусировано

Я пытался сделать sendkeys

SendKeys.Send("^c");

но это, кажется, работает один или два раза, если вообще перестает работать.

есть ли лучший способ попытаться заставить окна копировать выделенный контент в другое окно

Ответы [ 2 ]

13 голосов
/ 27 мая 2010

Один из способов сделать это - использовать функцию Win32 SendInputSendInput вы должны смоделировать события нажатия клавиш и нажатия клавиш вверх для полного нажатия клавиши для регистрации.Чтобы смоделировать CTRL + C , вам нужно будет сделать:

  • CTRL нажать
  • C ключ вниз
  • C ключ вверх
  • CTRL ключ вверх

У pinvoke.net есть несколько примеров использования SendInput.Следует помнить, что клавиша уже нажата.Вы можете использовать GetAsyncKeyState для имитации события нажатия клавиши только в том случае, если клавиша еще не нажата.

Ниже приведен пример кода того, как можно имитировать CTRL + C .С помощью приведенного ниже кода вы можете просто позвонить Keyboard.SimulateKeyStroke('c', ctrl: true); Обратите внимание, что это работает так, как если бы пользователь буквально нажал CTRL + C , поэтому активное приложение будет работать так, как всегда, когда такоепроисходит событие (т. е. если ничего обычно не копируется, то и этот метод также ничего не будет скопирован).

Редактировать: См. комментарий Дэвида ниже о пакетной отправке ввода.Приведенный ниже код должен отправлять всю последовательность входных событий через один вызов на 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 голос
/ 22 мая 2010

Если вы можете получить выделенный текст из сфокусированного окна (возможно, более простую проблему для решения), тогда вам лучше использовать метод SetText класса System.Windows.Forms.Clipboard.

...