如何将任何应用程序的选定文本添加到Windows窗体应用程序中

这是我想要做的,

当用户通过双击鼠标选择任何正在运行的应用程序的任何单词(文本)时,应将特定突出显示的单词插入已经运行的Windows应用程序中。

到目前为止,我已经使用Global Keystroke实现了逻辑,用户必须触发CRT + C键盘组合键才能将所选单词复制到win form应用程序中。

我想知道的是有没有办法将这些选定的文本放入应用程序而无需按键盘按键?

经过一番阅读,我找到了方法:

  1. 使用globalmousekeyhook.codeplex.com之类的东西挂钩双击事件
  2. (可选)保存剪贴板的当前状态
  3. user32.dll获取GetCursorPos的当前鼠标位置
  4. 使用来自user32.dll WindowFromPoint根据光标位置获取窗口

     [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); } 
  5. 使用SendMessage表单user32.dll发送复制命令(请参阅使用User32.dll SendMessage使用ALT修改器发送密钥 )

  6. 你的守则
  7. (可选)恢复在步骤2中保存的剪贴板内容

我实现了这个属于我的项目。 好的,我怎么处理这个,让我解释一下。

应该考虑两件大事。

  • 如何在任何窗口中获取文本?
  • 我应该在哪里存放?

所以,@ jcrada的回答包含一个好的观点,即选项1。

根据上述方法,步骤必须是:

  • 从Nuget添加globalmousekeyhook。
  • 通过Usr32.dll注册ClipboardContainsText事件
  • 注册鼠标的正确事件
  • 并开始倾听

首先,创建包含剪贴板事件的Win32帮助程序类。

 ///  /// This static class holds the Win32 function declarations and constants needed by /// this sample application. ///  internal static class Win32 { ///  /// The WM_DRAWCLIPBOARD message notifies a clipboard viewer window that /// the content of the clipboard has changed. ///  internal const int WmDrawclipboard = 0x0308; ///  /// A clipboard viewer window receives the WM_CHANGECBCHAIN message when /// another window is removing itself from the clipboard viewer chain. ///  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); } 

Seconly,注册鼠标和剪贴板事件,

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

鼠标事件;

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

最后一部分,当我们抓住时,我们会做什么

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

诀窍是将复制命令发送到窗口或操作系统另一方面Control + C命令,所以SendKeys.SendWait("^c"); 这样做。