[英]How to get selected text of any application into a windows form application
This is what am trying to do,这就是我想要做的,
When user select any word(text) of any running application by double clicking the mouse particular highlighted word should be inserted into a windows application which is already running.当用户通过双击鼠标选择任何正在运行的应用程序的任何单词(文本)时,应将特定突出显示的单词插入到已经运行的 Windows 应用程序中。
So far I have implemented the logic using Global Keystroke
where user has to trigger CRT + C keyboard key combination to copy the selected word into win form application.到目前为止,我已经使用
Global Keystroke
实现了逻辑,其中用户必须触发CRT + C键盘组合键才能将所选单词复制到 win 表单应用程序中。
What i want to know is there any way to get those selected text into the application without having any button key press of the keyboard?我想知道有什么方法可以让那些选定的文本进入应用程序而无需按键盘上的任何按钮?
After some reading, I have found the way: 经过一番阅读,我找到了方法:
GetCursorPos
from user32.dll
user32.dll
获取GetCursorPos
的当前鼠标位置 Get windows based on cursor position with WindowFromPoint
from user32.dll
使用来自
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); }
Send copy command with SendMessage
form user32.dll
(see Using User32.dll SendMessage To Send Keys With ALT Modifier ) 使用
SendMessage
表单user32.dll
发送复制命令(请参阅使用User32.dll SendMessage使用ALT修改器发送密钥 )
I implemented it this project that belongs to me. 我实现了这个属于我的项目。 Ok, how can i handle this, let me explain.
好的,我怎么处理这个,让我解释一下。
Two major things should be consider. 应该考虑两件大事。
So, @jcrada's answer contains one good point which is option 1. 所以,@ jcrada的回答包含一个好的观点,即选项1。
The steps must be, under the light of above approachs: 根据上述方法,步骤必须是:
Firstly, create Win32 helper class that contains clipboard event. 首先,创建包含剪贴板事件的Win32帮助程序类。
/// <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);
}
Seconly, Register mouse and clipboard events, 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;
}
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 last part, What will we do when we caught, 最后一部分,当我们抓住时,我们会做什么
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 is sending copy command to the window or Operating System on the other hand Control+C command,so SendKeys.SendWait("^c");
诀窍是将复制命令发送到窗口或操作系统另一方面Control + C命令,所以
SendKeys.SendWait("^c");
doing this. 这样做。
The two answers above are somewhat difficult to understand and not detailed .上面两个回答有点难懂,不详细。 Anyway, big thanks to them cause it helped me to achieve this function, after trying many times.
无论如何,非常感谢他们,因为它帮助我在尝试了很多次之后实现了这个功能。
It's 2021 now!现在是 2021 年! Let's dive into my detailed and simple and latest method.
让我们深入了解我的详细,简单和最新的方法。
Install MousekeyHook , which was globalmousekeyhook before, from Nuget.从 Nuget 安装MousekeyHook ,它之前是 globalmousekeyhook 。
Register mouse events ( MouseDoubleClick event and MouseDragFinished event, in which case you might have selected some text) with your function.使用您的函数注册鼠标事件( MouseDoubleClick事件和MouseDragFinished事件,在这种情况下您可能选择了一些文本)。
Save clipboard's current content to restore it later.保存剪贴板的当前内容以便稍后恢复。 (Optinal)
(可选)
Clear the clipboard to determine whether you have selected some text later.清除剪贴板以确定您稍后是否选择了某些文本。
Send Ctrl+C
command simply by System.Windows.Forms.SendKeys.SendWait("^c");
只需通过
System.Windows.Forms.SendKeys.SendWait("^c");
发送Ctrl+C
命令System.Windows.Forms.SendKeys.SendWait("^c");
Get the clipboard's content.获取剪贴板的内容。
If you have selected some text, get it simply by System.Windows.Clipboard.GetText()
and do anything you want then.如果您选择了一些文本,只需通过
System.Windows.Clipboard.GetText()
获取它,然后做任何您想做的事情。
If haven't, restore the clipboard.如果还没有,请恢复剪贴板。 (Optional)
(可选的)
And these are my code:这些是我的代码:
private IKeyboardMouseEvents globalMouseHook;
public MainWindow()
{
// Note: for the application hook, use the Hook.AppEvents() instead.
globalMouseHook = Hook.GlobalEvents();
// Bind MouseDoubleClick event with a function named MouseDoubleClicked.
globalMouseHook.MouseDoubleClick += MouseDoubleClicked;
// Bind DragFinished event with a function.
// Same as double click, so I didn't write here.
globalMouseHook.MouseDragFinished += MouseDragFinished;
}
// I make the function async to avoid GUI lags.
private async void MouseDoubleClicked(object sender, System.Windows.Forms.MouseEventArgs e)
{
// Save clipboard's current content to restore it later.
IDataObject tmpClipboard = System.Windows.Clipboard.GetDataObject();
System.Windows.Clipboard.Clear();
// I think a small delay will be more safe.
// You could remove it, but be careful.
await Task.Delay(50);
// Send Ctrl+C, which is "copy"
System.Windows.Forms.SendKeys.SendWait("^c");
// Same as above. But this is more important.
// In some softwares like Word, the mouse double click will not select the word you clicked immediately.
// If you remove it, you will not get the text you selected.
await Task.Delay(50);
if (System.Windows.Clipboard.ContainsText())
{
string text = System.Windows.Clipboard.GetText();
// Your code
}
else
{
// Restore the Clipboard.
System.Windows.Clipboard.SetDataObject(tmpClipboard);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.