简体   繁体   English

如何将任何应用程序的选定文本放入 windows 窗体应用程序

[英]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: 经过一番阅读,我找到了方法:

  1. Hook the double click event using something like globalmousekeyhook.codeplex.com 使用globalmousekeyhook.codeplex.com之类的东西挂钩双击事件
  2. (Optional) Save the current state of the clipboard (可选)保存剪贴板的当前状态
  3. Get The current mouse position with GetCursorPos from user32.dll user32.dll获取GetCursorPos的当前鼠标位置
  4. 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); } 
  5. 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修改器发送密钥

  6. Your Code 你的守则
  7. (Optional) Restore the clipboard content saved in step 2 (可选)恢复在步骤2中保存的剪贴板内容

I implemented it this project that belongs to me. 我实现了这个属于我的项目。 Ok, how can i handle this, let me explain. 好的,我怎么处理这个,让我解释一下。

Two major things should be 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. 所以,@ jcrada的回答包含一个好的观点,即选项1。

The steps must be, under the light of above approachs: 根据上述方法,步骤必须是:

  • Add globalmousekeyhook from Nuget. 从Nuget添加globalmousekeyhook。
  • Register ClipboardContainsText event via Usr32.dll 通过Usr32.dll注册ClipboardContainsText事件
  • Register right events for mouse 注册鼠标的正确事件
  • And start listening 并开始倾听

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.让我们深入了解我的详细,简单和最新的方法。

  1. Install MousekeyHook , which was globalmousekeyhook before, from Nuget.从 Nuget 安装MousekeyHook ,它之前是 globalmousekeyhook 。

  2. Register mouse events ( MouseDoubleClick event and MouseDragFinished event, in which case you might have selected some text) with your function.使用您的函数注册鼠标事件( MouseDoubleClick事件和MouseDragFinished事件,在这种情况下您可能选择了一些文本)。

  3. Save clipboard's current content to restore it later.保存剪贴板的当前内容以便稍后恢复。 (Optinal) (可选)

  4. Clear the clipboard to determine whether you have selected some text later.清除剪贴板以确定您稍后是否选择了某些文本。

  5. 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");

  6. 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.

相关问题 如何从 Windows 窗体应用程序的 DataGrid 中的选定行中获取值? - How to get values from selected row in DataGrid for Windows Form Application? 在Windows应用程序中,如何从任何窗口检查和检索(如果有)选定的文本/图像? - In a windows application, how to check and retrieve(if any) selected text/image from any window? C #Windows表单应用程序如何删除所选的列表框行和文本文件 - C# Windows form application how to delete selected listbox line and text file 如何在Windows窗体应用程序(C#)中更改在文本上而不是在值上展开的选定组合框项目? - How to change selected combobox item depanding on text instead of value in windows form application (C#)? 如何在Windows窗体应用程序中保存文本文件 - How to save text file in windows form application 如何从WPF中的任何应用程序访问突出显示/选定的文本? - How do I get access to highlighted/selected text from any application in my WPF? 如何选择任何应用程序文本到VB.NET没有按Clrt + C - how to get selected text any application to VB.NET With out press Clrt + C 在任何应用程序的Windows中获取鼠标指针下的文本 - Get the text under the mouse pointer in windows in any application 如何在Windows应用程序中获取位于DataGridView内的组合框所选项目? - How to get combobox selected item which is inside DataGridView in windows Application? 如何从 Web 浏览器控件获取价值到 Windows 窗体应用程序文本框? - how to get value from web browser control to windows form application Text Box?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM