如何获取当前焦点窗口的选定文本?

Ken*_*ton 2 c# focus selection

因此,我正在尝试制作一个执行以下操作的应用程序:

  1. 监听键盘快捷键(使用此库
  2. 当按下快捷键时,检索当前选定文本的内容,并
  3. 处理文本

我已使用此答案的最新编辑共享的方法(此方法)将我的应用程序附加到焦点控件,但GetText该方法中的功能不能满足我的需要。

我也看过这个答案,但它只提供了如何通过双击获得聚焦窗口的详细步骤,这不是我需要的。它确实链接到这个问题,导致我尝试该WM_KEYDOWN方法(如下所示),但这也不起作用。

到目前为止,我已经尝试过这些GetText方法(全部在 MSDN 帖子的上下文中):

string GetText(IntPtr handle)
{
    // works in Notepad, but not Chrome
    SendMessageW(handle, WM_COPY, 0, 0);
    string w = Clipboard.GetText();
    return w;

    // works in every app, but in Notepad gets the complete contents
    // and in Chrome gets the window title
    int maxLength = 160;
    IntPtr buffer = Marshal.AllocHGlobal((maxLength + 1) * 2);
    SendMessageW(handle, WM_GETTEXT, maxLength, buffer);
    string w = Marshal.PtrToStringUni(buffer);
    Marshal.FreeHGlobal(buffer);
    return w;

    // I would have thought these would work, but
    // they don't do anything for some reason. They
    // all simulate a Ctrl+C.

    SendKeys.SendWait("^c");
    // or
    // this is from the same library that listens for the keyboard shortcut
    KeyboardSimulator.SimulateStandardShortcut(StandardShortcut.Copy);
    // or
    SendMessageW(handle, WM_KEYDOWN, (ushort)Keys.LControlKey, 0);
    SendMessageW(handle, WM_KEYDOWN, (ushort)Keys.C, 0);
    SendMessageW(handle, WM_KEYUP, (ushort)Keys.C, 0);
    SendMessageW(handle, WM_KEYUP, (ushort)Keys.LControlKey, 0);
    // after any of those
    string w = Clipboard.GetText();
    return w;
}
Run Code Online (Sandbox Code Playgroud)

(我还不关心保留剪贴板。)

如何一致地获取当前焦点应用程序的选定文本?不篡改剪贴板的奖励积分,但使用它也可以。

小智 5

自 Vista 起,应用程序应避免使用 p-invoke 或WM_GETTEXT窥探其他应用程序,因为 Windows 提升进程可能会阻止。相反,请考虑使用Microsoft UI Automation。虽然可以说是一个测试框架,但它也可作为与另一个 GUI 应用程序远程交互的手段。

微软软件定义网络:

Microsoft UI 自动化是 Microsoft Windows 的新辅助功能框架。它通过提供对用户界面 (UI) 信息的编程访问来满足辅助技术产品和自动化测试框架的需求。此外,UI 自动化使控件和应用程序开发人员能够使其产品易于访问。

以下代码将查找正在运行的进程记事并抓取任何文本选择。 确保事先运行记事本,输入一些文本并选择一两个单词。

using System;
using System.Diagnostics;
using System.Linq;
using System.Windows.Automation;

namespace UiaTest
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var p = Process.GetProcessesByName("notepad").FirstOrDefault();       
            var root = AutomationElement.FromHandle(p.MainWindowHandle);

            var documentControl = new                                 
                    PropertyCondition(AutomationElement.ControlTypeProperty, 
                                      ControlType.Document);

            var textPatternAvailable = new PropertyCondition(AutomationElement.IsTextPatternAvailableProperty, true);

            var findControl = new AndCondition(documentControl, textPatternAvailable);

            var targetDocument = root.FindFirst(TreeScope.Descendants, findControl);    
            var textPattern = targetDocument.GetCurrentPattern(TextPattern.Pattern) as TextPattern;

            foreach (var selection in textPattern.GetSelection())
            {
                Console.WriteLine($"Selection: \"{selection.GetText(255)}\"");
            }    
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

如何一致地获取当前焦点应用程序的选定文本?

现在,在您的情况下,从聚焦窗口工作,而不是:

var p = Process.GetProcessesByName("notepad").FirstOrDefault();     
Run Code Online (Sandbox Code Playgroud)

...执行:

IntPtr handle = GetForegroundWindow();
var root = AutomationElement.FromHandle(handle);
Run Code Online (Sandbox Code Playgroud)

...其中GetForegroundWindow定义为:

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
Run Code Online (Sandbox Code Playgroud)

也可以看看