Send Ctrl + C to the previous active window

I am trying to write a small application that is in the system tray. I registered a hotkey. When the hotkey is launched and the application is activated, I want to send Ctrl + C to the last active window so that I can select the selected text on the clipboard.

This is what I got so far:

//http://stackoverflow.com/questions/9468476/switch-to-last-active-application-like-alt-tab [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] static extern IntPtr GetLastActivePopup(IntPtr hWnd); [DllImport("user32.dll", ExactSpelling = true)] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); const uint GA_PARENT = 1; const uint GA_ROOT = 2; const uint GA_ROOTOWNER = 3; public static IntPtr GetPreviousWindow() { IntPtr activeAppWindow = GetForegroundWindow(); if (activeAppWindow == IntPtr.Zero) return IntPtr.Zero; IntPtr prevAppWindow = GetLastActivePopup(activeAppWindow); return IsWindowVisible(prevAppWindow) ? prevAppWindow : IntPtr.Zero; } public static void FocusToPreviousWindow() { IntPtr prevWindow = GetPreviousWindow(); if (prevWindow != IntPtr.Zero) SetForegroundWindow(prevWindow); } ... private static void OnHotKeyFired() { FocusToPreviousWindow(); SendKeys.SendWait("^(c)"); _viewModel.Input = Clipboard.GetText(); new UIWindow(_viewModel).ShowDialog(); } 

But I can not get SendKeys to work. In most applications, nothing happens, i.e. ctrl-c does not start. In Ms Word, a copyright sign (c) is inserted in my document when SendWait is running.

UPDATE:

I tried WM_COPY and SendMessage:

 private static void OnHotKeyFired() { IntPtr handle = GetPreviousWindow(); SendMessage(handle, WM_COPY, IntPtr.Zero, IntPtr.Zero); _viewModel.Input = Clipboard.GetText(); ... 

And it works in Word, but not in Excel, Notepad, Visual Studio

0
c # wpf window
source share
3 answers

I think your problem is due to timing.

To adjust the focus focus and make the actual copy to the clipboard, you need to wait until the window becomes focus, and wait for the clipboard to update.

There are several ways to deal with these ugly win32 things.

For clipboard contents. I am comparing the source content with the current content. I set the original content to string.empty if its image or some other is not text data. Then I wait for a function that checks the clipboard for changes.

For SetForegroundWindow, I am currently adding a delay in my asynchronous function. You can probably also find the win32 api call to wait until this window is correctly placed in the foreground.

I do both of them in async functions and wait for it so that there is no block.

SendKeys should work with SendWait ("^ c"). SendWait ("^ (c)") will not always work as indicated in other answers. However, copying ctrl + c to the clipboard does not happen instantly.

 Point p; if (GetCursorPos(out p)) { IntPtr ptr = WindowFromPoint(p); if (ptr != IntPtr.Zero) { SetForegroundWindow(ptr); //wait for window to get focus quick and ugly // probably a cleaner way to wait for windows to send a message // that it has updated the foreground window await Task.Delay(300); //try to copy text in the current window SendKeys.Send("^c"); await WaitForClipboardToUpdate(originalClipboardText); } } } private static async Task WaitForClipboardToUpdate(string originalClipboardText) { Stopwatch sw = Stopwatch.StartNew(); while (true) { if (await DoClipboardCheck(originalClipboardText)) return; if (sw.ElapsedMilliseconds >= 1500) throw new Exception("TIMED OUT WAITING FOR CLIPBOARD TO UPDATE."); } } private static async Task<bool> DoClipboardCheck(string originalClipboardText) { await Task.Delay(10); if (!Clipboard.ContainsText()) return false; var currentText = Clipboard.GetText(); Debug.WriteLine("current text: " + currentText + " original text: " + originalClipboardText); return currentText != originalClipboardText; } [DllImport("user32.dll")] private static extern bool GetCursorPos(out Point pt); [DllImport("user32.dll", EntryPoint = "WindowFromPoint", CharSet = CharSet.Auto, ExactSpelling = true)] private static extern IntPtr WindowFromPoint(Point pt); // Activate an application window. [DllImport("USER32.DLL")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImportAttribute("user32.dll", EntryPoint = "GetForegroundWindow")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError = true)] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); 

Also - a real quick and dirty way to quickly check / check if time is your problem, you can put Thread.Sleep (1000); after calls to SetForegroundWindow and SendKeys.SendWait.

+1
source share
  SendKeys.SendWait("^(c)"); 

This does not send Ctrl + C, parentheses are also sent. You probably meant "^{c}" , curly braces instead of parentheses. Otherwise, the reason Word inserts the copyright symbol automatically corrects (c) to Β©. Fix:

  SendKeys.SendWait("^c"); 

If you still have problems, you'll probably want to, then read the MSDN article for SendKeys. He recommends using the .config file so that it uses a different method for entering keystrokes. SendInput () works better than the log hook in later versions of Windows.

+5
source share

I know that you are programming something, but in case you do it because you have not found an easier solution ... You can try AutoHotKey , this is a small program that sits in your tray and makes all kinds of hot keys / macros ... you will need to write a small script for your macro, something like this:

 #c::Send !{ESC}, ^c 

This simple script means:

  • #c :: (Define the Windows hotkey + c)
  • Send (Send a few keystrokes)
  • ! {ESC} (Alt + Esc, which switches to the last program)
  • ^ c (Control + c)

There are all kinds of fancy scripts that you can do with this software, for example, run programs, regular expressions, threads, mouse events, and much more ...

I know that it does not answer your question, but it is a simple alternative.

0
source share

All Articles