rautomation 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|