How to get the selected text of any application in a Windows form application

This is what I'm trying to do

When a user selects any word (text) of any running application by double-clicking, a specific highlighted word should be inserted into an already running Windows application.

So far, I have implemented the logic using Global Keystroke , where the user must call the keyboard shortcut CRT + C to copy the selected word into the winning form application.

What I want to know is there a way to get the selected text in the application without pressing a key on the keyboard?

+7
c # clipboard winforms hook
source share
2 answers

after some readings i found a way

  • Capture a double click event using something like this
    http://globalmousekeyhook.codeplex.com/

  • (Optional) Save the current state of the click card

  • Get current mouse position with GetCursorPos from user32

  • Get window-based cursor position using WindowFromPoint user32

     [DllImport("user32.dll")] public static extern IntPtr WindowFromPoint(Point lpPoint); [DllImport("user32.dll")] public static extern bool GetCursorPos(out Point lpPoint); public static IntPtr GetWindowUnderCursor() { Point ptCursor = new Point(); if (!(PInvoke.GetCursorPos(out ptCursor))) return IntPtr.Zero; return WindowFromPoint(ptCursor); } 
  • Send a copy command with the SendMessage form User 32 See Using User32.dll SendMessage to send keys with the ALT modifier

  • Your code
  • (Optional) Reload the control panel value stored in 2
+4
source share

I implemented this project, which belongs to me. Well, how can I handle this, let me explain.

Two main things to consider.

  • How can I get text inside any window?
  • Where should I store it?

So, @jcrada's answer contains one good point, which is option 1.

The steps should be in light of the above approaches:

  • Add globalmousekeyhook from Nuget.
  • Register ClipboardContainsText event through Usr32.dll
  • Register correct mouse events
  • And start listening

First, create a Win32 helper class containing the clipboard event.

 /// <summary> /// This static class holds the Win32 function declarations and constants needed by /// this sample application. /// </summary> internal static class Win32 { /// <summary> /// The WM_DRAWCLIPBOARD message notifies a clipboard viewer window that /// the content of the clipboard has changed. /// </summary> internal const int WmDrawclipboard = 0x0308; /// <summary> /// A clipboard viewer window receives the WM_CHANGECBCHAIN message when /// another window is removing itself from the clipboard viewer chain. /// </summary> internal const int WmChangecbchain = 0x030D; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); } 

Directly register mouse and clipboard events,

 public void Initialize() { var wih = new WindowInteropHelper(this.mainWindow); this.hWndSource = HwndSource.FromHwnd(wih.Handle); this.globalMouseHook = Hook.GlobalEvents(); this.mainWindow.CancellationTokenSource = new CancellationTokenSource(); var source = this.hWndSource; if (source != null) { source.AddHook(this.WinProc); // start processing window messages this.hWndNextViewer = Win32.SetClipboardViewer(source.Handle); // set this window as a viewer } this.SubscribeLocalevents(); this.growlNotifications.Top = SystemParameters.WorkArea.Top + this.startupConfiguration.TopOffset; this.growlNotifications.Left = SystemParameters.WorkArea.Left + SystemParameters.WorkArea.Width - this.startupConfiguration.LeftOffset; this.IsInitialized = true; } 

Mouse events;

 private void SubscribeLocalevents() { this.globalMouseHook.MouseDoubleClick += async (o, args) => await this.MouseDoubleClicked(o, args); this.globalMouseHook.MouseDown += async (o, args) => await this.MouseDown(o, args); this.globalMouseHook.MouseUp += async (o, args) => await this.MouseUp(o, args); } private async Task MouseUp(object sender, MouseEventArgs e) { this.mouseSecondPoint = e.Location; if (this.isMouseDown && !this.mouseSecondPoint.Equals(this.mouseFirstPoint)) { await Task.Run(() => { if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested) return; SendKeys.SendWait("^c"); }); this.isMouseDown = false; } this.isMouseDown = false; } private async Task MouseDown(object sender, MouseEventArgs e) { await Task.Run(() => { if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested) return; this.mouseFirstPoint = e.Location; this.isMouseDown = true; }); } private async Task MouseDoubleClicked(object sender, MouseEventArgs e) { this.isMouseDown = false; await Task.Run(() => { if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested) return; SendKeys.SendWait("^c"); }); } 

And the last part: what will we do when we catch

 private IntPtr WinProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case Win32.WmChangecbchain: if (wParam == this.hWndNextViewer) this.hWndNextViewer = lParam; //clipboard viewer chain changed, need to fix it. else if (this.hWndNextViewer != IntPtr.Zero) Win32.SendMessage(this.hWndNextViewer, msg, wParam, lParam); //pass the message to the next viewer. break; case Win32.WmDrawclipboard: Win32.SendMessage(this.hWndNextViewer, msg, wParam, lParam); //pass the message to the next viewer //clipboard content changed if (Clipboard.ContainsText() && !string.IsNullOrEmpty(Clipboard.GetText().Trim())) { Application.Current.Dispatcher.Invoke( DispatcherPriority.Background, (Action) delegate { var currentText = Clipboard.GetText().RemoveSpecialCharacters(); if (!string.IsNullOrEmpty(currentText)) { //In this section, we are doing something, because TEXT IS CAPTURED. Task.Run( async () => { if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested) return; await this.WhenClipboardContainsTextEventHandler.InvokeSafelyAsync(this, new WhenClipboardContainsTextEventArgs { CurrentString = currentText }); }); } }); } break; } return IntPtr.Zero; } 

The trick sends a copy command to a window or operating system, on the other hand, a Control + C command, so SendKeys.SendWait("^c"); doing this.

+1
source share

All Articles