c# - 从另一个应用程序的文本框中获取文本和插入符号
问题描述
背景资料
我正在开发一个 Windows Speech-To-Text 应用程序。
识别语音后,应将文本插入当前具有键盘焦点的文本框中(Think Word/Firefox/其他应用程序)。要插入我当前使用的文本InputSimulatorPlus。
插入文本时,识别文本的格式必须适合周围的文本,例如:
- 标点符号后的大写字母
- 不在标点符号之后的第一个字母小写
- 换行首字母大写
- 标点后的空格
等等
问题
为了能够格式化文本,我需要文本和插入符号位置。
目前我一直在使用UI Automation NuGet Package with Text Pattern。这适用于所有支持文本模式的文本框,但很多程序不支持文本模式。
策略问题:我应该使用 UI 自动化以外的其他方法吗?
我注意到很多我想支持的应用程序不支持文本模式,但支持值模式或传统 IAccessible 模式(Microsoft Active Accessibility)。
我一直在研究使用值模式并且可以获取文本框的文本,但不能获取插入符号的位置。
using System.Windows.Automation;
using System.Windows.Automation.Text;
...
AutomationElement automationElement = AutomationElement.FocusedElement;
var elements = automationElement.FindAll(TreeScope.Element,
new AndCondition(
new PropertyCondition(AutomationElement.HasKeyboardFocusProperty, true),
new PropertyCondition(AutomationElement.IsValuePatternAvailableProperty, true)));
foreach (AutomationElement element in elements)
{
if (element.GetCurrentPattern(ValuePattern.Pattern) is ValuePattern valuePattern)
{
var text = valuePattern.Current.Value;
var caret = ? //How to get caret position?
Console.WriteLine($"Caret: {caret}, Text: {text}");
return (text,caret);
}
}
我也一直在研究使用Legacy IAccessible Pattern并且可以获取文本框的文本,但不能获取插入符号的位置。
using System.Windows.Automation;
using System.Windows.Automation.Text;
...
AutomationElement automationElement = AutomationElement.FocusedElement;
var elements = automationElement.FindAll(TreeScope.Element,
new AndCondition(
new PropertyCondition(AutomationElement.HasKeyboardFocusProperty, true),
new PropertyCondition(AutomationElement.IsLegacyIAccessiblePatternAvailableProperty, true)));
foreach (AutomationElement element in elements)
{
if (element.GetCurrentPattern(LegacyIAccessiblePattern.Pattern) is LegacyIAccessiblePattern legazyAccessiblePattern)
{
var text = legazyAccessiblePattern.Current.Value;
var caret = ? //How to get caret position?
Console.WriteLine($"Caret: {caret}, Text: {text}");
return (text,caret);
}
}
主要问题:如何使用 UI 自动化获取给定文本框的插入符号位置?
PS我知道这永远不会适用于所有应用程序,但如果它可以适用于大多数普通应用程序,那就太棒了。
解决方案
你不想要 ValuePattern,你想要IUIAutomationTextPattern2
,它支持GetCaretRange。
如果您需要回退到 MSAA,那就更麻烦了(而且您根本无法获得插入符号周围的文本)。MSAA 没有像 UIAutomation 那样的文本支持。如果你真的真的不能使用 UIAutomation,那么你唯一真正的选择是使用Text Services Framework,它的文档记录很差,因此没有被广泛实施。如果你需要文本服务框架,你可能想看看我的博客,它已经有一段时间没有更新了。
对于 MSAA 插入符号,首先调用GetGUIThreadInfo
. 这将返回有关 a 的数据hwndCaret
,这是当前包含插入符号的窗口。(或者您可以尝试使用hwndFocus
if hwndCaret
is NULL。)使用其中一个窗口,您可以执行以下操作:
IAccessible *pAccCaret = NULL;
VARIANT varCaret;
varCaret.vt = VT_I4;
varCaret.lVal = CHILDID_SELF;
if (SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_CARET, IID_IAccessible, (void **)&pAccCaret)))
{
hr = pAccCaret->accLocation( &rcCaret.left, &rcCaret.top, &rcCaret.right, &rcCaret.bottom, varCaret);
pAccCaret->Release();
}
推荐阅读
- c# - 如何将加载到列表框中的数组的值复制到单独的文本框。
- ios - 在 iOS 中获得内存压力通知(关键)
- python - 设置 GTK Webkit.Webview 的 HTML 内容?
- java - 当应该动态设置图像时,如何将源添加到android中的imageView?
- java - 如何在 JavaFX 的 TextInputDialog 中执行输入检查?
- python - 随机化图像中黑色像素的位置
- gradle - 使用junit5自定义构建任务
- assembly - 如何在 x86 程序集中操作 REAL8 值以存储到缓冲区?(包括欧文32)
- java - 递归在完成最后一步时不要返回到后一步
- r - 图像无法在 R 闪亮中显示