rautomation 0.7.3 → 0.8.0
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.
- data/.gitignore +9 -8
- data/Gemfile.lock +2 -2
- data/History.rdoc +13 -0
- data/README.rdoc +3 -2
- data/Rakefile +30 -10
- data/VERSION +1 -1
- data/ext/UiaDll/Release/UiaDll.dll +0 -0
- data/ext/UiaDll/UiaDll/AssemblyInfo.cpp +40 -0
- data/ext/UiaDll/UiaDll/AutomatedComboBox.cpp +66 -0
- data/ext/UiaDll/UiaDll/AutomatedComboBox.h +32 -0
- data/ext/UiaDll/UiaDll/AutomatedTable.cpp +50 -0
- data/ext/UiaDll/UiaDll/AutomatedTable.h +22 -0
- data/ext/UiaDll/UiaDll/AutomationClicker.cpp +50 -0
- data/ext/UiaDll/UiaDll/AutomationClicker.h +24 -0
- data/ext/UiaDll/UiaDll/ExpandCollapseHelper.cpp +53 -0
- data/ext/UiaDll/UiaDll/ExpandCollapseHelper.h +22 -0
- data/ext/UiaDll/UiaDll/MenuItemSelector.cpp +75 -0
- data/ext/UiaDll/UiaDll/MenuItemSelector.h +22 -0
- data/ext/UiaDll/UiaDll/ReadMe.txt +8 -18
- data/ext/UiaDll/UiaDll/StringHelper.cpp +9 -0
- data/ext/UiaDll/UiaDll/StringHelper.h +7 -0
- data/ext/UiaDll/UiaDll/ToggleStateHelper.cpp +33 -0
- data/ext/UiaDll/UiaDll/ToggleStateHelper.h +10 -0
- data/ext/UiaDll/UiaDll/UiaDll.cpp +458 -325
- data/ext/UiaDll/UiaDll/UiaDll.h +13 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj +45 -28
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +66 -7
- data/ext/UiaDll/UiaDll/app.ico +0 -0
- data/ext/UiaDll/UiaDll/app.rc +0 -0
- data/ext/UiaDll/UiaDll/dllmain.cpp +5 -23
- data/ext/UiaDll/UiaDll/resource.h +3 -0
- data/ext/UiaDll/UiaDll/stdafx.cpp +0 -3
- data/ext/UiaDll/UiaDll/stdafx.h +23 -18
- data/ext/UiaDll/UiaDll.sln +6 -6
- data/ext/WindowsForms/Release/WindowsForms.exe +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/AboutBox.Designer.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/AboutBox.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/AboutBox.resx +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/DataEntryForm.Designer.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/DataEntryForm.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/DataEntryForm.resx +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/MainFormWindow.Designer.cs +173 -76
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/MainFormWindow.cs +76 -77
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/MainFormWindow.resx +3 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/PersonForm.Designer.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/PersonForm.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/PersonForm.resx +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/Program.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/Properties/AssemblyInfo.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/Properties/Resources.Designer.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/Properties/Resources.resx +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/Properties/Settings.Designer.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/Properties/Settings.settings +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/SimpleElementsForm.Designer.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/SimpleElementsForm.cs +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/SimpleElementsForm.resx +0 -0
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms → WindowsForms}/WindowsForms.csproj +2 -2
- data/ext/WindowsForms/{src/WindowsForms/WindowsForms.sln → WindowsForms.sln} +0 -0
- data/lib/rautomation/adapter/ms_uia/constants.rb +1 -0
- data/lib/rautomation/adapter/ms_uia/control.rb +11 -0
- data/lib/rautomation/adapter/ms_uia/functions.rb +8 -5
- data/lib/rautomation/adapter/ms_uia/menu.rb +36 -0
- data/lib/rautomation/adapter/ms_uia/select_list.rb +4 -12
- data/lib/rautomation/adapter/ms_uia/table.rb +90 -11
- data/lib/rautomation/adapter/ms_uia/uia_dll.rb +48 -2
- data/lib/rautomation/adapter/ms_uia/window.rb +6 -1
- data/lib/rautomation/adapter/ms_uia.rb +1 -0
- data/spec/adapter/autoit/mouse_spec.rb +2 -2
- data/spec/adapter/ms_uia/functions_spec.rb +39 -0
- data/spec/adapter/ms_uia/select_list_spec.rb +26 -13
- data/spec/adapter/ms_uia/table_spec.rb +96 -2
- data/spec/adapter/ms_uia/window_spec.rb +37 -11
- data/spec/adapter/win_32/mouse_spec.rb +2 -2
- data/spec/adapter/win_32/window_spec.rb +0 -9
- data/spec/spec_helper.rb +3 -3
- data/spec/window_spec.rb +17 -6
- metadata +48 -40
- data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.cpp +0 -174
- data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.vcxproj +0 -95
- data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.vcxproj.filters +0 -42
- data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.vcxproj.user +0 -3
- data/ext/ListViewExplorer/ListViewExplorer/ReadMe.txt +0 -40
- data/ext/ListViewExplorer/ListViewExplorer/stdafx.cpp +0 -8
- data/ext/ListViewExplorer/ListViewExplorer/stdafx.h +0 -17
- data/ext/ListViewExplorer/ListViewExplorer/table_support.cpp +0 -250
- data/ext/ListViewExplorer/ListViewExplorer/table_support.h +0 -2
- data/ext/ListViewExplorer/ListViewExplorer/targetver.h +0 -8
- data/ext/ListViewExplorer/ListViewExplorer.sln +0 -20
- data/ext/ListViewExplorer/ListViewExplorer.suo +0 -0
- data/ext/UiaDll/UiaDll.suo +0 -0
- data/ext/WindowsForms/bin/WindowsForms.exe +0 -0
- data/ext/WindowsForms/src/WindowsForms/WindowsForms.suo +0 -0
data/.gitignore
CHANGED
|
@@ -14,21 +14,22 @@ tmtags
|
|
|
14
14
|
*.swp
|
|
15
15
|
|
|
16
16
|
## PROJECT::GENERAL
|
|
17
|
-
coverage
|
|
18
|
-
rdoc
|
|
19
|
-
pkg
|
|
17
|
+
/coverage
|
|
18
|
+
/rdoc
|
|
19
|
+
/pkg
|
|
20
20
|
|
|
21
21
|
## PROJECT::SPECIFIC
|
|
22
|
-
|
|
22
|
+
/.idea/*
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
doc/
|
|
24
|
+
/.yardoc/
|
|
25
|
+
/doc/
|
|
26
26
|
|
|
27
27
|
## VisualStudio
|
|
28
28
|
Debug
|
|
29
29
|
Release
|
|
30
30
|
ipch
|
|
31
31
|
*.sdf
|
|
32
|
+
*.suo
|
|
32
33
|
*.user
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
*.opensdf
|
|
35
|
+
_ReSharper*/
|
data/Gemfile.lock
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rautomation (0.7.
|
|
4
|
+
rautomation (0.7.3)
|
|
5
5
|
ffi
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: http://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
diff-lcs (1.1.3)
|
|
11
|
-
ffi (1.
|
|
11
|
+
ffi (1.1.5-x86-mingw32)
|
|
12
12
|
rake (0.9.2.2)
|
|
13
13
|
rspec (2.8.0)
|
|
14
14
|
rspec-core (~> 2.8.0)
|
data/History.rdoc
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
== 0.8.0 / 2012-12-26
|
|
2
|
+
|
|
3
|
+
=== MsUia adapter
|
|
4
|
+
|
|
5
|
+
* Add Control#collapse for collapsing values in collapsable items.
|
|
6
|
+
* Add Control#expand for expanding values in expandable items.
|
|
7
|
+
* Add Row#cell(s).
|
|
8
|
+
* Add Table#cell(s).
|
|
9
|
+
* Add Table#row(s).
|
|
10
|
+
* Add Window#menu for selecting menu items.
|
|
11
|
+
* Fire change events when SelectList selections have been changed.
|
|
12
|
+
* Window#child instantiates MsUia adapter Window.
|
|
13
|
+
|
|
1
14
|
== 0.7.3 / 2012-10-31
|
|
2
15
|
|
|
3
16
|
=== Win32 adapter
|
data/README.rdoc
CHANGED
|
@@ -96,8 +96,9 @@ In case of any problems, feel free to contact me.
|
|
|
96
96
|
|
|
97
97
|
== Contributors
|
|
98
98
|
|
|
99
|
-
*
|
|
100
|
-
* Eric Kessler -
|
|
99
|
+
* Levi Wilson - https://github.com/leviwilson
|
|
100
|
+
* Eric Kessler - https://github.com/enkessler
|
|
101
|
+
* Stephan Schwab - https://github.com/snscaimito
|
|
101
102
|
|
|
102
103
|
== Note on Patches/Pull Requests
|
|
103
104
|
|
data/Rakefile
CHANGED
|
@@ -3,31 +3,51 @@ require 'bundler'
|
|
|
3
3
|
|
|
4
4
|
Bundler::GemHelper.install_tasks
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
namespace :build do
|
|
7
|
+
build_tasks = [
|
|
8
|
+
{:name => :uia_dll, :path => "UiaDll"},
|
|
9
|
+
{:name => :i_accessible_dll, :path => "IAccessibleDLL"},
|
|
10
|
+
{:name => :windows_forms, :path => "WindowsForms"}
|
|
11
|
+
]
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
build_tasks.each do |build_task|
|
|
14
|
+
desc "Build #{build_task[:path]}"
|
|
15
|
+
task build_task[:name] do
|
|
16
|
+
sh "msbuild /property:Configuration=Release ext\\#{build_task[:path]}\\#{build_task[:path]}.sln"
|
|
17
|
+
end
|
|
14
18
|
end
|
|
15
19
|
|
|
20
|
+
desc "Build all external dependencies"
|
|
21
|
+
task :all => build_tasks.map { |t| "build:#{t[:name]}"}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
task :build => "build:all"
|
|
25
|
+
|
|
26
|
+
namespace :spec do
|
|
16
27
|
adapters = %w[win_32 autoit ms_uia]
|
|
28
|
+
|
|
17
29
|
adapters.each do |adapter|
|
|
18
|
-
desc "Run
|
|
30
|
+
desc "Run RSpec code examples against #{adapter} adapter"
|
|
19
31
|
task adapter do
|
|
20
32
|
ENV["RAUTOMATION_ADAPTER"] = adapter
|
|
21
33
|
puts "Running specs for adapter: #{adapter}"
|
|
22
|
-
task = Rake::Task["spec
|
|
34
|
+
task = Rake::Task["spec"]
|
|
23
35
|
task.reenable
|
|
24
36
|
task.invoke
|
|
25
37
|
end
|
|
26
38
|
end
|
|
27
39
|
|
|
28
|
-
desc "Run
|
|
40
|
+
desc "Run RSpec code examples against all adapters"
|
|
29
41
|
task :all => adapters.map {|a| "spec:#{a}"}
|
|
30
42
|
end
|
|
31
43
|
|
|
44
|
+
require 'rspec/core/rake_task'
|
|
45
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
46
|
+
task :spec => :build
|
|
47
|
+
|
|
48
|
+
RSpec::Core::RakeTask.new(:rcov) { |spec| spec.rcov = true }
|
|
49
|
+
|
|
32
50
|
require 'yard'
|
|
33
51
|
YARD::Rake::YardocTask.new
|
|
52
|
+
|
|
53
|
+
task :default => "spec:all"
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.8.0
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#include "stdafx.h"
|
|
2
|
+
|
|
3
|
+
using namespace System;
|
|
4
|
+
using namespace System::Reflection;
|
|
5
|
+
using namespace System::Runtime::CompilerServices;
|
|
6
|
+
using namespace System::Runtime::InteropServices;
|
|
7
|
+
using namespace System::Security::Permissions;
|
|
8
|
+
|
|
9
|
+
//
|
|
10
|
+
// General Information about an assembly is controlled through the following
|
|
11
|
+
// set of attributes. Change these attribute values to modify the information
|
|
12
|
+
// associated with an assembly.
|
|
13
|
+
//
|
|
14
|
+
[assembly:AssemblyTitleAttribute("UiaDll")];
|
|
15
|
+
[assembly:AssemblyDescriptionAttribute("")];
|
|
16
|
+
[assembly:AssemblyConfigurationAttribute("")];
|
|
17
|
+
[assembly:AssemblyCompanyAttribute("")];
|
|
18
|
+
[assembly:AssemblyProductAttribute("UiaDll")];
|
|
19
|
+
[assembly:AssemblyCopyrightAttribute("Copyright (c) 2012")];
|
|
20
|
+
[assembly:AssemblyTrademarkAttribute("")];
|
|
21
|
+
[assembly:AssemblyCultureAttribute("")];
|
|
22
|
+
|
|
23
|
+
//
|
|
24
|
+
// Version information for an assembly consists of the following four values:
|
|
25
|
+
//
|
|
26
|
+
// Major Version
|
|
27
|
+
// Minor Version
|
|
28
|
+
// Build Number
|
|
29
|
+
// Revision
|
|
30
|
+
//
|
|
31
|
+
// You can specify all the value or you can default the Revision and Build Numbers
|
|
32
|
+
// by using the '*' as shown below:
|
|
33
|
+
|
|
34
|
+
[assembly:AssemblyVersionAttribute("1.0.*")];
|
|
35
|
+
|
|
36
|
+
[assembly:ComVisible(false)];
|
|
37
|
+
|
|
38
|
+
[assembly:CLSCompliantAttribute(true)];
|
|
39
|
+
|
|
40
|
+
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#include "StdAfx.h"
|
|
2
|
+
#include "AutomatedComboBox.h"
|
|
3
|
+
|
|
4
|
+
AutomatedComboBox::AutomatedComboBox(const HWND windowHandle)
|
|
5
|
+
{
|
|
6
|
+
_comboControl = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
bool AutomatedComboBox::SelectByIndex(const int whichItem)
|
|
10
|
+
{
|
|
11
|
+
try {
|
|
12
|
+
auto selectionItems = _comboControl->FindAll(System::Windows::Automation::TreeScope::Subtree, SelectionCondition);
|
|
13
|
+
Select(selectionItems[whichItem]);
|
|
14
|
+
return true;
|
|
15
|
+
} catch(Exception^ e) {
|
|
16
|
+
Console::WriteLine(e->ToString());
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
bool AutomatedComboBox::SelectByValue(const char* whichItem)
|
|
22
|
+
{
|
|
23
|
+
try {
|
|
24
|
+
auto nameCondition = gcnew PropertyCondition(AutomationElement::NameProperty, gcnew String(whichItem));
|
|
25
|
+
auto selectionAndNameCondition = gcnew AndCondition(SelectionCondition, nameCondition);
|
|
26
|
+
|
|
27
|
+
Select(_comboControl->FindFirst(System::Windows::Automation::TreeScope::Subtree, selectionAndNameCondition));
|
|
28
|
+
return true;
|
|
29
|
+
} catch(Exception^ e) {
|
|
30
|
+
Console::WriteLine(e->ToString());
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
bool AutomatedComboBox::GetValueByIndex(const int whichItem, char* comboValue, const int comboValueSize)
|
|
36
|
+
{
|
|
37
|
+
try {
|
|
38
|
+
auto selectionItem = SelectionItems[whichItem];
|
|
39
|
+
auto nameProperty = dynamic_cast<String^>(selectionItem->GetCurrentPropertyValue(AutomationElement::NameProperty));
|
|
40
|
+
|
|
41
|
+
StringHelper::CopyToUnmanagedString(nameProperty, comboValue, comboValueSize);
|
|
42
|
+
return true;
|
|
43
|
+
} catch(Exception^ e) {
|
|
44
|
+
Console::WriteLine(e->ToString());
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
int AutomatedComboBox::SelectedIndex::get() {
|
|
50
|
+
int selectedIndex = 0;
|
|
51
|
+
for each(AutomationElement^ selectionItem in SelectionItems) {
|
|
52
|
+
auto selectionPattern = dynamic_cast<SelectionItemPattern^>(selectionItem->GetCurrentPattern(SelectionItemPattern::Pattern));
|
|
53
|
+
if( selectionPattern->Current.IsSelected ) {
|
|
54
|
+
return selectedIndex;
|
|
55
|
+
}
|
|
56
|
+
++selectedIndex;
|
|
57
|
+
}
|
|
58
|
+
return -1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
void AutomatedComboBox::Select(AutomationElement^ itemToSelect)
|
|
63
|
+
{
|
|
64
|
+
auto selectionPattern = dynamic_cast<SelectionItemPattern^>(itemToSelect->GetCurrentPattern(SelectionItemPattern::Pattern));
|
|
65
|
+
selectionPattern->Select();
|
|
66
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
using namespace System::Windows::Automation;
|
|
3
|
+
|
|
4
|
+
public ref class AutomatedComboBox
|
|
5
|
+
{
|
|
6
|
+
public:
|
|
7
|
+
AutomatedComboBox(const HWND windowHandle);
|
|
8
|
+
bool SelectByIndex(const int whichItem);
|
|
9
|
+
bool SelectByValue(const char* whichItem);
|
|
10
|
+
bool GetValueByIndex(const int whichItem, char* comboValue, const int comboValueSize);
|
|
11
|
+
|
|
12
|
+
property int Count {
|
|
13
|
+
int get() { return SelectionItems->Count; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
property int SelectedIndex {
|
|
17
|
+
int get();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private:
|
|
21
|
+
AutomationElement^ _comboControl;
|
|
22
|
+
void Select(AutomationElement^ itemToSelect);
|
|
23
|
+
|
|
24
|
+
property AutomationElementCollection^ SelectionItems {
|
|
25
|
+
AutomationElementCollection^ get() { return _comboControl->FindAll(System::Windows::Automation::TreeScope::Subtree, SelectionCondition); }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
property PropertyCondition^ SelectionCondition {
|
|
29
|
+
PropertyCondition^ get() { return gcnew PropertyCondition(AutomationElement::IsSelectionItemPatternAvailableProperty, true); }
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#include "StdAfx.h"
|
|
2
|
+
#include "AutomatedTable.h"
|
|
3
|
+
|
|
4
|
+
AutomatedTable::AutomatedTable(const HWND windowHandle)
|
|
5
|
+
{
|
|
6
|
+
_tableControl = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
int AutomatedTable::RowCount::get()
|
|
10
|
+
{
|
|
11
|
+
auto tablePattern = dynamic_cast<TablePattern^>(_tableControl->GetCurrentPattern(TablePattern::Pattern));
|
|
12
|
+
return tablePattern->Current.RowCount;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
bool AutomatedTable::Exists(const char* whichItem)
|
|
16
|
+
{
|
|
17
|
+
return Exists(gcnew PropertyCondition(AutomationElement::NameProperty, gcnew String(whichItem)));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
bool AutomatedTable::Exists(const int whichItemIndex, const int whichColumnIndex)
|
|
21
|
+
{
|
|
22
|
+
return nullptr != DataItemAt(whichItemIndex, whichColumnIndex);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
String^ AutomatedTable::ValueAt(const int whichItemIndex, const int whichItemColumn)
|
|
26
|
+
{
|
|
27
|
+
return DataItemAt(whichItemIndex, whichItemColumn)->Current.Name;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
AutomationElement^ AutomatedTable::DataItemAt(const int whichItemIndex, const int whichItemColumn)
|
|
31
|
+
{
|
|
32
|
+
auto dataItemProperty = gcnew PropertyCondition(AutomationElement::IsTableItemPatternAvailableProperty, true);
|
|
33
|
+
auto indexProperty = gcnew PropertyCondition(TableItemPattern::RowProperty, whichItemIndex);
|
|
34
|
+
auto columnProperty = gcnew PropertyCondition(TableItemPattern::ColumnProperty, whichItemColumn);
|
|
35
|
+
return _tableControl->FindFirst(System::Windows::Automation::TreeScope::Subtree, gcnew AndCondition(dataItemProperty, indexProperty, columnProperty));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
bool AutomatedTable::Exists(Condition^ condition)
|
|
39
|
+
{
|
|
40
|
+
auto dataItemProperty = gcnew PropertyCondition(AutomationElement::IsTableItemPatternAvailableProperty, true);
|
|
41
|
+
return _tableControl->FindAll(System::Windows::Automation::TreeScope::Subtree, gcnew AndCondition(dataItemProperty, condition))->Count > 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void AutomatedTable::Select(const int dataItemIndex)
|
|
45
|
+
{
|
|
46
|
+
auto dataItemProperty = gcnew PropertyCondition(AutomationElement::ControlTypeProperty, ControlType::DataItem);
|
|
47
|
+
auto dataItem = _tableControl->FindAll(System::Windows::Automation::TreeScope::Subtree, dataItemProperty)[dataItemIndex];
|
|
48
|
+
auto selectionItemPattern = dynamic_cast<SelectionItemPattern^>(dataItem->GetCurrentPattern(SelectionItemPattern::Pattern));
|
|
49
|
+
selectionItemPattern->Select();
|
|
50
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
using namespace System::Windows::Automation;
|
|
3
|
+
|
|
4
|
+
ref class AutomatedTable
|
|
5
|
+
{
|
|
6
|
+
public:
|
|
7
|
+
AutomatedTable(const HWND windowHandle);
|
|
8
|
+
bool Exists(const char* whichItem);
|
|
9
|
+
bool Exists(const int whichItemIndex, const int whichColumnIndex);
|
|
10
|
+
String^ ValueAt(const int whichItemIndex, const int whichColumnIndex);
|
|
11
|
+
void Select(const int dataItemIndex);
|
|
12
|
+
|
|
13
|
+
property int RowCount {
|
|
14
|
+
int get();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private:
|
|
18
|
+
AutomationElement^ _tableControl;
|
|
19
|
+
bool Exists(Condition^ condition);
|
|
20
|
+
AutomationElement^ DataItemAt(const int whichItemIndex, const int whichItemRow);
|
|
21
|
+
};
|
|
22
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#include "StdAfx.h"
|
|
2
|
+
#include "AutomationClicker.h"
|
|
3
|
+
|
|
4
|
+
AutomationClicker::AutomationClicker(const HWND windowHandle) {
|
|
5
|
+
_automationElement = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
void AutomationClicker::Click() {
|
|
9
|
+
if( CanInvoke() ) {
|
|
10
|
+
return Invoke();
|
|
11
|
+
} else if( CanToggle() ) {
|
|
12
|
+
return Toggle();
|
|
13
|
+
} else if( CanSelect() ) {
|
|
14
|
+
return Select();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
throw gcnew Exception(gcnew String("AutomationElement did not support the InvokePattern, TogglePattern or the SelectionItemPattern"));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void AutomationClicker::MouseClick() {
|
|
21
|
+
_automationElement->SetFocus();
|
|
22
|
+
auto clickablePoint = _automationElement->GetClickablePoint();
|
|
23
|
+
Cursor::Position = Point((int)clickablePoint.X, (int)clickablePoint.Y);
|
|
24
|
+
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
|
|
25
|
+
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
bool AutomationClicker::CanInvoke() {
|
|
29
|
+
return (bool)(_automationElement->GetCurrentPropertyValue(AutomationElement::IsInvokePatternAvailableProperty));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void AutomationClicker::Invoke() {
|
|
33
|
+
dynamic_cast<InvokePattern^>(_automationElement->GetCurrentPattern(InvokePattern::Pattern))->Invoke();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
bool AutomationClicker::CanToggle() {
|
|
37
|
+
return (bool)(_automationElement->GetCurrentPropertyValue(AutomationElement::IsTogglePatternAvailableProperty));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void AutomationClicker::Toggle() {
|
|
41
|
+
dynamic_cast<TogglePattern^>(_automationElement->GetCurrentPattern(TogglePattern::Pattern))->Toggle();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
bool AutomationClicker::CanSelect() {
|
|
45
|
+
return (bool)(_automationElement->GetCurrentPropertyValue(AutomationElement::IsSelectionItemPatternAvailableProperty));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void AutomationClicker::Select() {
|
|
49
|
+
dynamic_cast<SelectionItemPattern^>(_automationElement->GetCurrentPattern(SelectionItemPattern::Pattern))->Select();
|
|
50
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
using namespace System::Windows::Automation;
|
|
3
|
+
using namespace System::Windows::Forms;
|
|
4
|
+
using namespace System::Drawing;
|
|
5
|
+
|
|
6
|
+
ref class AutomationClicker
|
|
7
|
+
{
|
|
8
|
+
public:
|
|
9
|
+
AutomationClicker(const HWND windowHandle);
|
|
10
|
+
void Click();
|
|
11
|
+
void MouseClick();
|
|
12
|
+
|
|
13
|
+
private:
|
|
14
|
+
AutomationElement^ _automationElement;
|
|
15
|
+
|
|
16
|
+
bool CanInvoke();
|
|
17
|
+
void Invoke();
|
|
18
|
+
|
|
19
|
+
bool CanToggle();
|
|
20
|
+
void Toggle();
|
|
21
|
+
|
|
22
|
+
bool CanSelect();
|
|
23
|
+
void Select();
|
|
24
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#include "StdAfx.h"
|
|
2
|
+
#include "ExpandCollapseHelper.h"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
void ExpandCollapseHelper::ExpandByValue(const HWND windowHandle, const char* whichItem)
|
|
6
|
+
{
|
|
7
|
+
Expand(ExpandableItem(windowHandle, whichItem));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
void ExpandCollapseHelper::ExpandByIndex(const HWND windowHandle, const int whichItemIndex)
|
|
11
|
+
{
|
|
12
|
+
auto expandableItem = ExpandableItems(windowHandle)[whichItemIndex];
|
|
13
|
+
Expand(expandableItem);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
void ExpandCollapseHelper::CollapseByValue(const HWND windowHandle, const char* whichItem)
|
|
17
|
+
{
|
|
18
|
+
Collapse(ExpandableItem(windowHandle, whichItem));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void ExpandCollapseHelper::CollapseByIndex(const HWND windowHandle, const int whichItemIndex)
|
|
22
|
+
{
|
|
23
|
+
auto expandableItem = ExpandableItems(windowHandle)[whichItemIndex];
|
|
24
|
+
Collapse(expandableItem);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
AutomationElementCollection^ ExpandCollapseHelper::ExpandableItems(const HWND windowHandle)
|
|
28
|
+
{
|
|
29
|
+
auto automationElement = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
30
|
+
return automationElement->FindAll(System::Windows::Automation::TreeScope::Subtree, IsExpandable);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
AutomationElement^ ExpandCollapseHelper::ExpandableItem(const HWND windowHandle, const char* whichItem)
|
|
34
|
+
{
|
|
35
|
+
auto automationElement = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
36
|
+
auto andTheNameMatches = gcnew PropertyCondition(AutomationElement::NameProperty, gcnew String(whichItem));
|
|
37
|
+
return automationElement->FindFirst(System::Windows::Automation::TreeScope::Subtree, gcnew AndCondition(IsExpandable, andTheNameMatches));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void ExpandCollapseHelper::Expand(AutomationElement^ automationElement)
|
|
41
|
+
{
|
|
42
|
+
dynamic_cast<ExpandCollapsePattern^>(automationElement->GetCurrentPattern(ExpandCollapsePattern::Pattern))->Expand();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void ExpandCollapseHelper::Collapse(AutomationElement^ automationElement)
|
|
46
|
+
{
|
|
47
|
+
dynamic_cast<ExpandCollapsePattern^>(automationElement->GetCurrentPattern(ExpandCollapsePattern::Pattern))->Collapse();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
PropertyCondition^ ExpandCollapseHelper::IsExpandable::get()
|
|
51
|
+
{
|
|
52
|
+
return gcnew PropertyCondition(AutomationElement::IsExpandCollapsePatternAvailableProperty, true);
|
|
53
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
using namespace System::Windows::Automation;
|
|
3
|
+
|
|
4
|
+
ref class ExpandCollapseHelper
|
|
5
|
+
{
|
|
6
|
+
public:
|
|
7
|
+
void ExpandByValue(const HWND windowHandle, const char* whichItem);
|
|
8
|
+
void ExpandByIndex(const HWND windowHandle, const int whichItemIndex);
|
|
9
|
+
void CollapseByValue(const HWND windowHandle, const char* whichItem);
|
|
10
|
+
void CollapseByIndex(const HWND windowHandle, const int whichItemIndex);
|
|
11
|
+
|
|
12
|
+
private:
|
|
13
|
+
AutomationElementCollection^ ExpandableItems(const HWND windowHandle);
|
|
14
|
+
AutomationElement^ ExpandableItem(const HWND windowHandle, const char* whichItem);
|
|
15
|
+
void Expand(AutomationElement^ automationElement);
|
|
16
|
+
void Collapse(AutomationElement^ automationElement);
|
|
17
|
+
|
|
18
|
+
property PropertyCondition^ IsExpandable {
|
|
19
|
+
PropertyCondition^ get();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#include "StdAfx.h"
|
|
2
|
+
#include "MenuItemSelector.h"
|
|
3
|
+
|
|
4
|
+
using namespace std;
|
|
5
|
+
|
|
6
|
+
void MenuItemSelector::SelectMenuPath(const HWND windowHandle, list<const char*>& menuItems)
|
|
7
|
+
{
|
|
8
|
+
auto automationElement = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
9
|
+
auto foundMenuItem = FindMenuItem(automationElement, menuItems);
|
|
10
|
+
auto invokePattern = dynamic_cast<InvokePattern^>(foundMenuItem->GetCurrentPattern(InvokePattern::Pattern));
|
|
11
|
+
invokePattern->Invoke();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
BOOL MenuItemSelector::MenuItemExists(const HWND windowHandle, list<const char*>& menuItems)
|
|
15
|
+
{
|
|
16
|
+
try {
|
|
17
|
+
auto automationElement = AutomationElement::FromHandle(IntPtr(windowHandle));
|
|
18
|
+
return FindMenuItem(automationElement, menuItems) != nullptr;
|
|
19
|
+
} catch(Exception^ e) {
|
|
20
|
+
return FALSE;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
AutomationElement^ MenuItemSelector::FindMenuItem(AutomationElement^ rootElement, std::list<const char*>& menuItems)
|
|
25
|
+
{
|
|
26
|
+
auto foundMenuItem = rootElement;
|
|
27
|
+
|
|
28
|
+
for(list<const char*>::iterator menuItem = menuItems.begin(); menuItem != menuItems.end(); ++menuItem) {
|
|
29
|
+
foundMenuItem = GetNextMenuItem(foundMenuItem, gcnew String(*menuItem));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return foundMenuItem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
PropertyCondition^ MenuItemSelector::NameConditionFor(String^ name)
|
|
36
|
+
{
|
|
37
|
+
return gcnew PropertyCondition(AutomationElement::NameProperty, name);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
AutomationElement^ MenuItemSelector::GetNextMenuItem(AutomationElement^ foundMenuItem, String^ nextMenu)
|
|
41
|
+
{
|
|
42
|
+
TryToExpand(AsExpandCollapse(foundMenuItem));
|
|
43
|
+
auto nextMenuItem = foundMenuItem->FindFirst(System::Windows::Automation::TreeScope::Subtree,
|
|
44
|
+
gcnew AndCondition(MenuItemControlType, NameConditionFor(nextMenu)));
|
|
45
|
+
if( nullptr == nextMenuItem ) {
|
|
46
|
+
throw gcnew Exception(String::Format("MenuItem with the text \"{0}\" does not exist", nextMenu));
|
|
47
|
+
}
|
|
48
|
+
return nextMenuItem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ExpandCollapsePattern^ MenuItemSelector::AsExpandCollapse(AutomationElement^ foundMenuItem)
|
|
52
|
+
{
|
|
53
|
+
try
|
|
54
|
+
{
|
|
55
|
+
return dynamic_cast<ExpandCollapsePattern^>(foundMenuItem->GetCurrentPattern(ExpandCollapsePattern::Pattern));
|
|
56
|
+
}
|
|
57
|
+
catch(Exception^ e)
|
|
58
|
+
{
|
|
59
|
+
return nullptr;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void MenuItemSelector::TryToExpand(ExpandCollapsePattern^ expandCollapsePattern)
|
|
64
|
+
{
|
|
65
|
+
if (nullptr == expandCollapsePattern) return;
|
|
66
|
+
|
|
67
|
+
try
|
|
68
|
+
{
|
|
69
|
+
expandCollapsePattern->Expand();
|
|
70
|
+
}
|
|
71
|
+
catch(Exception^ e)
|
|
72
|
+
{
|
|
73
|
+
expandCollapsePattern->Expand();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
using namespace System::Windows::Automation;
|
|
3
|
+
|
|
4
|
+
public ref class MenuItemSelector
|
|
5
|
+
{
|
|
6
|
+
public:
|
|
7
|
+
void SelectMenuPath(const HWND windowHandle, std::list<const char*>& menuItems);
|
|
8
|
+
BOOL MenuItemExists(const HWND windowHandle, std::list<const char*>& menuItems);
|
|
9
|
+
|
|
10
|
+
private:
|
|
11
|
+
AutomationElement^ FindMenuItem(AutomationElement^ rootElement, std::list<const char*>& menuItems);
|
|
12
|
+
PropertyCondition^ NameConditionFor(String^ name);
|
|
13
|
+
AutomationElement^ GetNextMenuItem(AutomationElement^ foundMenuItem, String^ nextMenu);
|
|
14
|
+
ExpandCollapsePattern^ AsExpandCollapse(AutomationElement^ foundMenuItem);
|
|
15
|
+
void TryToExpand(ExpandCollapsePattern^ expandCollapsePattern);
|
|
16
|
+
|
|
17
|
+
property PropertyCondition^ MenuItemControlType {
|
|
18
|
+
private:
|
|
19
|
+
PropertyCondition^ get() { return gcnew PropertyCondition(AutomationElement::ControlTypeProperty, ControlType::MenuItem); }
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
DYNAMIC LINK LIBRARY : UiaDll Project Overview
|
|
3
3
|
========================================================================
|
|
4
4
|
|
|
5
|
-
AppWizard has created this UiaDll DLL for you.
|
|
5
|
+
AppWizard has created this UiaDll DLL for you.
|
|
6
6
|
|
|
7
7
|
This file contains a summary of what you will find in each of the files that
|
|
8
8
|
make up your UiaDll application.
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
UiaDll.vcxproj
|
|
12
|
-
This is the main project file for VC++ projects generated using an Application Wizard.
|
|
13
|
-
It contains information about the version of Visual C++ that generated the file, and
|
|
11
|
+
This is the main project file for VC++ projects generated using an Application Wizard.
|
|
12
|
+
It contains information about the version of Visual C++ that generated the file, and
|
|
14
13
|
information about the platforms, configurations, and project features selected with the
|
|
15
14
|
Application Wizard.
|
|
16
15
|
|
|
@@ -24,25 +23,16 @@ UiaDll.vcxproj.filters
|
|
|
24
23
|
UiaDll.cpp
|
|
25
24
|
This is the main DLL source file.
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
to be a project dependency of some other project, you will either need to
|
|
30
|
-
add code to export some symbols from the DLL so that an export library
|
|
31
|
-
will be produced, or you can set the Ignore Input Library property to Yes
|
|
32
|
-
on the General propert page of the Linker folder in the project's Property
|
|
33
|
-
Pages dialog box.
|
|
34
|
-
|
|
35
|
-
/////////////////////////////////////////////////////////////////////////////
|
|
36
|
-
Other standard files:
|
|
26
|
+
UiaDll.h
|
|
27
|
+
This file contains a class declaration.
|
|
37
28
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
named UiaDll.pch and a precompiled types file named StdAfx.obj.
|
|
29
|
+
AssemblyInfo.cpp
|
|
30
|
+
Contains custom attributes for modifying assembly metadata.
|
|
41
31
|
|
|
42
32
|
/////////////////////////////////////////////////////////////////////////////
|
|
43
33
|
Other notes:
|
|
44
34
|
|
|
45
|
-
AppWizard uses "TODO:"
|
|
35
|
+
AppWizard uses "TODO:" to indicate parts of the source code you
|
|
46
36
|
should add to or customize.
|
|
47
37
|
|
|
48
38
|
/////////////////////////////////////////////////////////////////////////////
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#include "StdAfx.h"
|
|
2
|
+
#include "StringHelper.h"
|
|
3
|
+
|
|
4
|
+
void StringHelper::CopyToUnmanagedString(String^ source, char* destination, const int destinationSize)
|
|
5
|
+
{
|
|
6
|
+
auto unmanagedString = Marshal::StringToHGlobalAnsi(source);
|
|
7
|
+
strncpy(destination, (const char*)(void*)unmanagedString, destinationSize - 1);
|
|
8
|
+
Marshal::FreeHGlobal(unmanagedString);
|
|
9
|
+
}
|