我想创建一个应用程序来获取光标下的单词(不仅仅是文本字段),但我找不到如何做到这一点。使用OCR非常困难。我见过的唯一工作就是Deskperience组件。他们支持'本土'方式,但我花了很多钱。现在我想弄清楚这种“原生”方式是什么(也许某种程度上是挂钩)。任何帮助将不胜感激。
修改 我找到了一种方法,但它只获得了控件的整个文本。知道怎么只从全文中获取光标下的单词吗?
答案 0 :(得分:50)
在最近的Windows版本中,将信息从一个应用程序收集到另一个应用程序(如果您当前没有目标应用程序)的推荐方法是使用 UI Automation 技术。 维基百科非常适合提供更多相关信息:Microsoft UI Automation
基本上,UI自动化将使用所有必要的手段来收集可以收集的内容
这是一个小型控制台应用程序代码,可以监视其他应用程序的UI。运行它并将鼠标移动到不同的应用程序。每个应用程序对各种“UI自动化模式”都有不同的支持。例如,这里展示了Value模式和Text模式。
static void Main(string[] args)
{
do
{
System.Drawing.Point mouse = System.Windows.Forms.Cursor.Position; // use Windows forms mouse code instead of WPF
AutomationElement element = AutomationElement.FromPoint(new System.Windows.Point(mouse.X, mouse.Y));
if (element == null)
{
// no element under mouse
return;
}
Console.WriteLine("Element at position " + mouse + " is '" + element.Current.Name + "'");
object pattern;
// the "Value" pattern is supported by many application (including IE & FF)
if (element.TryGetCurrentPattern(ValuePattern.Pattern, out pattern))
{
ValuePattern valuePattern = (ValuePattern)pattern;
Console.WriteLine(" Value=" + valuePattern.Current.Value);
}
// the "Text" pattern is supported by some applications (including Notepad)and returns the current selection for example
if (element.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
{
TextPattern textPattern = (TextPattern)pattern;
foreach(TextPatternRange range in textPattern.GetSelection())
{
Console.WriteLine(" SelectionRange=" + range.GetText(-1));
}
}
Thread.Sleep(1000);
Console.WriteLine(); Console.WriteLine();
}
while (true);
}
实际上,Internet Explorer和Firefox支持UI自动化,但据我所知,Chrome不支持。请看这个链接:When will Google Chrome be accessible?
现在,这只是你工作的开始:-),因为:
大多数时候,这一切都有很大的安全隐患。使用此技术(或直接Windows技术,如WindowFromPoint)将需要足够的权限(例如作为管理员)。我不认为DExperience有任何方法可以克服这些限制,除非他们在计算机上安装内核驱动程序。
即使拥有适当的权利,某些应用程序也不会向任何人公开任何内容。例如,如果我正在编写银行应用程序,我不希望您监视我的应用程序将显示的内容:-)。其他应用程序(如带有DRM的Outlook)不会出于同样的原因暴露任何内容。
只有UI自动化文本模式支持才能提供更多信息(如单词),而不仅仅是整个文本。唉,IE和FF都不支持这种特定模式,即使它们支持全球UI自动化。
因此,如果所有这些对你不起作用,你将不得不深入研究并使用OCR或形状识别技术。即便如此,在某些情况下你根本无法做到这一点(因为担保权)。
答案 1 :(得分:10)
如果您想要“窥探”的应用程序自己绘制文本,这是非常重要的。一种可能的解决方案是通过使光标正下方的区域无效来触发另一个应用程序绘制其窗口的一部分。
当其他应用程序绘制时,您将不得不拦截文本绘图调用。一种方法是在另一个应用程序中注入代码,并拦截调用到绘制文本的GDI函数。调试本机应用程序时,这是visual studio实现断点的方法。要测试这个想法,您可以使用像detours这样的库(但这不是免费用于商业用途)。
您还可以检查应用程序是否支持Windows中的某个可访问性API,以便为盲人屏幕阅读器等内容提供便利。
提醒一句:我自己没有这样做过。
答案 2 :(得分:7)
如果应用程序不仅需要处理.Net应用程序,我将从导入函数(P/Invoke)开始:
稍后您可以迭代控件并尝试根据类型从内部获取文本。如果我找到一些时间,我会尝试发布这样的代码。
经过一些检查后,看起来最好的方法(不幸的是也很难)是挂钩GDI文本呈现some discussion
答案 3 :(得分:5)
我会回应Patricker的说法,但我认为没有可靠的方法来做你想做的事。
您可能获得了窗口文本或类似内容。但是如果光标位于不使用窗口文本存储其内容的窗口上呢? Windows没有义务以特定方式存储数据。
这最终会指向字符识别,您可以在其中查看光标下的像素,并尝试找出哪些字样。但这不仅非常重要,而且也不是万无一失的。如果单词的一部分因为它延伸出窗口而不可见,该怎么办?
这绝对不是微不足道的。有几种方法可以解决它。但是没有可靠的方法可以适用于所有窗口。
答案 4 :(得分:2)
有一个用于使用OCR获取文本的sdk。它不是免费的,但与其他产品相比它相当便宜:http://www.screenocr.com/screen-ocr-library-sdk.htm它们有一个提供相同功能的应用程序,因此您也可以尝试演示。
答案 5 :(得分:0)
要实现这一目标,您需要采取多管齐下的方法。
UIA确实可以在许多应用程序中运行,但您需要尝试查看文本的返回位置。它可能在元素,值或范围内。即使在办公室应用程序中也没有一致性。
如果UIA失败,则枚举运行对象表(ROT)并将COM指针检索到ROT中注册的各种应用程序。然后,您可以将这些指针强制转换为基础办公室类型:
例如:
enumerate ROT - then
wb = (Excel._Workbook)enumerator.Value;
string strText = wb.Application.ActiveCell.Text.ToString();
如果以上两种方法失败,请使用MODI中的免费OCR系统(Microsoft Office Document Imaging 12.0类型库)