概要‎ > ‎

Window取得

Window、GUI要素の取得は複数の手段があります。
それは、対象とするウィンドウの実装方法によって、最良の手段が異なるからです。
選択するときのポイントは以下のものです。
1.確実に繰り返し取得できること。
2.GUIの仕様変更に可能な限り耐えうること。
3.画面の特性に合わせるlこと。

2に関しては仕様変更があれば、テストの修正も覚悟しなければなりません。
しかし、それでも変更量が少ないに越したことはありません。
また、重要なのは、プロダクトコードを作成するときに常にテストを意識することです。
(理想はテストファーストです。難しいですが。)
テストで使用するフィールド、プロパティー、メソッドは仕様として固定しておけば、テストメンテナンスの工数削減に役立ちます。

3に関しては、画面には、それぞれ特性があります。
例えば、条件によって、配置が変更されたり、文言が変化したりなどです。
特性に合った最適な取得方法を選択する必要があります。
以下にセオリーというかコツを書きました。参考にしてみてください。

また、ウィンドウの特定にはTestAssistantが役に立ちますのでご利用お願いします。

それから、以下の取得は全てWindowControlのインターフェイスを使っていますので、そちらのAPIリファレンスも参照お願いします。


.Netのフィールド、プロパティー、メソッドを使って取得
.Netアプリケーションであるなら、この方法が一番です。
テスト作成後のプロダクトコード修正によるテストの影響も明確です。
また、フィールド名称からの取得だけでなく、既存の.NetのSystem.Windows.Forms.Control.FromHandleや
System.Windows.Forms.Application.OpenFormsなども活用してみてください。

//WindowsAppFriend app が宣言されているとする
//Process process は対象プロセスが入っているものとする

//メインウィンドウ取得
AppVar mainWindow = app["System.Windows.Forms.Control.FromHandle"](process.MainWindowHandle);

//開いているすべてのフォームに対する処理
List<string> titles = new List<string>();
foreach(AppVar element in new Enumerate(app["System.Windows.Forms.Application.OpenForms"]()))
{
titles.Add((string)element["Text"]().Core);
}

TestAssistantでは「.Netのフィールドで取得」がこれに当たります。
また、「操作画面」でフィールド、プロパティー、メソッドから取得することもできます。



ダイアログIDから取得
ネイティブのダイアログであれば、この方法が一番です。
ただ、画面起動のたびにコントロールを生成して、ダイアログIDをその都度任意で設定しているものは除きます。
WindowControlのIdentifyFromDialogIdを使用します。



ZIndexから取得
コントロールのZ順で設定したインデックスから取得します。
この方法も多くの画面で正確にウィンドウを取得できます。
ウィンドウ内のコントロールの数が開くたびに変化するものでは使用できません。
WindowControlのIdentifyFromZIndexを使用します。



WindowTextから取得
ネイティブAPIのGetWindowTextで取得できる文字列から取得します。(GetWindowTextはテストプロセスで実行されます。)
外部仕様に表れる情報から取得できるのでわかりやすいかもしれません。
例えば、メッセージボックスの「OK」ボタンなんどの取得には向いています。
条件によって文字列が変化するものには使用できません。
ウィンドウを特定するには、WindowControlのIdentifyFromZIndexを使用します。
また、複数指定の文字列のウィンドウが検出される場合にはWindowControlのGetFromWindowTextを使用します。



Boundsから取得
ネイティブAPIのGetWindowRectで取得できる矩形から取得します。
座標は取得元のWindowControlに対応するウィンドウからのクライアント座標です。
コントロールの矩形が全く変わらない固定ウィンドウでは使用可能です。
ただし、サイズ変更可能なダイアログでは多くの場合使用できません。
使いどころの難しい取得方式です。
ウィンドウを特定するには、WindowControlのIdentifyFromBoundsを使用します。
また、複数指定の矩形のウィンドウが検出される場合にはWindowControlのGetFromBoundsを使用します。



.Netの型フルネームから取得
.Net型のフルネームから取得します。
例えば、画面上にSystem.Windows.Forms.DataGridViewが一つしかないなら以下のように特定可能です。
AppVar grid = form.IdentifyFromTypeFullName("System.Windows.Forms.DataGridView");

ウィンドウを特定するには、WindowControlのIdentifyFromTypeFullNameを使用します。
また、複数指定の型のウィンドウが検出される場合にはWindowControlのGetFromTypeFullNameを使用します。



WindowClass名称から取得
WindowClass名称から取得します。
先ほどの.Netの型フルネームから取得は.Net用なのに対し、こちらはネイティブ用です。
例えば、画面上にEditが一つしかないなら以下のように特定可能です。
WindowControl edit = dlg.IdentifyeFromWindowClass("Edit");

ウィンドウを特定するには、WindowControlのIdentifyeFromWindowClassを使用します。
また、複数指定の型のウィンドウが検出される場合にはWindowControlのGetFromWindowClassを使用します。



ウィンドウハンドルから取得
何らかの手段でウィンドウハンドルが取得できるなら、それを使ってWindowControlを生成することが可能です。
.Netのウィンドウの場合は、生成後にWindowControlの保持するAppVarを使って(もしくは[]プロパティーを使用して)FriendlyOperationの呼び出しが可能です。
WindowControl  target = new WindowControl(app, handle);//appはWindowsAppFriend, handleはIntPtr



その他
場合によっては、GetFromWindowTextとGetFromWindowClassの組み合わせなど、複数の条件で検索したり、ここには紹介していない
お客様独自の方法で取得するのもアリです。
重要なのは、画面に合わせて確実に目的のウィンドウを特定できることです。
よろしくお願いします。