web-dev-qa-db-ja.com

Windowsでカーソルの下にWordを取得するにはどうすればよいですか?

Wordをカーソルの下に配置する(テキストフィールドだけでなく)アプリケーションを作成したいのですが、その方法がわかりません。 OCRの使用はかなり難しいです。私が機能しているのは、Deskperienceコンポーネントだけです。彼らは「ネイティブ」の方法をサポートしますが、私は彼らが高くつく。今、私はこの「ネイティブ」な方法が何であるかを理解しようとしています(多分どういうわけかフッキング)。どんな助けでもありがたいです。

編集:方法を見つけましたが、コントロールのテキスト全体しか取得できません。テキスト全体からカーソルの下の単語だけを取得する方法はありますか?

49
blez

最近のバージョンの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);
}

UIオートメーションは実際にはInternet ExplorerとFirefoxでサポートされていますが、Chromeではサポートされていません。このリンクを参照してください。 Google Chromeアクセス可能ですか?

さて、これはあなたのための仕事の始まりにすぎません:-)、なぜなら:

  • ほとんどの場合、これはすべてセキュリティに大きな影響を与えます。このテクノロジー(またはWindowFromPointなどの直接Windowsテクノロジー)を使用するには、そのための十分な権限(管理者であるなど)が必要です。また、コンピューターにカーネルドライバーをインストールしない限り、DExperienceがこれらの制限を克服する方法はないと思います。

  • 一部のアプリケーションは、適切な権限があっても、誰にも何も公開しません。たとえば、銀行のアプリケーションを作成している場合、私のアプリケーションが何を表示するかをスパイしてほしくありません:-)。 DRMを使用したOutlookなどの他のアプリケーションは、同じ理由で何も公開しません。

  • UIオートメーションのテキストパターンサポートのみが、テキスト全体よりも多くの情報(Wordなど)を提供できます。悲しいかな、この特定のパターンは、UIオートメーションをグローバルにサポートしていても、IEもFFもサポートしていません。

したがって、これらすべてがうまくいかない場合は、さらに深く掘り下げ、OCRまたは形状認識技術を使用する必要があります。これを使用しても、(セキュリティ権限のため)まったく実行できない場合があります。

50
Simon Mourier

「スパイ」したいアプリケーションがテキスト自体を描画している場合、これは重要です。可能な解決策の1つは、カーソルのすぐ下の領域を無効にすることにより、他のアプリケーションをトリガーしてウィンドウの一部をペイントすることです。

他のアプリケーションがペイントするとき、テキスト描画呼び出しをインターセプトする必要があります。これを行う1つの方法は、他のアプリケーションにコードを挿入し、テキストを描画するGDI関数への呼び出しをインターセプトすることです。ネイティブアプリケーションをデバッグする場合、これがVisual Studioがブレークポイントを実装するために行うことです。 detours のようなライブラリを使用できるというアイデアをテストします(ただし、商用利用は無料ではありません)。

また、アプリケーションがWindowsのアクセシビリティAPIの1つをサポートしているかどうかを確認して、視覚障害者向けのスクリーンリーダーなどを容易にすることもできます。

注意点:私はこれを自分でやったことはありません。

9
user180326

アプリが.Netアプリだけでなく処理する必要がある場合は、関数のインポートから始めます( P/Invoke ):

後で、コントロールを反復処理して、タイプに基づいて内部からテキストを取得することができます。時間があれば、そのようなコードを公開しようと思います。

いくつかのチェックの後、それは最良の方法のように見えます(残念ながら、これも難しい)GDIテキストレンダリング 一部の議論 にフックすることです。

7
baalazamon

私はパトリッカーが言ったことをエコーし​​ますが、あなたが望むことをする確実な方法はないと思います。

あなたはおそらくウィンドウのテキストかそのようなものを手に入れました。しかし、カーソルがウィンドウのテキストを使用してそのコンテンツを格納していないウィンドウの上にある場合はどうなるでしょうか。 Windowsは、特定の方法でデータを保存する義務を負いません。

これは、カーソルの下のピクセルを見て、そこにある単語が何であるかを理解しようとする文字認識に向かっていることになります。しかし、これは非常に重要なだけでなく、絶対に簡単でもありません。 Wordの一部がウィンドウの外に出ているために表示されない場合はどうなりますか?

これは決して簡単なことではありません。これに取り組むにはいくつかの方法があります。しかし、すべてのウィンドウで機能する信頼できる方法はありません。

5
Jonathan Wood

OCRを使用してテキストを取得するためのSDKがあります。それは無料ではありませんが、他の製品と比較してかなり安いです: http://www.screenocr.com/screen-ocr-library-sdk.htm 彼らはあなたができるように同じ機能を提供するアプリケーションを持っていますデモも試してください。

2
Giorgi

これを実現するには、多面的なアプローチが必要です。

UIAは多くのアプリケーションで機能しますが、テキストが返される場所を確認するために実験する必要があります。要素、値、範囲のいずれかになります。オフィスアプリケーション間でも一貫性はありません。

UIAが失敗した場合は、実行中のオブジェクトテーブル(ROT)を列挙し、ROTに登録されているさまざまなアプリへのCOMポインターを取得します。次に、これらのポインタを基になるオフィスタイプにキャストできます。
例えば:

enumerate ROT  - then
 wb = (Excel._Workbook)enumerator.Value;
string strText = wb.Application.ActiveCell.Text.ToString();

上記の2つの方法が失敗した場合は、MODI(Microsoft Office Document Imaging 12.0 Type Library)の無料のOCRシステムを利用してください。

0
RichardB