rautomation 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|