因此,我正在尝试制作一个执行以下操作的应用程序:
我使用了this answer(this method)的最新编辑所共享的方法,将我的应用程序附加到焦点控件上,但是该方法中的GetText
函数没有做我需要的事。
我也见过this answer,但这仅给出了有关如何在双击时获得焦点窗口的详细步骤,这不是我所需要的。它确实链接到this question,这使我尝试了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;
}
(我不在乎保存剪贴板。)
如何才能始终如一地获取当前关注的应用程序的选定文本?奖励点是不篡改剪贴板,但也可以使用。
答案 0 :(得分:2)
自Vista以来,由于Windows高程进程的潜在阻止,应用程序应避免使用p调用或WM_GETTEXT
监听其他应用程序。而是考虑使用 Microsoft UI Automation 。尽管可以说是一个测试框架,但它也可以作为与另一个GUI应用程序进行远程交互的一种方式。
MSDN:
Microsoft UI Automation是Microsoft Windows的新辅助功能框架。它通过提供对有关用户界面(UI)信息的编程访问来满足辅助技术产品和自动化测试框架的需求。此外,UI自动化使控件和应用程序开发人员可以访问其产品。
以下代码将查找正在运行的进程 Notepad ,并抓住所有文本选择。 确保您事先运行了记事本,输入一些文字并选择一个或两个单词。
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)}\"");
}
}
}
}
编辑:
如何始终获取当前重点应用程序的选定文本?
现在,您可以从焦点窗口开始工作了,而不是:
var p = Process.GetProcessesByName("notepad").FirstOrDefault();
...执行a:
IntPtr handle = GetForegroundWindow();
var root = AutomationElement.FromHandle(handle);
...其中GetForegroundWindow
定义为:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();