4

下の画像には、不明な(カスタム)クラスがある領域があります。それはグリッドでもテーブルでもありません。

ここに画像の説明を入力してください

私はできる必要があります:

  • この領域の行を選択するには
  • 各セルから値を取得するには

問題は、それが一般的なタイプの要素ではないためです。この問題をグーグルで検索したり、自分で解決したりする方法がわかりません。これまでのところ、コードは次のとおりです。

Process[] proc = Process.GetProcessesByName("programname");
AutomationElement window = AutomationElement.FromHandle(proc [0].MainWindowHandle);
PropertyCondition xEllist2 = new PropertyCondition(AutomationElement.ClassNameProperty, "CustomListClass", PropertyConditionFlags.IgnoreCase);
AutomationElement targetElement = window.FindFirst(TreeScope.Children, xEllist2);

私はすでにこのエリアをテキストボックス、グリッド、コンボボックスとして脅かそうとしましたが、これまでのところ問題を解決するものは何もありません。この領域からデータを取得して行を反復処理する方法についてアドバイスはありますか?

編集:申し訳ありませんが、私は間違った仮定をしました。実際、この領域のヘッダー(列1、列2、列3)と「下半分」は異なるコントロールタイプです!!

Wininspectorのおかげで、これらのコントロールタイプに関する詳細情報を掘り下げることができました。

  • ヘッダーには次のプロパティがあります。HeaderControl0x056407DC(90441692)アトム:#43288 0xFFFFFFFF(-1)
  • 下半分には次のものがあります:ListControl 0x056408A4(90441892)Atom:#43288 0x02A6FDA0(44498336)

前に示したコード-「List」要素のみを取得したので、更新は次のとおりです。

Process[] proc = Process.GetProcessesByName("programname");
AutomationElement window = AutomationElement.FromHandle(proc [0].MainWindowHandle);
//getting the header
PropertyCondition xEllist3 = new PropertyCondition(AutomationElement.ClassNameProperty, "CustomHeaderClass", PropertyConditionFlags.IgnoreCase);
AutomationElement headerEl = XElAE.FindFirst(TreeScope.Children, xEllist3);
//getting the list
PropertyCondition xEllist2 = new PropertyCondition(AutomationElement.ClassNameProperty, "CustomListClass", PropertyConditionFlags.IgnoreCase);
AutomationElement targetElement = window.FindFirst(TreeScope.Children, xEllist2);

さらに考えた後、すべての列名を取得しようとしました。

AutomationElementCollection headerLines = headerEl.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.HeaderItem));
string headertest = headerLines[0].GetCurrentPropertyValue(AutomationElement.NameProperty) as string;
textBox2.AppendText("Header 1: " + headertest + Environment.NewLine);

残念ながら、デバッグモードでは、「headerLines」の要素数は0であるため、プログラムはエラーをスローします。

編集2:以下の回答のおかげで-デフォルトのUIAよりも優れた可能性を保持するアンマネージUIオートメーションをインストールしました。http://uiacomwrapper.codeplex.com/ レガシーパターンを使用して、不明なコントロールタイプからデータを取得するにはどうすればよいですか?

if((bool)datagrid.GetCurrentPropertyValue(AutomationElementIdentifiers.IsLegacyIAccessiblePatternAvailableProperty))
{
var pattern = ((LegacyIAccessiblePattern)datagrid.GetCurrentPattern(LegacyIAccessiblePattern.Pattern));
var state = pattern.Current.State;
}

編集3.IUIAutoamtionアプローチ(現在は機能していません)

        _automation = new CUIAutomation();
        cacheRequest = _automation.CreateCacheRequest();
        cacheRequest.AddPattern(UiaConstants.UIA_LegacyIAccessiblePatternId);
        cacheRequest.AddProperty(UiaConstants.UIA_LegacyIAccessibleNamePropertyId);
        cacheRequest.TreeFilter = _automation.ContentViewCondition;
        trueCondition = _automation.CreateTrueCondition();


        Process[] ps = Process.GetProcessesByName("program");
        IntPtr hwnd = ps[0].MainWindowHandle;
        IUIAutomationElement elementMailAppWindow = _automation.ElementFromHandle(hwnd);


        List<IntPtr> ls = new List<IntPtr>();

        ls = GetChildWindows(hwnd);

        foreach (var child in ls)
        {
            IUIAutomationElement iuiae = _automation.ElementFromHandle(child);
            if (iuiae.CurrentClassName == "CustomListClass")
            {
                var outerArayOfStuff = iuiae.FindAllBuildCache(interop.UIAutomationCore.TreeScope.TreeScope_Children, trueCondition, cacheRequest.Clone());
                var outerArayOfStuff2 = iuiae.FindAll(interop.UIAutomationCore.TreeScope.TreeScope_Children, trueCondition);

                var countOuter = outerArayOfStuff.Length;
                var countOuter2 = outerArayOfStuff2.Length;

                var uiAutomationElement = outerArayOfStuff.GetElement(0); // error
                var uiAutomationElement2 = outerArayOfStuff2.GetElement(0); // error
    //...
    //I've erased what's followed next because the code isn't working even now..
              }
        }

この問題のおかげでコードが実装されました:

C#を使用して、別のアプリケーションのSysListView32のデータグリッドからセルアイテムを読み取ります

結果として:

  • countOuterおよびcountOuter2の長さ=0
  • 要素を選択できません(リストからの行)
  • 値を取得することは不可能
  • 何も機能していません
4

1 に答える 1

2

コアUIオートメーションクラスを使用してみることをお勧めします。C#で使用するには、dllをインポートする必要があります。これをビルド前のイベントに追加します(または1回だけ実行するなど)。

"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\tlbimp.exe" %windir%\system32\UIAutomationCore.dll /out:..\interop.UIAutomationCore.dll"

その後、IUIAutomationLegacyIAccessiblePatternを使用できます。

次からの呼び出しに必要な定数を取得します。

C:\ Program Files \ Microsoft SDKs \ Windows \ v7.1 \ Include \ UIAutomationClient.h

私はこの方法でInfragisticsUltragridsを読むことができます。

それが苦痛すぎる場合は、MSAAを使用してみてください。すべてのUIAコアに変換する前に、このプロジェクトをMSAAの開始点として使用しました: MSSAサンプルコード

-----2012年6月25日に編集------

適切な「識別子」を見つけることは、MSUIAutomationのものを使用する上で最も苦痛な部分だと断言できます。私が非常に役立ったのは、「ロケーションレコーダー」として使用できる簡単なフォームアプリケーションを作成することです。基本的に、必要なのは2つだけです。

  • フォームのウィンドウから離れているときでもフォーカスを保持する方法フォーカスを保持する

  • マウスの位置のx、y座標を使用したElementFromPoint()の呼び出し。これは、CUIAutomationクラスに実装されています。

Ctrlボタンを使用して、マウスの座標(System.Windows.Forms.Cursor.Position)を取得するようにアプリに指示します。次に、ポイントから要素を取得し、デスクトップに到達するまで要素の親を再帰的に取得します。

        var desktop = auto.GetRootElement();
        var walker = GetRawTreeWalker();
        while (true)
        {
            element = walker.GetParentElement(element);
            if (auto.CompareElements(desktop, element) == 1){ break;}
        }

-----2012年6月26日に編集-----

自動化の識別子や名前を繰り返し見つけることができたら、ここでコードを簡単に変更できます: http : //blog.functionalfun.net/2009/06/introduction-to-ui-automation-with.htmlコアUIオートメーションクラス。これにより、XPathスタイルの構文を使用して、アプリケーションにネストされたコントロールを識別するために使用できる文字列を再帰的に作成できます。

于 2012-06-22T22:46:40.397 に答える