因此,我正在尝试制作一个执行以下操作的应用程序:
- 监听键盘快捷键(使用 this library )
- 当按下快捷键时,检索当前所选文本的内容,并且
- 处理文本
我使用了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;
}
(我还不关心保留剪贴板。)
如何始终获取当前焦点应用程序的选定文本?不篡改剪贴板的奖励积分,但使用它也可以。
最佳答案
自 Vista 起,应用程序应避免使用 p-invoke 或 WM_GETTEXT
来窥探其他应用程序,因为 Windows 提升进程可能会阻塞。请考虑使用Microsoft UI Automation。虽然可以说是一个测试框架,但它也可作为与另一个 GUI 应用程序远程交互的手段。
MSDN:
Microsoft UI Automation is the new accessibility framework for Microsoft Windows. It addresses the needs of assistive technology products and automated test frameworks by providing programmatic access to information about the user interface (UI). In addition, UI Automation enables control and application developers to make their products accessible.
以下代码将查找正在运行的进程记事本并抓取任何文本选择。 确保事先运行记事本,输入一些文本并选择一个或两个单词。
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)}\"");
}
}
}
}
编辑:
How can I consistently get the selected text of the currently focused application?
现在,在您的情况下,从聚焦窗口工作,而不是:
var p = Process.GetProcessesByName("notepad").FirstOrDefault();
...执行:
IntPtr handle = GetForegroundWindow();
var root = AutomationElement.FromHandle(handle);
...其中 GetForegroundWindow
定义为:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
另请参阅
关于c# - 如何获取当前焦点窗口的选定文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51557059/