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

发布于 2024-09-02 04:05:25 字数 385 浏览 1 评论 0原文

我正在开发一个程序来触发剪切和粘贴

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

剪切和/或复制被证明有点困难

我的程序失去焦点并且有操作系统注册的几个热键 CTRL+ALT+2 CTRL+ALT +3 等)

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

我尝试执行 sendkeys

SendKeys.Send("^c");

但似乎工作一次或两次(如果有的话)然后停止工作。

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

I'm working on a program to trigger cut and pastes

Pastes I have no problem with (I just dump a string into the clipboard)

Cut and or Copys are proving to be a little more difficult

The program I have is out of focus and has several hot keys registered with the os CTRL+ALT+2 CTRL+ALT+3 etc)

That I want to use to trigger Windows to copy anything that is highlighted in the window that is focused

I tried doing a sendkeys

SendKeys.Send("^c");

but that seems to work once or twice if at all then stop working.

is there a better way to try to trigger windows into coping highlighted content on a different window

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

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

发布评论

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

评论(2

捂风挽笑 2024-09-09 04:05:25

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

  • CTRL 键按下
  • C 键按下
  • C 键向上
  • CTRL 键向上

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);
        }
    }
}

One way to do this is by using the Win32 SendInput function. With SendInput, you have to simulate both the key down and key up events in order for the full key press to register. To simulate CTRL+C, you'd have to do:

  • CTRL key down
  • C key down
  • C key up
  • CTRL key up

pinvoke.net has some examples of SendInput usage. One issue to be mindful of is if the key is already pressed. You can use GetAsyncKeyState to only simulate a key down event if the key is not already down.

Below is some example code of how you could simulate CTRL+C. With the code below, you can simply call Keyboard.SimulateKeyStroke('c', ctrl: true); Note that this works as if the user literally pressed CTRL+C, so the active application will behave as it always does when such an event happens (i.e. if nothing is normally copied, then nothing will be copied with this method, either).

Edit: See David's comment below about batching the sent input. The code below should be sending the entire sequence of input events through a single call to SendInput to avoid being interleaved (and misinterpreted) with real user input events.

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);
        }
    }
}
笔落惊风雨 2024-09-09 04:05:25

如果您可以从聚焦窗口中获取选定的文本(也许是一个更容易解决的问题),那么您最好使用 System.Windows.Forms.ClipboardSetText 方法代码>类。

If you can get the selected text from the focused window (maybe an easier problem to solve) then you're better off using the SetText method of the System.Windows.Forms.Clipboard class.

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