rautomation 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/History.rdoc +6 -0
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/ext/UiaDll/Release/UiaDll.dll +0 -0
- data/ext/UiaDll/UiaDll/AutomatedSelectList.cpp +49 -43
- data/ext/UiaDll/UiaDll/AutomatedSelectList.h +1 -0
- data/ext/UiaDll/UiaDll/AutomationClicker.h +5 -0
- data/ext/UiaDll/UiaDll/AutomationControl.cpp +4 -0
- data/ext/UiaDll/UiaDll/AutomationControl.h +1 -0
- data/ext/UiaDll/UiaDll/AutomationFinder.cpp +31 -5
- data/ext/UiaDll/UiaDll/AutomationFinder.h +6 -1
- data/ext/UiaDll/UiaDll/stdafx.h +2 -0
- data/ext/WindowsForms/Release/WindowsForms.exe +0 -0
- data/ext/WindowsForms/WindowsForms/DataEntryForm.Designer.cs +1 -0
- data/ext/WindowsForms/WindowsForms/DataEntryForm.cs +5 -0
- data/ext/WindowsForms/WindowsForms/DataGridView.Designer.cs +77 -0
- data/ext/WindowsForms/WindowsForms/DataGridView.cs +42 -0
- data/ext/WindowsForms/WindowsForms/DataGridView.resx +120 -0
- data/ext/WindowsForms/WindowsForms/FizzWare.NBuilder.dll +0 -0
- data/ext/WindowsForms/WindowsForms/MainFormWindow.Designer.cs +15 -2
- data/ext/WindowsForms/WindowsForms/MainFormWindow.cs +70 -79
- data/ext/WindowsForms/WindowsForms/WindowsForms.csproj +12 -0
- data/lib/rautomation/adapter/ms_uia/control.rb +1 -0
- data/lib/rautomation/adapter/ms_uia/uia_dll.rb +10 -0
- data/spec/adapter/ms_uia/control_spec.rb +12 -7
- data/spec/adapter/ms_uia/listbox_spec.rb +10 -0
- data/spec/adapter/win_32/window_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5f0b5a12282ceff2cdd88c9851065c7e3785a51
|
4
|
+
data.tar.gz: f4de36829f09d006d979165664cd9c679cbe8bcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f8b6e450dff617cb3a1b1b372d3319c45a3f86117c701971753959b22ed5cf05a7046fc082355ff51c510f79403d4ec6b805507b22c31266077d1fc7ea7188d
|
7
|
+
data.tar.gz: 375e1b71b72b399694cdc306a3e0f877c8974f68ab77d7d99c411b4f82589c3ee3b713ef83fdffe5c57d95de69b929072a4d88317fa85dac01b5eabf405deea3
|
data/Gemfile.lock
CHANGED
data/History.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -57,8 +57,8 @@ Check out the documentation for other possible usages!
|
|
57
57
|
|
58
58
|
Available adapters:
|
59
59
|
* :win_32 - uses Windows API directly with FFI (default)
|
60
|
-
* :autoit - uses AutoIt for automation
|
61
60
|
* :ms_uia - an experimental adapter
|
61
|
+
* :autoit - uses AutoIt for automation (DEPRECATED)
|
62
62
|
|
63
63
|
When using AutoIt adapter:
|
64
64
|
You might need administrative privileges if running for the first time and you haven't installed AutoIt before!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.3
|
Binary file
|
@@ -20,68 +20,74 @@ array<String^>^ AutomatedSelectList::Selection::get() {
|
|
20
20
|
int AutomatedSelectList::GetOptions(const char* options[]) {
|
21
21
|
auto selectionItems = SelectionItems;
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
if( NULL != options ) {
|
24
|
+
StringHelper::CopyNames(selectionItems, options);
|
25
|
+
}
|
26
26
|
|
27
|
-
|
27
|
+
return selectionItems->Count;
|
28
28
|
}
|
29
29
|
|
30
30
|
bool AutomatedSelectList::SelectByIndex(const int whichItem)
|
31
31
|
{
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
try {
|
33
|
+
auto selectionItems = _control->FindAll(System::Windows::Automation::TreeScope::Subtree, SelectionCondition);
|
34
|
+
Select(selectionItems[whichItem]);
|
35
|
+
return true;
|
36
|
+
} catch(Exception^ e) {
|
37
|
+
Console::WriteLine(e->ToString());
|
38
|
+
return false;
|
39
|
+
}
|
40
40
|
}
|
41
41
|
|
42
42
|
bool AutomatedSelectList::SelectByValue(const char* whichItem)
|
43
43
|
{
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
try {
|
45
|
+
auto nameCondition = gcnew PropertyCondition(AutomationElement::NameProperty, gcnew String(whichItem));
|
46
|
+
auto selectionAndNameCondition = gcnew AndCondition(SelectionCondition, nameCondition);
|
47
|
+
|
48
|
+
Select(_control->FindFirst(System::Windows::Automation::TreeScope::Subtree, selectionAndNameCondition));
|
49
|
+
return true;
|
50
|
+
} catch(Exception^ e) {
|
51
|
+
Console::WriteLine(e->ToString());
|
52
|
+
return false;
|
53
|
+
}
|
54
54
|
}
|
55
55
|
|
56
56
|
bool AutomatedSelectList::GetValueByIndex(const int whichItem, char* comboValue, const int comboValueSize)
|
57
57
|
{
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
58
|
+
try {
|
59
|
+
auto selectionItem = SelectionItems[whichItem];
|
60
|
+
auto nameProperty = dynamic_cast<String^>(selectionItem->GetCurrentPropertyValue(AutomationElement::NameProperty));
|
61
|
+
|
62
|
+
StringHelper::CopyToUnmanagedString(nameProperty, comboValue, comboValueSize);
|
63
|
+
return true;
|
64
|
+
} catch(Exception^ e) {
|
65
|
+
Console::WriteLine(e->ToString());
|
66
|
+
return false;
|
67
|
+
}
|
68
68
|
}
|
69
69
|
|
70
70
|
int AutomatedSelectList::SelectedIndex::get() {
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
71
|
+
int selectedIndex = 0;
|
72
|
+
for each(AutomationElement^ selectionItem in SelectionItems) {
|
73
|
+
auto selectionPattern = dynamic_cast<SelectionItemPattern^>(selectionItem->GetCurrentPattern(SelectionItemPattern::Pattern));
|
74
|
+
if( selectionPattern->Current.IsSelected ) {
|
75
|
+
return selectedIndex;
|
76
|
+
}
|
77
|
+
++selectedIndex;
|
78
|
+
}
|
79
|
+
return -1;
|
80
80
|
}
|
81
81
|
|
82
82
|
|
83
83
|
void AutomatedSelectList::Select(AutomationElement^ itemToSelect)
|
84
84
|
{
|
85
|
-
|
86
|
-
|
85
|
+
auto selectionPattern = dynamic_cast<SelectionItemPattern^>(itemToSelect->GetCurrentPattern(SelectionItemPattern::Pattern));
|
86
|
+
|
87
|
+
try {
|
88
|
+
AutomationClicker::MouseClickOn(itemToSelect);
|
89
|
+
} catch(Exception^) {}
|
90
|
+
|
91
|
+
if( !selectionPattern->Current.IsSelected )
|
92
|
+
selectionPattern->Select();
|
87
93
|
}
|
@@ -10,9 +10,14 @@ ref class AutomationClicker : AutomationControl
|
|
10
10
|
public:
|
11
11
|
AutomationClicker(const HWND windowHandle) : AutomationControl(windowHandle) {}
|
12
12
|
AutomationClicker(const FindInformation& findInformation) : AutomationControl(findInformation) {}
|
13
|
+
AutomationClicker(AutomationElement^ automationElement) : AutomationControl(automationElement) {}
|
13
14
|
bool Click();
|
14
15
|
void MouseClick();
|
15
16
|
|
17
|
+
static void MouseClickOn(AutomationElement^ automationElement) {
|
18
|
+
(gcnew AutomationClicker(automationElement))->MouseClick();
|
19
|
+
}
|
20
|
+
|
16
21
|
private:
|
17
22
|
bool CanInvoke();
|
18
23
|
void Invoke();
|
@@ -19,6 +19,10 @@ AutomationControl::AutomationControl(const FindInformation& findInformation)
|
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
22
|
+
AutomationControl::AutomationControl(AutomationElement^ automationElement) {
|
23
|
+
_control = automationElement;
|
24
|
+
}
|
25
|
+
|
22
26
|
void AutomationControl::Value::set(String^ value) {
|
23
27
|
AsValuePattern->SetValue(value);
|
24
28
|
}
|
@@ -9,6 +9,7 @@ ref class AutomationControl
|
|
9
9
|
public:
|
10
10
|
AutomationControl(const HWND windowHandle);
|
11
11
|
AutomationControl(const FindInformation& findInformation);
|
12
|
+
AutomationControl(AutomationElement^ automationElement);
|
12
13
|
|
13
14
|
property AutomationElement^ Element {
|
14
15
|
AutomationElement^ get() { return _control; }
|
@@ -8,26 +8,47 @@ AutomationFinder::AutomationFinder(AutomationElement^ automationElement)
|
|
8
8
|
|
9
9
|
AutomationElementCollection^ AutomationFinder::Find(...array<Condition^>^ conditions)
|
10
10
|
{
|
11
|
-
|
11
|
+
return Find(Subtree, conditions);
|
12
|
+
}
|
13
|
+
|
14
|
+
AutomationElementCollection^ AutomationFinder::Find(const UIAutomation::TreeScope scope, ...array<Condition^>^ conditions)
|
15
|
+
{
|
16
|
+
return _automationElement->FindAll(scope, SomethingOrEverything(conditions));
|
12
17
|
}
|
13
18
|
|
14
19
|
AutomationElement^ AutomationFinder::FindFirst(...array<Condition^>^ conditions)
|
15
20
|
{
|
16
|
-
|
21
|
+
return FindFirst(Subtree, conditions);
|
22
|
+
}
|
23
|
+
|
24
|
+
AutomationElement^ AutomationFinder::FindFirst(const UIAutomation::TreeScope scope, ...array<Condition^>^ conditions)
|
25
|
+
{
|
26
|
+
return _automationElement->FindFirst(scope, SomethingOrEverything(conditions));
|
17
27
|
}
|
18
28
|
|
19
29
|
AutomationElement^ AutomationFinder::Find(const FindInformation& findInformation)
|
20
30
|
{
|
31
|
+
auto scope = findInformation.onlySearchChildren ? Children : Subtree;
|
32
|
+
|
21
33
|
switch(findInformation.how) {
|
22
34
|
case FindMethod::Id:
|
23
35
|
{
|
24
36
|
auto searchCondition = gcnew PropertyCondition(AutomationElement::AutomationIdProperty, gcnew String(findInformation.data.stringData));
|
25
|
-
|
37
|
+
if( 0 == findInformation.index ) {
|
38
|
+
return FindFirst(scope, searchCondition);
|
39
|
+
}
|
40
|
+
|
41
|
+
return FindAt(scope, findInformation.index, searchCondition);
|
26
42
|
}
|
27
43
|
case FindMethod::Value:
|
28
44
|
{
|
29
45
|
auto searchCondition = gcnew PropertyCondition(AutomationElement::NameProperty, gcnew String(findInformation.data.stringData));
|
30
|
-
|
46
|
+
|
47
|
+
if( 0 == findInformation.index ) {
|
48
|
+
return FindFirst(scope, searchCondition);
|
49
|
+
}
|
50
|
+
|
51
|
+
return FindAt(scope, findInformation.index, searchCondition);
|
31
52
|
}
|
32
53
|
case FindMethod::Focus:
|
33
54
|
return AutomationElement::FocusedElement;
|
@@ -42,7 +63,12 @@ AutomationElement^ AutomationFinder::Find(const FindInformation& findInformation
|
|
42
63
|
|
43
64
|
AutomationElement^ AutomationFinder::FindAt(const int whichItem, ...array<Condition^>^ conditions)
|
44
65
|
{
|
45
|
-
|
66
|
+
return FindAt(Subtree, whichItem, conditions);
|
67
|
+
}
|
68
|
+
|
69
|
+
AutomationElement^ AutomationFinder::FindAt(const UIAutomation::TreeScope scope, const int whichItem, ...array<Condition^>^ conditions)
|
70
|
+
{
|
71
|
+
return Find(scope, conditions)[whichItem];
|
46
72
|
}
|
47
73
|
|
48
74
|
Condition^ AutomationFinder::SomethingOrEverything(...array<Condition^>^ conditions)
|
@@ -6,10 +6,13 @@ ref class AutomationFinder
|
|
6
6
|
{
|
7
7
|
public:
|
8
8
|
AutomationFinder(AutomationElement^ automationElement);
|
9
|
-
AutomationElementCollection^ Find(...array<Condition^>^ conditions);
|
10
9
|
AutomationElement^ Find(const FindInformation& findInformation);
|
10
|
+
AutomationElementCollection^ Find(...array<Condition^>^ conditions);
|
11
|
+
AutomationElementCollection^ Find(const UIAutomation::TreeScope scope, ...array<Condition^>^ conditions);
|
11
12
|
AutomationElement^ FindFirst(...array<Condition^>^ conditions);
|
13
|
+
AutomationElement^ FindFirst(const UIAutomation::TreeScope scope, ...array<Condition^>^ conditions);
|
12
14
|
AutomationElement^ FindAt(const int whichItem, ...array<Condition^>^ conditions);
|
15
|
+
AutomationElement^ FindAt(const UIAutomation::TreeScope scope, const int whichItem, ...array<Condition^>^ conditions);
|
13
16
|
|
14
17
|
static property Condition^ IsSelectionItem {
|
15
18
|
Condition^ get() {
|
@@ -42,6 +45,8 @@ public:
|
|
42
45
|
}
|
43
46
|
|
44
47
|
private:
|
48
|
+
static UIAutomation::TreeScope Subtree = UIAutomation::TreeScope::Subtree;
|
49
|
+
static UIAutomation::TreeScope Children = UIAutomation::TreeScope::Children;
|
45
50
|
AutomationElement^ _automationElement;
|
46
51
|
Condition^ SomethingOrEverything(...array<Condition^>^ conditions);
|
47
52
|
};
|
data/ext/UiaDll/UiaDll/stdafx.h
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
|
21
21
|
using namespace System;
|
22
22
|
using namespace System::Runtime::InteropServices;
|
23
|
+
namespace UIAutomation = System::Windows::Automation;
|
23
24
|
|
24
25
|
typedef enum {
|
25
26
|
Handle = 1,
|
@@ -32,6 +33,7 @@ typedef enum {
|
|
32
33
|
typedef struct _FindInformation {
|
33
34
|
HWND rootWindow;
|
34
35
|
int index;
|
36
|
+
bool onlySearchChildren;
|
35
37
|
FindMethod how;
|
36
38
|
union {
|
37
39
|
char stringData[256];
|
Binary file
|
@@ -98,6 +98,7 @@
|
|
98
98
|
this.personListView.TabIndex = 0;
|
99
99
|
this.personListView.UseCompatibleStateImageBehavior = false;
|
100
100
|
this.personListView.View = System.Windows.Forms.View.Details;
|
101
|
+
this.personListView.SelectedIndexChanged += new System.EventHandler(this.personListView_SelectedIndexChanged);
|
101
102
|
//
|
102
103
|
// columnName
|
103
104
|
//
|
@@ -0,0 +1,77 @@
|
|
1
|
+
namespace WindowsForms
|
2
|
+
{
|
3
|
+
partial class DataGridView
|
4
|
+
{
|
5
|
+
/// <summary>
|
6
|
+
/// Required designer variable.
|
7
|
+
/// </summary>
|
8
|
+
private System.ComponentModel.IContainer components = null;
|
9
|
+
|
10
|
+
/// <summary>
|
11
|
+
/// Clean up any resources being used.
|
12
|
+
/// </summary>
|
13
|
+
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
14
|
+
protected override void Dispose(bool disposing)
|
15
|
+
{
|
16
|
+
if (disposing && (components != null))
|
17
|
+
{
|
18
|
+
components.Dispose();
|
19
|
+
}
|
20
|
+
base.Dispose(disposing);
|
21
|
+
}
|
22
|
+
|
23
|
+
#region Windows Form Designer generated code
|
24
|
+
|
25
|
+
/// <summary>
|
26
|
+
/// Required method for Designer support - do not modify
|
27
|
+
/// the contents of this method with the code editor.
|
28
|
+
/// </summary>
|
29
|
+
private void InitializeComponent()
|
30
|
+
{
|
31
|
+
this.buttonClose = new System.Windows.Forms.Button();
|
32
|
+
this.dataGridView1 = new System.Windows.Forms.DataGridView();
|
33
|
+
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
|
34
|
+
this.SuspendLayout();
|
35
|
+
//
|
36
|
+
// buttonClose
|
37
|
+
//
|
38
|
+
this.buttonClose.Location = new System.Drawing.Point(13, 13);
|
39
|
+
this.buttonClose.Name = "buttonClose";
|
40
|
+
this.buttonClose.Size = new System.Drawing.Size(75, 23);
|
41
|
+
this.buttonClose.TabIndex = 0;
|
42
|
+
this.buttonClose.Text = "Close";
|
43
|
+
this.buttonClose.UseVisualStyleBackColor = true;
|
44
|
+
this.buttonClose.Click += new System.EventHandler(this.buttonClose_Click);
|
45
|
+
//
|
46
|
+
// dataGridView1
|
47
|
+
//
|
48
|
+
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
49
|
+
| System.Windows.Forms.AnchorStyles.Left)
|
50
|
+
| System.Windows.Forms.AnchorStyles.Right)));
|
51
|
+
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
52
|
+
this.dataGridView1.Location = new System.Drawing.Point(13, 56);
|
53
|
+
this.dataGridView1.Name = "dataGridView1";
|
54
|
+
this.dataGridView1.Size = new System.Drawing.Size(641, 190);
|
55
|
+
this.dataGridView1.TabIndex = 1;
|
56
|
+
//
|
57
|
+
// DataGridView
|
58
|
+
//
|
59
|
+
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
60
|
+
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
61
|
+
this.ClientSize = new System.Drawing.Size(666, 258);
|
62
|
+
this.Controls.Add(this.dataGridView1);
|
63
|
+
this.Controls.Add(this.buttonClose);
|
64
|
+
this.Name = "DataGridView";
|
65
|
+
this.Text = "DataGridView";
|
66
|
+
this.Load += new System.EventHandler(this.DataGridView_Load);
|
67
|
+
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
|
68
|
+
this.ResumeLayout(false);
|
69
|
+
|
70
|
+
}
|
71
|
+
|
72
|
+
#endregion
|
73
|
+
|
74
|
+
private System.Windows.Forms.Button buttonClose;
|
75
|
+
private System.Windows.Forms.DataGridView dataGridView1;
|
76
|
+
}
|
77
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
using System;
|
2
|
+
using System.Linq;
|
3
|
+
using System.Windows.Forms;
|
4
|
+
using FizzWare.NBuilder;
|
5
|
+
|
6
|
+
namespace WindowsForms
|
7
|
+
{
|
8
|
+
public partial class DataGridView : Form
|
9
|
+
{
|
10
|
+
public DataGridView()
|
11
|
+
{
|
12
|
+
InitializeComponent();
|
13
|
+
}
|
14
|
+
|
15
|
+
public class Person
|
16
|
+
{
|
17
|
+
// ReSharper disable UnusedMember.Local
|
18
|
+
public String FirstName { get; set; }
|
19
|
+
public String LastName { get; set; }
|
20
|
+
public int Age { get; set; }
|
21
|
+
public String City { get; set; }
|
22
|
+
public String State { get; set; }
|
23
|
+
// ReSharper restore UnusedMember.Local
|
24
|
+
}
|
25
|
+
|
26
|
+
private void DataGridView_Load(object sender, EventArgs e)
|
27
|
+
{
|
28
|
+
var dataSource = new BindingSource();
|
29
|
+
foreach (var person in Builder<Person>.CreateListOfSize(50).Build())
|
30
|
+
{
|
31
|
+
dataSource.Add(person);
|
32
|
+
}
|
33
|
+
dataGridView1.AutoGenerateColumns = true;
|
34
|
+
dataGridView1.DataSource = dataSource;
|
35
|
+
}
|
36
|
+
|
37
|
+
private void buttonClose_Click(object sender, EventArgs e)
|
38
|
+
{
|
39
|
+
Close();
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
@@ -0,0 +1,120 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<root>
|
3
|
+
<!--
|
4
|
+
Microsoft ResX Schema
|
5
|
+
|
6
|
+
Version 2.0
|
7
|
+
|
8
|
+
The primary goals of this format is to allow a simple XML format
|
9
|
+
that is mostly human readable. The generation and parsing of the
|
10
|
+
various data types are done through the TypeConverter classes
|
11
|
+
associated with the data types.
|
12
|
+
|
13
|
+
Example:
|
14
|
+
|
15
|
+
... ado.net/XML headers & schema ...
|
16
|
+
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
17
|
+
<resheader name="version">2.0</resheader>
|
18
|
+
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
19
|
+
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
20
|
+
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
21
|
+
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
22
|
+
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
23
|
+
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
24
|
+
</data>
|
25
|
+
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
26
|
+
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
27
|
+
<comment>This is a comment</comment>
|
28
|
+
</data>
|
29
|
+
|
30
|
+
There are any number of "resheader" rows that contain simple
|
31
|
+
name/value pairs.
|
32
|
+
|
33
|
+
Each data row contains a name, and value. The row also contains a
|
34
|
+
type or mimetype. Type corresponds to a .NET class that support
|
35
|
+
text/value conversion through the TypeConverter architecture.
|
36
|
+
Classes that don't support this are serialized and stored with the
|
37
|
+
mimetype set.
|
38
|
+
|
39
|
+
The mimetype is used for serialized objects, and tells the
|
40
|
+
ResXResourceReader how to depersist the object. This is currently not
|
41
|
+
extensible. For a given mimetype the value must be set accordingly:
|
42
|
+
|
43
|
+
Note - application/x-microsoft.net.object.binary.base64 is the format
|
44
|
+
that the ResXResourceWriter will generate, however the reader can
|
45
|
+
read any of the formats listed below.
|
46
|
+
|
47
|
+
mimetype: application/x-microsoft.net.object.binary.base64
|
48
|
+
value : The object must be serialized with
|
49
|
+
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
50
|
+
: and then encoded with base64 encoding.
|
51
|
+
|
52
|
+
mimetype: application/x-microsoft.net.object.soap.base64
|
53
|
+
value : The object must be serialized with
|
54
|
+
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
55
|
+
: and then encoded with base64 encoding.
|
56
|
+
|
57
|
+
mimetype: application/x-microsoft.net.object.bytearray.base64
|
58
|
+
value : The object must be serialized into a byte array
|
59
|
+
: using a System.ComponentModel.TypeConverter
|
60
|
+
: and then encoded with base64 encoding.
|
61
|
+
-->
|
62
|
+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
63
|
+
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
64
|
+
<xsd:element name="root" msdata:IsDataSet="true">
|
65
|
+
<xsd:complexType>
|
66
|
+
<xsd:choice maxOccurs="unbounded">
|
67
|
+
<xsd:element name="metadata">
|
68
|
+
<xsd:complexType>
|
69
|
+
<xsd:sequence>
|
70
|
+
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
71
|
+
</xsd:sequence>
|
72
|
+
<xsd:attribute name="name" use="required" type="xsd:string" />
|
73
|
+
<xsd:attribute name="type" type="xsd:string" />
|
74
|
+
<xsd:attribute name="mimetype" type="xsd:string" />
|
75
|
+
<xsd:attribute ref="xml:space" />
|
76
|
+
</xsd:complexType>
|
77
|
+
</xsd:element>
|
78
|
+
<xsd:element name="assembly">
|
79
|
+
<xsd:complexType>
|
80
|
+
<xsd:attribute name="alias" type="xsd:string" />
|
81
|
+
<xsd:attribute name="name" type="xsd:string" />
|
82
|
+
</xsd:complexType>
|
83
|
+
</xsd:element>
|
84
|
+
<xsd:element name="data">
|
85
|
+
<xsd:complexType>
|
86
|
+
<xsd:sequence>
|
87
|
+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
88
|
+
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
89
|
+
</xsd:sequence>
|
90
|
+
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
91
|
+
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
92
|
+
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
93
|
+
<xsd:attribute ref="xml:space" />
|
94
|
+
</xsd:complexType>
|
95
|
+
</xsd:element>
|
96
|
+
<xsd:element name="resheader">
|
97
|
+
<xsd:complexType>
|
98
|
+
<xsd:sequence>
|
99
|
+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
100
|
+
</xsd:sequence>
|
101
|
+
<xsd:attribute name="name" type="xsd:string" use="required" />
|
102
|
+
</xsd:complexType>
|
103
|
+
</xsd:element>
|
104
|
+
</xsd:choice>
|
105
|
+
</xsd:complexType>
|
106
|
+
</xsd:element>
|
107
|
+
</xsd:schema>
|
108
|
+
<resheader name="resmimetype">
|
109
|
+
<value>text/microsoft-resx</value>
|
110
|
+
</resheader>
|
111
|
+
<resheader name="version">
|
112
|
+
<value>2.0</value>
|
113
|
+
</resheader>
|
114
|
+
<resheader name="reader">
|
115
|
+
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
116
|
+
</resheader>
|
117
|
+
<resheader name="writer">
|
118
|
+
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
119
|
+
</resheader>
|
120
|
+
</root>
|
Binary file
|
@@ -68,6 +68,7 @@
|
|
68
68
|
this.aboutToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
|
69
69
|
this.treeView = new System.Windows.Forms.TreeView();
|
70
70
|
this.multiLineTextField = new System.Windows.Forms.TextBox();
|
71
|
+
this.buttonDataGridView = new System.Windows.Forms.Button();
|
71
72
|
this.automatableMonthCalendar1 = new WindowsForms.AutomatableMonthCalendar();
|
72
73
|
this.groupBox1.SuspendLayout();
|
73
74
|
this.groupBox2.SuspendLayout();
|
@@ -336,6 +337,7 @@
|
|
336
337
|
this.FruitListBox.Name = "FruitListBox";
|
337
338
|
this.FruitListBox.Size = new System.Drawing.Size(159, 95);
|
338
339
|
this.FruitListBox.TabIndex = 14;
|
340
|
+
this.FruitListBox.SelectedIndexChanged += new System.EventHandler(this.FruitListBox_SelectedIndexChanged);
|
339
341
|
//
|
340
342
|
// menuStrip1
|
341
343
|
//
|
@@ -414,19 +416,29 @@
|
|
414
416
|
this.multiLineTextField.Size = new System.Drawing.Size(325, 123);
|
415
417
|
this.multiLineTextField.TabIndex = 5;
|
416
418
|
//
|
419
|
+
// buttonDataGridView
|
420
|
+
//
|
421
|
+
this.buttonDataGridView.Location = new System.Drawing.Point(12, 152);
|
422
|
+
this.buttonDataGridView.Name = "buttonDataGridView";
|
423
|
+
this.buttonDataGridView.Size = new System.Drawing.Size(95, 23);
|
424
|
+
this.buttonDataGridView.TabIndex = 18;
|
425
|
+
this.buttonDataGridView.Text = "Data Grid View";
|
426
|
+
this.buttonDataGridView.UseVisualStyleBackColor = true;
|
427
|
+
this.buttonDataGridView.Click += new System.EventHandler(this.buttonDataGridView_Click);
|
428
|
+
//
|
417
429
|
// automatableMonthCalendar1
|
418
430
|
//
|
419
431
|
this.automatableMonthCalendar1.Location = new System.Drawing.Point(142, 474);
|
420
432
|
this.automatableMonthCalendar1.MaxSelectionCount = 1;
|
421
433
|
this.automatableMonthCalendar1.Name = "automatableMonthCalendar1";
|
422
434
|
this.automatableMonthCalendar1.TabIndex = 17;
|
423
|
-
this.automatableMonthCalendar1.DateChanged += new System.Windows.Forms.DateRangeEventHandler(this.automatableMonthCalendar1_DateChanged);
|
424
435
|
//
|
425
436
|
// MainFormWindow
|
426
437
|
//
|
427
438
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
428
439
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
429
440
|
this.ClientSize = new System.Drawing.Size(657, 657);
|
441
|
+
this.Controls.Add(this.buttonDataGridView);
|
430
442
|
this.Controls.Add(this.automatableMonthCalendar1);
|
431
443
|
this.Controls.Add(this.multiLineTextField);
|
432
444
|
this.Controls.Add(this.treeView);
|
@@ -495,7 +507,8 @@
|
|
495
507
|
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem1;
|
496
508
|
private System.Windows.Forms.TreeView treeView;
|
497
509
|
private System.Windows.Forms.TextBox multiLineTextField;
|
498
|
-
private AutomatableMonthCalendar automatableMonthCalendar1;
|
510
|
+
private AutomatableMonthCalendar automatableMonthCalendar1;
|
511
|
+
private System.Windows.Forms.Button buttonDataGridView;
|
499
512
|
}
|
500
513
|
}
|
501
514
|
|
@@ -1,87 +1,78 @@
|
|
1
|
-
using System;
|
2
|
-
using System.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
23
|
-
|
24
|
-
private void
|
25
|
-
{
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
{
|
50
|
-
radioButtonLabel.Text = "Option 2 selected";
|
51
|
-
}
|
52
|
-
|
53
|
-
private void radioButtonReset_Click(object sender, EventArgs e)
|
54
|
-
{
|
55
|
-
radioButton1.Checked = false;
|
56
|
-
radioButton2.Checked = false;
|
57
|
-
radioButtonLabel.Text = "No option selected";
|
58
|
-
}
|
59
|
-
|
60
|
-
private void FruitsComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
61
|
-
{
|
62
|
-
fruitsLabel.Text = FruitsComboBox.Text;
|
63
|
-
}
|
64
|
-
|
65
|
-
private void nextFormButton_Click(object sender, EventArgs e)
|
66
|
-
{
|
67
|
-
DataEntryForm form = new DataEntryForm();
|
68
|
-
form.Show();
|
69
|
-
}
|
70
|
-
|
71
|
-
private void buttonButton_Click(object sender, EventArgs e)
|
72
|
-
{
|
73
|
-
SimpleElementsForm buttonForm = new SimpleElementsForm();
|
74
|
-
buttonForm.Show();
|
1
|
+
using System;
|
2
|
+
using System.Windows.Forms;
|
3
|
+
|
4
|
+
namespace WindowsForms
|
5
|
+
{
|
6
|
+
public partial class MainFormWindow : Form
|
7
|
+
{
|
8
|
+
public MainFormWindow()
|
9
|
+
{
|
10
|
+
InitializeComponent();
|
11
|
+
}
|
12
|
+
|
13
|
+
private void label1_Click(object sender, EventArgs e)
|
14
|
+
{
|
15
|
+
|
16
|
+
}
|
17
|
+
|
18
|
+
private void aboutButton_Click(object sender, EventArgs e)
|
19
|
+
{
|
20
|
+
var aboutBox = new AboutBox();
|
21
|
+
aboutBox.Show();
|
22
|
+
}
|
23
|
+
|
24
|
+
private void button1_Click(object sender, EventArgs e)
|
25
|
+
{
|
26
|
+
Close();
|
27
|
+
}
|
28
|
+
|
29
|
+
private void checkBox_CheckedChanged(object sender, EventArgs e)
|
30
|
+
{
|
31
|
+
checkBoxLabel.Text = checkBox.Checked ? "checkBox is on" : "checkBox is off";
|
32
|
+
}
|
33
|
+
|
34
|
+
private void radioButton1_CheckedChanged(object sender, EventArgs e)
|
35
|
+
{
|
36
|
+
radioButtonLabel.Text = "Option 1 selected";
|
37
|
+
}
|
38
|
+
|
39
|
+
private void radioButton2_CheckedChanged(object sender, EventArgs e)
|
40
|
+
{
|
41
|
+
radioButtonLabel.Text = "Option 2 selected";
|
42
|
+
}
|
43
|
+
|
44
|
+
private void radioButtonReset_Click(object sender, EventArgs e)
|
45
|
+
{
|
46
|
+
radioButton1.Checked = false;
|
47
|
+
radioButton2.Checked = false;
|
48
|
+
radioButtonLabel.Text = "No option selected";
|
75
49
|
}
|
76
50
|
|
77
|
-
private void
|
51
|
+
private void FruitsComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
78
52
|
{
|
53
|
+
fruitsLabel.Text = FruitsComboBox.Text;
|
54
|
+
}
|
55
|
+
|
56
|
+
private void nextFormButton_Click(object sender, EventArgs e)
|
57
|
+
{
|
58
|
+
var form = new DataEntryForm();
|
59
|
+
form.Show();
|
60
|
+
}
|
79
61
|
|
62
|
+
private void buttonButton_Click(object sender, EventArgs e)
|
63
|
+
{
|
64
|
+
var buttonForm = new SimpleElementsForm();
|
65
|
+
buttonForm.Show();
|
80
66
|
}
|
81
67
|
|
82
|
-
private void
|
68
|
+
private void buttonDataGridView_Click(object sender, EventArgs e)
|
83
69
|
{
|
70
|
+
new DataGridView().Show();
|
71
|
+
}
|
84
72
|
|
85
|
-
|
86
|
-
|
87
|
-
|
73
|
+
private void FruitListBox_SelectedIndexChanged(object sender, EventArgs e)
|
74
|
+
{
|
75
|
+
fruitsLabel.Text = (string) FruitListBox.SelectedItem;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
@@ -34,6 +34,9 @@
|
|
34
34
|
<WarningLevel>4</WarningLevel>
|
35
35
|
</PropertyGroup>
|
36
36
|
<ItemGroup>
|
37
|
+
<Reference Include="FizzWare.NBuilder">
|
38
|
+
<HintPath>.\FizzWare.NBuilder.dll</HintPath>
|
39
|
+
</Reference>
|
37
40
|
<Reference Include="System" />
|
38
41
|
<Reference Include="System.Core" />
|
39
42
|
<Reference Include="System.Xml.Linq" />
|
@@ -66,6 +69,12 @@
|
|
66
69
|
<Compile Include="DataEntryForm.Designer.cs">
|
67
70
|
<DependentUpon>DataEntryForm.cs</DependentUpon>
|
68
71
|
</Compile>
|
72
|
+
<Compile Include="DataGridView.cs">
|
73
|
+
<SubType>Form</SubType>
|
74
|
+
</Compile>
|
75
|
+
<Compile Include="DataGridView.Designer.cs">
|
76
|
+
<DependentUpon>DataGridView.cs</DependentUpon>
|
77
|
+
</Compile>
|
69
78
|
<Compile Include="SimpleElementsForm.cs">
|
70
79
|
<SubType>Form</SubType>
|
71
80
|
</Compile>
|
@@ -92,6 +101,9 @@
|
|
92
101
|
<EmbeddedResource Include="DataEntryForm.resx">
|
93
102
|
<DependentUpon>DataEntryForm.cs</DependentUpon>
|
94
103
|
</EmbeddedResource>
|
104
|
+
<EmbeddedResource Include="DataGridView.resx">
|
105
|
+
<DependentUpon>DataGridView.cs</DependentUpon>
|
106
|
+
</EmbeddedResource>
|
95
107
|
<EmbeddedResource Include="SimpleElementsForm.resx">
|
96
108
|
<DependentUpon>SimpleElementsForm.cs</DependentUpon>
|
97
109
|
</EmbeddedResource>
|
@@ -13,6 +13,7 @@ module RAutomation
|
|
13
13
|
# @option locators [String, Regexp] :class Internal class name of the button
|
14
14
|
# @option locators [String, Fixnum] :id Internal ID of the button
|
15
15
|
# @option locators [String, Fixnum] :index 0-based index to specify n-th button if all other criteria match
|
16
|
+
# @option locators [String, Boolean] :children_only limit the scope of the search to children only
|
16
17
|
# @see RAutomation::Window#button
|
17
18
|
def initialize(window, locators)
|
18
19
|
@window = window
|
@@ -25,6 +25,7 @@ module RAutomation
|
|
25
25
|
info = SearchCriteria.new
|
26
26
|
info.parent_window = parent
|
27
27
|
info.index = locator[:index] || 0
|
28
|
+
info.children_only = locator[:children_only]
|
28
29
|
|
29
30
|
case
|
30
31
|
when locator[:hwnd]
|
@@ -61,6 +62,14 @@ module RAutomation
|
|
61
62
|
self[:index] = value
|
62
63
|
end
|
63
64
|
|
65
|
+
def children_only?
|
66
|
+
self[:children_only]
|
67
|
+
end
|
68
|
+
|
69
|
+
def children_only=(yes_or_no)
|
70
|
+
self[:children_only] = yes_or_no
|
71
|
+
end
|
72
|
+
|
64
73
|
def parent_window
|
65
74
|
self[:hwnd]
|
66
75
|
end
|
@@ -95,6 +104,7 @@ module RAutomation
|
|
95
104
|
|
96
105
|
layout :hwnd, :int,
|
97
106
|
:index, :int,
|
107
|
+
:children_only, :bool,
|
98
108
|
:how, HowToFind, :data, FindData
|
99
109
|
end
|
100
110
|
|
@@ -1,27 +1,32 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "MsUia::Control", :if => SpecHelper.adapter == :ms_uia do
|
4
|
+
let(:window) { RAutomation::Window.new(:title => /MainFormWindow/i) }
|
4
5
|
|
5
6
|
it "control coordinates", :special => false do
|
6
|
-
window = RAutomation::Window.new(:title => /MainFormWindow/i)
|
7
|
-
|
8
7
|
window.maximize
|
9
8
|
control = window.control(:id => "radioButtonReset")
|
10
9
|
control.bounding_rectangle.should be_all {|coord| coord.between?(200, 400)}
|
11
10
|
end
|
12
11
|
|
13
12
|
it "control process id", :special => true do
|
14
|
-
window = RAutomation::Window.new(:title => /MainFormWindow/i)
|
15
|
-
|
16
13
|
control = window.control(:id => "radioButtonReset")
|
17
14
|
control.new_pid.should == @pid1
|
18
15
|
end
|
19
16
|
|
20
17
|
it "has a class" do
|
21
|
-
window = RAutomation::Window.new(:title => /MainFormWindow/i)
|
22
|
-
|
23
18
|
control = window.control(:id => "radioButtonReset")
|
24
|
-
control.control_class.should =~ /WindowsForms10.BUTTON
|
19
|
+
control.control_class.should =~ /WindowsForms10.BUTTON.*/
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can limit the search depth" do
|
23
|
+
window.button(:id => 'buttonDataGridView').click { true }
|
24
|
+
data_grid_window = RAutomation::Window.new(:title => /DataGridView/i)
|
25
|
+
|
26
|
+
start = Time.new
|
27
|
+
data_grid_window.button(:id => 'buttonClose', :children_only => true).exist?
|
28
|
+
elapsed_time = Time.new - start
|
29
|
+
elapsed_time.should be < 2
|
25
30
|
end
|
26
31
|
|
27
32
|
context RAutomation::Adapter::MsUia::UiaDll::SearchCriteria, :pure_unit => true do
|
@@ -62,4 +62,14 @@ describe "MsUia::ListBox", :if => SpecHelper.adapter == :ms_uia do
|
|
62
62
|
|
63
63
|
list_box.strings.should == ["Apple", "Orange", "Mango"]
|
64
64
|
end
|
65
|
+
|
66
|
+
it "fires events when the index changes" do
|
67
|
+
list_box = RAutomation::Window.new(:title => "MainFormWindow").list_box(:id => "FruitListBox")
|
68
|
+
label = RAutomation::Window.new(:title => "MainFormWindow").label(:id => "fruitsLabel")
|
69
|
+
|
70
|
+
['Apple', 'Orange', 'Mango'].each_with_index do |value, index|
|
71
|
+
list_box.select index
|
72
|
+
label.value.should eq(value)
|
73
|
+
end
|
74
|
+
end
|
65
75
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rautomation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jarmo Pertman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -158,6 +158,10 @@ files:
|
|
158
158
|
- ext/WindowsForms/WindowsForms/DataEntryForm.Designer.cs
|
159
159
|
- ext/WindowsForms/WindowsForms/DataEntryForm.cs
|
160
160
|
- ext/WindowsForms/WindowsForms/DataEntryForm.resx
|
161
|
+
- ext/WindowsForms/WindowsForms/DataGridView.Designer.cs
|
162
|
+
- ext/WindowsForms/WindowsForms/DataGridView.cs
|
163
|
+
- ext/WindowsForms/WindowsForms/DataGridView.resx
|
164
|
+
- ext/WindowsForms/WindowsForms/FizzWare.NBuilder.dll
|
161
165
|
- ext/WindowsForms/WindowsForms/MainFormWindow.Designer.cs
|
162
166
|
- ext/WindowsForms/WindowsForms/MainFormWindow.cs
|
163
167
|
- ext/WindowsForms/WindowsForms/MainFormWindow.resx
|