gpt4 book ai didi

c# - 如何从另一个应用程序的文本框中获取插入符号的位置? (不是坐标,而是文本框内的实际索引)

转载 作者:行者123 更新时间:2023-12-04 10:10:09 27 4
gpt4 key购买 nike

我需要在焦点窗口的文本框中检索插入符号的索引,可能使用 UI 自动化,或者可能是 Win32 API 函数,如果有 cat 执行此操作的任何函数。
我强调,我不是指 x,y 坐标,而是文本框文本内插入符号的索引。我怎样才能做到这一点?
另见 this类似的问题。

最佳答案

您可以为此使用 UI 自动化,尤其是 IUIAutomationTextPattern2具有 GetCaretRange 的接口(interface)方法。

下面是两个示例控制台应用程序(C++ 和 C# 代码),它们连续运行并显示鼠标下当前元素的插入符号位置:

C++ 版本

int main()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
CComPtr<IUIAutomation> automation;

// make sure you use CLSID_CUIAutomation8, *not* CLSID_CUIAutomation
automation.CoCreateInstance(CLSID_CUIAutomation8);
do
{
POINT pt;
if (GetCursorPos(&pt))
{
CComPtr<IUIAutomationElement> element;
automation->ElementFromPoint(pt, &element);
if (element)
{
CComBSTR name;
element->get_CurrentName(&name);
wprintf(L"Watched element %s\n", name);

CComPtr<IUIAutomationTextPattern2> text;
element->GetCurrentPatternAs(UIA_TextPattern2Id, IID_PPV_ARGS(&text));
if (text)
{
// get document range
CComPtr<IUIAutomationTextRange> documentRange;
text->get_DocumentRange(&documentRange);

// get caret range
BOOL active = FALSE;
CComPtr<IUIAutomationTextRange> range;
text->GetCaretRange(&active, &range);
if (range)
{
// compare caret start with document start
int caretPos = 0;
range->CompareEndpoints(TextPatternRangeEndpoint_Start, documentRange, TextPatternRangeEndpoint_Start, &caretPos);
wprintf(L" caret is at %i\n", caretPos);
}
}
}
}
Sleep(500);
} while (TRUE);
}
CoUninitialize();
return 0;
}

C#版本
static void Main(string[] args)
{
// needs 'using UIAutomationClient;'
// to reference UIA, don't use the .NET assembly
// but instead, reference the UIAutomationClient dll as a COM object
// and set Embed Interop Types to False for the UIAutomationClient reference in the C# project
var automation = new CUIAutomation8();
do
{
var cursor = System.Windows.Forms.Cursor.Position;
var element = automation.ElementFromPoint(new tagPOINT { x = cursor.X, y = cursor.Y });
if (element != null)
{
Console.WriteLine("Watched element " + element.CurrentName);
var guid = typeof(IUIAutomationTextPattern2).GUID;
var ptr = element.GetCurrentPatternAs(UIA_PatternIds.UIA_TextPattern2Id, ref guid);
if (ptr != IntPtr.Zero)
{
var pattern = (IUIAutomationTextPattern2)Marshal.GetObjectForIUnknown(ptr);
if (pattern != null)
{
var documentRange = pattern.DocumentRange;
var caretRange = pattern.GetCaretRange(out _);
if (caretRange != null)
{
var caretPos = caretRange.CompareEndpoints(
TextPatternRangeEndpoint.TextPatternRangeEndpoint_Start,
documentRange,
TextPatternRangeEndpoint.TextPatternRangeEndpoint_Start);
Console.WriteLine(" caret is at " + caretPos);
}
}
}
}
Thread.Sleep(500);
}
while (true);
}

诀窍是使用 IUIAutomationTextRange::CompareEndpoints允许您将插入符号范围与另一个范围(例如整个文档范围)进行比较的方法。

注意有缺点:
  • 有些应用根本不支持任何 MSAA/UIA 内省(introspection),或者不支持文本模式。对于这些,根本没有解决方案(我认为即使使用 Windows API)
  • 某些应用程序错误地报告插入符号,尤其是当您选择文本时(因此,使用移动的插入符号)。例如,使用记事本,在按下 SHIFT 的同时向左移动将向后选择,但由于某种原因 UIA 不会更新插入符号位置。我认为这是记事本的问题,因为它也使用全局插入符号位置的 IME(输入法编辑器,如您可以使用 Win+ 召唤的表情符号编辑器;键盘组合)也存在插入符号问题。例如,写字板没有问题。
  • 关于c# - 如何从另一个应用程序的文本框中获取插入符号的位置? (不是坐标,而是文本框内的实际索引),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61368790/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com