SendKeys Ctrl + C to external applications (text into Clipboard)

余生长醉 提交于 2019-12-04 04:29:26

In this case, VB.Net actually provides a method to solve your problem. It's called SendKeys.Send(<key>), you can use it with argument SendKeys.Send("^(c)"). This send Ctrl+C to the computer, according to this msdn-article

Jeremy Thompson

Put AutoHotkey back in the closet and ditch your need of IsClipboardFormatAvailable.

Use a Global Keyboard Hook done by Microsoft: RegisterHotKey function works really well,
the only caveat for you is that it wont work with F6 by itself you need Alt +, Ctrl + or Shift +.

Download the sample winform app and see for yourself:

https://code.msdn.microsoft.com/CppRegisterHotkey-7bd897a8 C++ https://code.msdn.microsoft.com/CSRegisterHotkey-e3f5061e C# https://code.msdn.microsoft.com/VBRegisterHotkey-50af3179 VB.Net

Should the above links rot I have included the C# source code in this answer.

Strategy:

  1. Monitor which was the last Active Window

  2. (Optional) Save the current state of the clipboard (so you can restore it after)

  3. Set the SetForegroundWindow() to the handle of the last Active Window

  4. SendKeys.Send("^c");

  5. (Optional) Reset the clipboard value saved in 2

Code:

Here is how I modified the Microsoft Sample projects, replace the mainform.cs constructor with this code:

namespace CSRegisterHotkey
{
public partial class MainForm : Form
{
    [DllImport("User32.dll")]
    static extern int SetForegroundWindow(IntPtr point);

    WinEventDelegate dele = null;
    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

    [DllImport("user32.dll")]
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

    private const uint WINEVENT_OUTOFCONTEXT = 0;
    private const uint EVENT_SYSTEM_FOREGROUND = 3;

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

    //Another way if SendKeys doesn't work (watch out for this with newer operating systems!)
    [DllImport("user32.dll")]
    static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

    //----

    HotKeyRegister hotKeyToRegister = null;

    Keys registerKey = Keys.None;

    KeyModifiers registerModifiers = KeyModifiers.None;

    public MainForm()
    {
        InitializeComponent();

        dele = new WinEventDelegate(WinEventProc);
        IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
    }

    private string GetActiveWindowTitle()
    {
        const int nChars = 256;
        IntPtr handle = IntPtr.Zero;
        StringBuilder Buff = new StringBuilder(nChars);
        handle = GetForegroundWindow();

        if (GetWindowText(handle, Buff, nChars) > 0)
        {
            lastHandle = handle;
            return Buff.ToString();
        }
        return null;
    }

    public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        txtLog.Text += GetActiveWindowTitle() + "\r\n";
    }

In the mainform change the HotKeyPressed event to this goodness:

void HotKeyPressed(object sender, EventArgs e)
{
    //if (this.WindowState == FormWindowState.Minimized)
    //{
    //    this.WindowState = FormWindowState.Normal;
    //}
    //this.Activate();

    //Here is the magic
    SendCtrlCKey(lastHandle);
}

private void SendCtrlCKey(IntPtr mainWindowHandle)
{
    SetForegroundWindow(mainWindowHandle);
    //IMPORTANT - Wait for the window to regain focus
    Thread.Sleep(300); 
    SendKeys.Send("^c");

    //Comment out the next 3 lines in Release
#if DEBUG 
    this.Activate();
    MessageBox.Show(Clipboard.GetData(DataFormats.Text).ToString());
    SetForegroundWindow(mainWindowHandle);
#endif
}

//Optional example of how to use the keybd_event encase with newer Operating System the SendKeys doesn't work
private void SendCtrlC(IntPtr hWnd)
{
    uint KEYEVENTF_KEYUP = 2;
    byte VK_CONTROL = 0x11;
    SetForegroundWindow(hWnd);
    keybd_event(VK_CONTROL, 0, 0, 0);
    keybd_event(0x43, 0, 0, 0); //Send the C key (43 is "C")
    keybd_event(0x43, 0, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);// 'Left Control Up
}

Warnings:

  1. If your application is intended for international use with a variety of keyboards, the use of SendKeys.Send could yield unpredictable results and should be avoided. Ref: Simulating Keyboard Input <- Method DOES NOT WORK!!!
  1. Becareful around Operating System Changes, as discussed here: https://superuser.com/questions/11308/how-can-i-determine-which-process-owns-a-hotkey-in-windows

Research:

Detect active window changed using C# without polling
Simulating CTRL+C with Sendkeys fails
Is it possible to send a WM_COPY message that copies text somewhere other than the Clipboard?
Global hotkey release (keyup)? (WIN32 API)
C# using Sendkey function to send a key to another application
How to perform .Onkey Event in an Excel Add-In created with Visual Studio 2010?
How to get selected text of any application into a windows form application
Clipboard event C#
How do I monitor clipboard content changes in C#?

Enjoy:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!