Update native bridge to UI Automation for speed and reliability
Native UI Automation bridge redesigned for speed and reliability. The bridge library has been renamed to UiaBridge. Native components use VS 2010 C++ and .Net 4.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="src" path="native/WpfBridge/bin"/>
|
<classpathentry kind="src" path="native/uiabridge/bin"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||||
<classpathentry kind="lib" path="lib/jna-3.4.0.jar"/>
|
<classpathentry kind="lib" path="lib/jna-3.4.0.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/platform-3.4.0.jar"/>
|
<classpathentry kind="lib" path="lib/platform-3.4.0.jar"/>
|
||||||
|
|||||||
12
build.xml
12
build.xml
@@ -58,7 +58,7 @@
|
|||||||
<fileset dir="${src}"> <!-- includes images -->
|
<fileset dir="${src}"> <!-- includes images -->
|
||||||
<include name="**/*.png" />
|
<include name="**/*.png" />
|
||||||
</fileset>
|
</fileset>
|
||||||
<fileset dir="native/WpfBridge/bin"> <!-- includes native jni dlls -->
|
<fileset dir="native/uiabridge/bin"> <!-- includes native jni dlls -->
|
||||||
<include name="**/*.dll" />
|
<include name="**/*.dll" />
|
||||||
</fileset>
|
</fileset>
|
||||||
<manifest>
|
<manifest>
|
||||||
@@ -69,7 +69,13 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="run" depends="dist" description="runs our generated jar file">
|
<target name="run" depends="dist" description="runs our generated jar file">
|
||||||
<java jar="dist/${jarname}" fork="true"/>
|
<java jar="${dist}/${jarname}" fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="jni" depends="dist" description="compile the source including jars from lib directory" >
|
||||||
|
<!-- makes a JNI header of the named class -->
|
||||||
|
<javah destdir="${build}" verbose="yes" classpath="${dist}/${jarname}">
|
||||||
|
<class name="org.synthuse.UiaBridge"/>
|
||||||
|
</javah>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -1,351 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014, Synthuse.org
|
|
||||||
* Released under the Apache Version 2.0 License.
|
|
||||||
*
|
|
||||||
* last modified by ejakubowski7@gmail.com
|
|
||||||
*/
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "WpfAutomation.h"
|
|
||||||
|
|
||||||
using namespace System;
|
|
||||||
using namespace System::Windows::Automation;
|
|
||||||
|
|
||||||
WpfAutomation::WpfAutomation(void)
|
|
||||||
{
|
|
||||||
this->frameworkId = WpfAutomation::DEFAULT_FRAMEWORK;
|
|
||||||
this->touchableOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WpfAutomation::setFrameworkId(System::String ^propertyValue)
|
|
||||||
{
|
|
||||||
this->frameworkId = propertyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WpfAutomation::setTouchableOnly(System::Boolean val)
|
|
||||||
{
|
|
||||||
this->touchableOnly = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::Windows::Automation::Condition ^ WpfAutomation::getSearchConditions()
|
|
||||||
{
|
|
||||||
array<System::Windows::Automation::Condition ^> ^cons = nullptr;
|
|
||||||
if (this->touchableOnly)
|
|
||||||
{
|
|
||||||
cons = gcnew array<System::Windows::Automation::Condition ^>(3);
|
|
||||||
cons[0] = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);//is WPF framework
|
|
||||||
cons[1] = gcnew PropertyCondition(AutomationElement::IsEnabledProperty, true);//is enabled
|
|
||||||
cons[2] = gcnew PropertyCondition(AutomationElement::IsOffscreenProperty, false);// is off screen
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cons = gcnew array<System::Windows::Automation::Condition ^>(1);
|
|
||||||
cons[0] = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);//is WPF framework
|
|
||||||
}
|
|
||||||
System::Windows::Automation::Condition ^result = gcnew System::Windows::Automation::AndCondition(cons);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::Int32> ^ WpfAutomation::convertRuntimeIdString(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
System::String ^delim = L"-";
|
|
||||||
array<System::String ^> ^idStrArray = runtimeIdValue->Split(delim->ToCharArray());
|
|
||||||
array<System::Int32> ^idArray = gcnew array<System::Int32>(idStrArray->Length);
|
|
||||||
for(System::Int32 i = 0 ; i < idStrArray->Length ; i++)
|
|
||||||
{
|
|
||||||
idArray[i] = System::Int32::Parse(idStrArray[i]);
|
|
||||||
}
|
|
||||||
return idArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
AutomationElement ^ WpfAutomation::findAutomationElementById(System::String ^runtimeIdValue, System::Boolean unfiltered)
|
|
||||||
{
|
|
||||||
if (runtimeIdValue == nullptr || runtimeIdValue->Equals(L""))
|
|
||||||
return AutomationElement::RootElement;
|
|
||||||
array<System::Int32> ^idArray = this->convertRuntimeIdString(runtimeIdValue);
|
|
||||||
if (unfiltered)
|
|
||||||
return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray));
|
|
||||||
//Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);
|
|
||||||
Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray);
|
|
||||||
Condition ^frameworkAndRuntimeId = gcnew AndCondition(getSearchConditions(), pcRunId);
|
|
||||||
return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndRuntimeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection)
|
|
||||||
{
|
|
||||||
array<System::String ^> ^idStrArray = gcnew array<System::String ^>(collection->Count);
|
|
||||||
System::Int32 count = 0;
|
|
||||||
for each(AutomationElement ^child in collection)
|
|
||||||
{
|
|
||||||
idStrArray[count] = getRuntimeIdFromElement(child);
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return idStrArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::String ^ WpfAutomation::getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element)
|
|
||||||
{
|
|
||||||
System::String ^result = L"";
|
|
||||||
System::Object ^currentVal = element->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
|
|
||||||
if (currentVal != nullptr)
|
|
||||||
{
|
|
||||||
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
|
|
||||||
for each(System::Int32 val in idArray)
|
|
||||||
{
|
|
||||||
result += System::Convert::ToString(val) + L"-";
|
|
||||||
}
|
|
||||||
result = result->TrimEnd('-');
|
|
||||||
//System::Console::WriteLine("id: {0}", result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Descendants will walk the full tree of windows, NOT just one level of children
|
|
||||||
System::Int32 WpfAutomation::countDescendantWindows()
|
|
||||||
{
|
|
||||||
//AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition);
|
|
||||||
AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Descendants, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return 0;
|
|
||||||
System::Int32 result = aec->Count;
|
|
||||||
//delete aec;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return 0;
|
|
||||||
System::Int32 result = aec->Count;
|
|
||||||
//delete aec;
|
|
||||||
//delete frameworkAndRuntimeId;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::Int32 WpfAutomation::countChildrenWindows()
|
|
||||||
{
|
|
||||||
//AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition);
|
|
||||||
AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Children, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return 0;
|
|
||||||
System::Int32 result = aec->Count;
|
|
||||||
//delete aec;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return 0;
|
|
||||||
System::Int32 result = aec->Count;
|
|
||||||
//delete aec;
|
|
||||||
//delete frameworkAndRuntimeId;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::enumChildrenWindowIds(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return getRuntimeIdsFromCollection(aec);
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return getRuntimeIdsFromCollection(aec);
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::Int32 processId)
|
|
||||||
{
|
|
||||||
Condition ^frameworkAndProcessId = gcnew AndCondition(
|
|
||||||
gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId),
|
|
||||||
gcnew PropertyCondition(AutomationElement::ProcessIdProperty, processId));
|
|
||||||
AutomationElement ^parent = AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndProcessId);
|
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
|
|
||||||
if (aec == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return getRuntimeIdsFromCollection(aec);
|
|
||||||
}
|
|
||||||
|
|
||||||
System::String ^ WpfAutomation::getRuntimeIdFromHandle(System::IntPtr windowHandle)
|
|
||||||
{
|
|
||||||
//AutomationElement test = AutomationElement.FromHandle(new System.IntPtr(123123));
|
|
||||||
AutomationElement ^target = AutomationElement::FromHandle(windowHandle);
|
|
||||||
if (target == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return getRuntimeIdFromElement(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::enumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
if (parent == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
|
|
||||||
|
|
||||||
//when wildcard is enabled it will pull all property names & values
|
|
||||||
System::Boolean wildcardEnabled = false;
|
|
||||||
if (properties->Equals(L"*"))
|
|
||||||
wildcardEnabled = true;
|
|
||||||
|
|
||||||
//create array for keeping order of properties
|
|
||||||
System::String ^delim = L",";
|
|
||||||
array<System::String ^> ^propSpltArray = properties->Split(delim->ToCharArray());
|
|
||||||
TreeWalker ^tw = TreeWalker::ControlViewWalker;
|
|
||||||
|
|
||||||
array<System::String ^> ^winInfoList = gcnew array<System::String ^>(aec->Count);
|
|
||||||
System::Int32 count = 0;
|
|
||||||
for each(AutomationElement ^child in aec) //loop through all descendants
|
|
||||||
{
|
|
||||||
array<AutomationProperty^> ^aps = child->GetSupportedProperties();
|
|
||||||
array<System::String ^> ^propValues = gcnew array<System::String ^>(propSpltArray->Length);//keep order
|
|
||||||
System::String ^wildcardProperties = L"";
|
|
||||||
if (wildcardEnabled) {
|
|
||||||
wildcardProperties += "ParentRuntimeIdProperty:" + getRuntimeIdFromElement(tw->GetParent(child)) + ",";
|
|
||||||
//propValues = gcnew array<System::String ^>(aps->Length +1 );//add one for parent property since it doesn't exist
|
|
||||||
}
|
|
||||||
for(int i=0 ; i < propValues->Length ; i++)
|
|
||||||
{
|
|
||||||
propValues[i] = L"";
|
|
||||||
if (propSpltArray[i]->Equals("ParentRuntimeIdProperty"))//custom property for getting parent
|
|
||||||
{
|
|
||||||
propValues[i] = getRuntimeIdFromElement(tw->GetParent(child));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for each(AutomationProperty ^ap in aps) //loop through all supported Properties for a child
|
|
||||||
{
|
|
||||||
System::String ^currentPropertyStr = L""; //current property values
|
|
||||||
//System::Console::WriteLine("property: {0}", ap->ProgrammaticName);
|
|
||||||
System::String ^shortPropName = L" null ";
|
|
||||||
if (ap->ProgrammaticName->Contains(L"."))
|
|
||||||
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
|
|
||||||
if (properties->Contains(shortPropName) || properties->Contains(ap->ProgrammaticName) || ap->ProgrammaticName->Equals(properties) || wildcardEnabled)
|
|
||||||
{
|
|
||||||
//System::Console::WriteLine("shortPropName: {0}", shortPropName);
|
|
||||||
System::Object ^currentVal = child->GetCurrentPropertyValue(ap);
|
|
||||||
if (currentVal == nullptr)
|
|
||||||
continue;
|
|
||||||
if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty"))
|
|
||||||
{
|
|
||||||
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
|
|
||||||
for each(System::Int32 val in idArray)
|
|
||||||
{
|
|
||||||
currentPropertyStr += System::Convert::ToString(val) + L"-";
|
|
||||||
}
|
|
||||||
currentPropertyStr = currentPropertyStr->TrimEnd('-');
|
|
||||||
//System::Console::WriteLine("id: {0}", result);
|
|
||||||
}
|
|
||||||
else//not runtimeId which is an Int32[]
|
|
||||||
{
|
|
||||||
currentPropertyStr = currentVal->ToString();
|
|
||||||
currentPropertyStr = currentPropertyStr->Replace(",",",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentPropertyStr->Equals(L"")) //if there isn't a value skip
|
|
||||||
continue;
|
|
||||||
if (wildcardEnabled) {
|
|
||||||
wildcardProperties += shortPropName + ":" +currentPropertyStr + ",";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//System::Console::WriteLine("currentPropertyStr: {0}", currentPropertyStr);
|
|
||||||
//find the correct order to return this property
|
|
||||||
for(int i=0 ; i < propSpltArray->Length ; i++)
|
|
||||||
{
|
|
||||||
if (propSpltArray[i]->Equals(shortPropName) || propSpltArray[i]->Equals(ap->ProgrammaticName))
|
|
||||||
propValues[i] = currentPropertyStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//output properties in the correct order
|
|
||||||
for(int i=0 ; i < propSpltArray->Length ; i++)
|
|
||||||
winInfoList[count] += propValues[i] + L",";
|
|
||||||
if (wildcardEnabled)
|
|
||||||
winInfoList[count] += wildcardProperties;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return winInfoList;
|
|
||||||
}
|
|
||||||
|
|
||||||
System::String ^ WpfAutomation::getRuntimeIdFromPoint(System::Int32 x, System::Int32 y)
|
|
||||||
{
|
|
||||||
AutomationElement ^target = AutomationElement::FromPoint(System::Windows::Point(x,y));
|
|
||||||
if (target == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return getRuntimeIdFromElement(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
System::String ^ WpfAutomation::getParentRuntimeId(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^target = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
if (target == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
TreeWalker ^tw = TreeWalker::ControlViewWalker;
|
|
||||||
AutomationElement ^parent = tw->GetParent(target);
|
|
||||||
return getRuntimeIdFromElement(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
if (parent == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
//System::Object ^currentVal = parent->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
|
|
||||||
array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
|
|
||||||
for each(AutomationProperty ^ap in aps)
|
|
||||||
{
|
|
||||||
//System::Console::WriteLine("property: {0}", ap->ProgrammaticName);
|
|
||||||
if (ap->ProgrammaticName->Contains(L"." + propertyName) || ap->ProgrammaticName->Equals(propertyName))
|
|
||||||
{
|
|
||||||
System::Object ^currentVal = parent->GetCurrentPropertyValue(ap);
|
|
||||||
return currentVal->ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::getProperties(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
if (parent == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
|
|
||||||
array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length);
|
|
||||||
System::Int32 count = 0;
|
|
||||||
for each(AutomationProperty ^ap in aps)
|
|
||||||
{
|
|
||||||
System::Object ^currentVal = parent->GetCurrentPropertyValue(ap);
|
|
||||||
if (currentVal == nullptr)
|
|
||||||
continue;
|
|
||||||
propStrArray[count] = ap->ProgrammaticName;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return propStrArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
array<System::String ^> ^ WpfAutomation::getPropertiesAndValues(System::String ^runtimeIdValue)
|
|
||||||
{
|
|
||||||
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
|
||||||
if (parent == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
|
|
||||||
array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length);
|
|
||||||
System::Int32 count = 0;
|
|
||||||
for each(AutomationProperty ^ap in aps)
|
|
||||||
{
|
|
||||||
System::Object ^currentVal = parent->GetCurrentPropertyValue(ap);
|
|
||||||
if (currentVal == nullptr)
|
|
||||||
continue;
|
|
||||||
propStrArray[count] = ap->ProgrammaticName + ":" + currentVal->ToString();
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return propStrArray;
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014, Synthuse.org
|
|
||||||
* Released under the Apache Version 2.0 License.
|
|
||||||
*
|
|
||||||
* last modified by ejakubowski7@gmail.com
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
public ref class WpfAutomation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WpfAutomation(void);
|
|
||||||
void setFrameworkId(System::String ^propertyValue); //default is WPF, but also accepts Silverlight, Win32
|
|
||||||
void setTouchableOnly(System::Boolean val); //default is true
|
|
||||||
|
|
||||||
//Descendants will walk the full tree of windows, NOT just one level of children
|
|
||||||
System::Int32 countDescendantWindows();
|
|
||||||
System::Int32 countDescendantWindows(System::String ^runtimeIdValue);
|
|
||||||
|
|
||||||
System::Int32 countChildrenWindows();
|
|
||||||
System::Int32 countChildrenWindows(System::String ^runtimeIdValue);
|
|
||||||
|
|
||||||
array<System::String ^> ^ enumChildrenWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop
|
|
||||||
array<System::String ^> ^ enumDescendantWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop
|
|
||||||
array<System::String ^> ^ enumDescendantWindowIds(System::Int32 processId);
|
|
||||||
//In all the above Enumerate methods will return a list of Runtime Ids for all related windows.
|
|
||||||
array<System::String ^> ^ enumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties);
|
|
||||||
|
|
||||||
System::String ^ getRuntimeIdFromHandle(System::IntPtr windowHandle);
|
|
||||||
System::String ^ getRuntimeIdFromPoint(System::Int32 x, System::Int32 y);
|
|
||||||
System::String ^ getParentRuntimeId(System::String ^runtimeIdValue);
|
|
||||||
System::String ^ getProperty(System::String ^propertyName, System::String ^runtimeIdValue);
|
|
||||||
array<System::String ^> ^ getProperties(System::String ^runtimeIdValue);
|
|
||||||
array<System::String ^> ^ getPropertiesAndValues(System::String ^runtimeIdValue);
|
|
||||||
private:
|
|
||||||
array<System::Int32> ^ convertRuntimeIdString(System::String ^runtimeIdValue);
|
|
||||||
System::Windows::Automation::AutomationElement ^ findAutomationElementById(System::String ^runtimeIdValue, System::Boolean unfiltered);
|
|
||||||
System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element);
|
|
||||||
array<System::String ^> ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection);
|
|
||||||
System::Windows::Automation::Condition ^ getSearchConditions();
|
|
||||||
|
|
||||||
static System::String ^DEFAULT_FRAMEWORK = L"WPF";
|
|
||||||
static System::Boolean ^DEFAULT_TOUCHABLE = true;
|
|
||||||
System::String ^frameworkId;
|
|
||||||
System::Boolean ^touchableOnly;
|
|
||||||
};
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,300 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014, Synthuse.org
|
|
||||||
* Released under the Apache Version 2.0 License.
|
|
||||||
*
|
|
||||||
* last modified by ejakubowski7@gmail.com
|
|
||||||
*/
|
|
||||||
#include "StdAfx.h"
|
|
||||||
#include "org_synthuse_WpfBridge.h"
|
|
||||||
#include "WpfAutomation.h"
|
|
||||||
#include "Global.h"
|
|
||||||
#include <msclr/marshal.h> //using namespace msclr::interop;
|
|
||||||
|
|
||||||
using namespace System;
|
|
||||||
using namespace System::Windows::Automation;
|
|
||||||
using namespace msclr::interop;
|
|
||||||
using namespace Globals;
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId(JNIEnv *env, jobject obj, jstring jpropertyValue)
|
|
||||||
{
|
|
||||||
const char *propertyValue = env->GetStringUTFChars(jpropertyValue, 0);//convert string
|
|
||||||
Global::WPF_AUTO->setFrameworkId(marshal_as<String ^>(propertyValue));
|
|
||||||
env->ReleaseStringUTFChars(jpropertyValue, propertyValue); //release string
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: setTouchableOnly
|
|
||||||
* Signature: (Z)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setTouchableOnly(JNIEnv *env, jobject obj, jboolean jval)
|
|
||||||
{
|
|
||||||
Global::WPF_AUTO->setTouchableOnly((bool)(jval == JNI_TRUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: CountDescendantWindows
|
|
||||||
* Signature: ()I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__(JNIEnv *env, jobject obj)
|
|
||||||
{
|
|
||||||
return Global::WPF_AUTO->countDescendantWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: CountDescendantWindows
|
|
||||||
* Signature: (Ljava/lang/String;)I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
jint result = Global::WPF_AUTO->countDescendantWindows(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: CountChildrenWindows
|
|
||||||
* Signature: ()I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__(JNIEnv *env, jobject obj)
|
|
||||||
{
|
|
||||||
return Global::WPF_AUTO->countChildrenWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: CountChildrenWindows
|
|
||||||
* Signature: (Ljava/lang/String;)I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
jint result = Global::WPF_AUTO->countChildrenWindows(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: EnumChildrenWindowIds
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumChildrenWindowIds(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
if (mchildrenIds == nullptr)
|
|
||||||
return NULL;
|
|
||||||
//create result object array to the same size as the managed children Ids string array
|
|
||||||
jclass stringClass = env->FindClass("java/lang/String");
|
|
||||||
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
//char **childrenIds = new char *[mchildrenIds->Length];
|
|
||||||
for(int i = 0 ; i < mchildrenIds->Length ; i++)
|
|
||||||
{
|
|
||||||
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
|
|
||||||
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
|
|
||||||
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
|
|
||||||
}
|
|
||||||
//delete[] childrenIds;
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: EnumDescendantWindowIds
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
if (mchildrenIds == nullptr)
|
|
||||||
return NULL;
|
|
||||||
//create result object array to the same size as the managed children Ids string array
|
|
||||||
jclass stringClass = env->FindClass("java/lang/String");
|
|
||||||
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
//char **childrenIds = new char *[mchildrenIds->Length];
|
|
||||||
for(int i = 0 ; i < mchildrenIds->Length ; i++)
|
|
||||||
{
|
|
||||||
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
|
|
||||||
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
|
|
||||||
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
|
|
||||||
}
|
|
||||||
//delete[] childrenIds;
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: EnumDescendantWindowIds
|
|
||||||
* Signature: (J)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J(JNIEnv *env, jobject obj, jlong jprocessId)
|
|
||||||
{
|
|
||||||
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds((System::Int32)jprocessId);
|
|
||||||
if (mchildrenIds == nullptr)
|
|
||||||
return NULL;
|
|
||||||
//create result object array to the same size as the managed children Ids string array
|
|
||||||
jclass stringClass = env->FindClass("java/lang/String");
|
|
||||||
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
for(int i = 0 ; i < mchildrenIds->Length ; i++)
|
|
||||||
{
|
|
||||||
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getRuntimeIdFromHandle
|
|
||||||
* Signature: (J)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle)
|
|
||||||
{
|
|
||||||
System::String ^mrunId = Global::WPF_AUTO->getRuntimeIdFromHandle(System::IntPtr(jwindowHandle));
|
|
||||||
if (mrunId == nullptr)
|
|
||||||
return NULL;
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mrunId));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: enumDescendantWindowInfo
|
|
||||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo(JNIEnv *env, jobject obj, jstring jruntimeIdValue, jstring jproperties)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
|
|
||||||
array<System::String ^> ^mwinInfo = Global::WPF_AUTO->enumDescendantWindowInfo(marshal_as<String ^>(runtimeIdValue), marshal_as<String ^>(properties));
|
|
||||||
if (mwinInfo == nullptr)
|
|
||||||
return NULL;
|
|
||||||
//create result object array to the same size as the managed window info string array
|
|
||||||
jclass stringClass = env->FindClass("java/lang/String");
|
|
||||||
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
for(int i = 0 ; i < mwinInfo->Length ; i++)
|
|
||||||
{
|
|
||||||
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mwinInfo[i])));
|
|
||||||
}
|
|
||||||
env->ReleaseStringUTFChars(jproperties, properties); //release string
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getRuntimeIdFromPoint
|
|
||||||
* Signature: (II)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromPoint(JNIEnv *env, jobject obj, jint x, jint y)
|
|
||||||
{
|
|
||||||
System::String ^mresult = Global::WPF_AUTO->getRuntimeIdFromPoint(x, y);
|
|
||||||
if (mresult == nullptr)
|
|
||||||
return NULL;
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getParentRuntimeId
|
|
||||||
* Signature: (Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getParentRuntimeId(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
System::String ^mresult = Global::WPF_AUTO->getParentRuntimeId(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
if (mresult == nullptr)
|
|
||||||
return NULL;
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: GetProperty
|
|
||||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getProperty(JNIEnv *env, jobject obj, jstring jpropertyName, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
const char *propertyName = env->GetStringUTFChars(jpropertyName, 0);//convert string
|
|
||||||
System::String ^mresult = Global::WPF_AUTO->getProperty(marshal_as<String ^>(propertyName), marshal_as<String ^>(runtimeIdValue));
|
|
||||||
if (mresult == nullptr)
|
|
||||||
return NULL;
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
|
|
||||||
env->ReleaseStringUTFChars(jpropertyName, propertyName); //release string
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: GetProperties
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getProperties(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
array<System::String ^> ^mprops = Global::WPF_AUTO->getProperties(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
if (mprops == nullptr)
|
|
||||||
return NULL;
|
|
||||||
//create result object array to the same size as the managed children Ids string array
|
|
||||||
jclass stringClass = env->FindClass("java/lang/String");
|
|
||||||
jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0);
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
for(int i = 0 ; i < mprops->Length ; i++)
|
|
||||||
{
|
|
||||||
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mprops[i])));
|
|
||||||
}
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: GetPropertiesAndValues
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getPropertiesAndValues(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
|
|
||||||
{
|
|
||||||
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
|
|
||||||
array<System::String ^> ^mprops = Global::WPF_AUTO->getPropertiesAndValues(marshal_as<String ^>(runtimeIdValue));
|
|
||||||
if (mprops == nullptr)
|
|
||||||
return NULL;
|
|
||||||
//create result object array to the same size as the managed children Ids string array
|
|
||||||
jclass stringClass = env->FindClass("java/lang/String");
|
|
||||||
jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0);
|
|
||||||
marshal_context context; //lets you marshal managed classes to unmanaged types
|
|
||||||
for(int i = 0 ; i < mprops->Length ; i++)
|
|
||||||
{
|
|
||||||
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mprops[i])));
|
|
||||||
}
|
|
||||||
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
|
||||||
#include <jni.h>
|
|
||||||
/* Header for class org_synthuse_WpfBridge */
|
|
||||||
|
|
||||||
#ifndef _Included_org_synthuse_WpfBridge
|
|
||||||
#define _Included_org_synthuse_WpfBridge
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: setFrameworkId
|
|
||||||
* Signature: (Ljava/lang/String;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: setTouchableOnly
|
|
||||||
* Signature: (Z)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setTouchableOnly
|
|
||||||
(JNIEnv *, jobject, jboolean);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: countDescendantWindows
|
|
||||||
* Signature: ()I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__
|
|
||||||
(JNIEnv *, jobject);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: countDescendantWindows
|
|
||||||
* Signature: (Ljava/lang/String;)I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__Ljava_lang_String_2
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: countChildrenWindows
|
|
||||||
* Signature: ()I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__
|
|
||||||
(JNIEnv *, jobject);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: countChildrenWindows
|
|
||||||
* Signature: (Ljava/lang/String;)I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__Ljava_lang_String_2
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: enumChildrenWindowIds
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: enumDescendantWindowIds
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__Ljava_lang_String_2
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: enumDescendantWindowIds
|
|
||||||
* Signature: (J)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J
|
|
||||||
(JNIEnv *, jobject, jlong);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: enumDescendantWindowInfo
|
|
||||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo
|
|
||||||
(JNIEnv *, jobject, jstring, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getRuntimeIdFromHandle
|
|
||||||
* Signature: (J)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromHandle
|
|
||||||
(JNIEnv *, jobject, jlong);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getRuntimeIdFromPoint
|
|
||||||
* Signature: (II)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromPoint
|
|
||||||
(JNIEnv *, jobject, jint, jint);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getParentRuntimeId
|
|
||||||
* Signature: (Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getParentRuntimeId
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getProperty
|
|
||||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getProperty
|
|
||||||
(JNIEnv *, jobject, jstring, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getProperties
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getProperties
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: org_synthuse_WpfBridge
|
|
||||||
* Method: getPropertiesAndValues
|
|
||||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getPropertiesAndValues
|
|
||||||
(JNIEnv *, jobject, jstring);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
36
native/uiabridge.sln
Normal file
36
native/uiabridge.sln
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uiabridge", "uiabridge\uiabridge.vcxproj", "{BAC1B079-7B87-4396-B17F-91A86DF1AE29}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uiabtest", "uiabtest\uiabtest.vcxproj", "{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|x64.Build.0 = Release|x64
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
BIN
native/uiabridge.suo
Normal file
BIN
native/uiabridge.suo
Normal file
Binary file not shown.
@@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014, Synthuse.org
|
|
||||||
* Released under the Apache Version 2.0 License.
|
|
||||||
*
|
|
||||||
* last modified by ejakubowski7@gmail.com
|
|
||||||
*/
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
using namespace System;
|
using namespace System;
|
||||||
@@ -17,12 +11,12 @@ using namespace System::Security::Permissions;
|
|||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
//
|
//
|
||||||
[assembly:AssemblyTitleAttribute("WpfBridge")];
|
[assembly:AssemblyTitleAttribute("uiabridge")];
|
||||||
[assembly:AssemblyDescriptionAttribute("")];
|
[assembly:AssemblyDescriptionAttribute("")];
|
||||||
[assembly:AssemblyConfigurationAttribute("")];
|
[assembly:AssemblyConfigurationAttribute("")];
|
||||||
[assembly:AssemblyCompanyAttribute("Synthuse")];
|
[assembly:AssemblyCompanyAttribute("na")];
|
||||||
[assembly:AssemblyProductAttribute("WpfBridge")];
|
[assembly:AssemblyProductAttribute("uiabridge")];
|
||||||
[assembly:AssemblyCopyrightAttribute("Copyright (c) Synthuse 2014")];
|
[assembly:AssemblyCopyrightAttribute("Copyright (c) na 2014")];
|
||||||
[assembly:AssemblyTrademarkAttribute("")];
|
[assembly:AssemblyTrademarkAttribute("")];
|
||||||
[assembly:AssemblyCultureAttribute("")];
|
[assembly:AssemblyCultureAttribute("")];
|
||||||
|
|
||||||
@@ -37,7 +31,7 @@ using namespace System::Security::Permissions;
|
|||||||
// You can specify all the value or you can default the Revision and Build Numbers
|
// You can specify all the value or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly:AssemblyVersionAttribute("1.1.*")];
|
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||||
|
|
||||||
[assembly:ComVisible(false)];
|
[assembly:ComVisible(false)];
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* last modified by ejakubowski7@gmail.com
|
* last modified by ejakubowski7@gmail.com
|
||||||
*/
|
*/
|
||||||
#include "StdAfx.h"
|
#include "stdafx.h"
|
||||||
#include "Global.h"
|
#include "Global.h"
|
||||||
#include "WpfAutomation.h"
|
#include "uiabridge.h"
|
||||||
|
using namespace uiabridge;
|
||||||
@@ -5,7 +5,8 @@
|
|||||||
* last modified by ejakubowski7@gmail.com
|
* last modified by ejakubowski7@gmail.com
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "WpfAutomation.h"
|
#include "uiabridge.h"
|
||||||
|
using namespace uiabridge;
|
||||||
namespace Globals
|
namespace Globals
|
||||||
{
|
{
|
||||||
using namespace System;
|
using namespace System;
|
||||||
@@ -13,7 +14,7 @@ namespace Globals
|
|||||||
public ref class Global
|
public ref class Global
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static WpfAutomation ^WPF_AUTO = gcnew WpfAutomation();
|
static AutomationBridge ^AUTO_BRIDGE = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
========================================================================
|
========================================================================
|
||||||
DYNAMIC LINK LIBRARY : WpfBridge Project Overview
|
DYNAMIC LINK LIBRARY : uiabridge Project Overview
|
||||||
========================================================================
|
========================================================================
|
||||||
|
|
||||||
Created By Edward Jakubowski ejakubowski7@gmail.com
|
Created By Edward Jakubowski ejakubowski7@gmail.com
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
This is a bridge for java to access .net 4 UI Automation libraries. This
|
This is a bridge for java to access .net 4 UI Automation libraries. This
|
||||||
library enables Synthuse to access and automation WPF and Silverlight apps.
|
library enables Synthuse to access and automate WinForms, WPF and Silverlight apps.
|
||||||
6
native/uiabridge/Stdafx.cpp
Normal file
6
native/uiabridge/Stdafx.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// stdafx.cpp : source file that includes just the standard includes
|
||||||
|
// uiabridge.pch will be the pre-compiled header
|
||||||
|
// stdafx.obj will contain the pre-compiled type information
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include <msclr/marshal.h>
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
157
native/uiabridge/org_synthuse_UiaBridge.cpp
Normal file
157
native/uiabridge/org_synthuse_UiaBridge.cpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski7@gmail.com
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include <msclr/marshal.h> //using namespace msclr::interop;
|
||||||
|
#include "org_synthuse_UiaBridge.h"
|
||||||
|
#include "uiabridge.h"
|
||||||
|
#include "Global.h"
|
||||||
|
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Windows::Automation;
|
||||||
|
using namespace msclr::interop;
|
||||||
|
using namespace Globals;
|
||||||
|
using namespace uiabridge;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: initialize
|
||||||
|
* Signature: (Ljava/lang/String;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_initialize(JNIEnv *env, jobject obj, jstring jproperties)
|
||||||
|
{
|
||||||
|
Global::AUTO_BRIDGE = gcnew AutomationBridge();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: shutdown
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_shutdown(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: addEnumFilter
|
||||||
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_org_synthuse_UiaBridge_addEnumFilter(JNIEnv *env, jobject obj, jstring jpropertyName, jstring jpropertyValue)
|
||||||
|
{
|
||||||
|
const char *propertyName = env->GetStringUTFChars(jpropertyValue, 0);//convert string
|
||||||
|
const char *propertyValue = env->GetStringUTFChars(jpropertyValue, 0);//convert string
|
||||||
|
return (jint)Global::AUTO_BRIDGE->addEnumFilter(marshal_as<String ^>(propertyName), marshal_as<String ^>(propertyValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: clearEnumFilters
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_clearEnumFilters(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
Global::AUTO_BRIDGE->clearEnumFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: enumWindowInfo
|
||||||
|
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jproperties)
|
||||||
|
{
|
||||||
|
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
|
||||||
|
array<System::String ^> ^mwinInfo = Global::AUTO_BRIDGE->enumWindowInfo(marshal_as<String ^>(properties));
|
||||||
|
if (mwinInfo == nullptr)
|
||||||
|
return NULL;
|
||||||
|
//create result object array to the same size as the managed children Ids string array
|
||||||
|
jclass stringClass = env->FindClass("java/lang/String");
|
||||||
|
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
|
||||||
|
marshal_context context; //lets you marshal managed classes to unmanaged types
|
||||||
|
//char **childrenIds = new char *[mchildrenIds->Length];
|
||||||
|
for(int i = 0 ; i < mwinInfo->Length ; i++)
|
||||||
|
{
|
||||||
|
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
|
||||||
|
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
|
||||||
|
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mwinInfo[i])));
|
||||||
|
}
|
||||||
|
//delete[] childrenIds;
|
||||||
|
env->ReleaseStringUTFChars(jproperties, properties); //release string
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: enumWindowInfo
|
||||||
|
* Signature: (ILjava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__ILjava_lang_String_2(JNIEnv *env, jobject obj, jint jwindowHandle, jstring jproperties)
|
||||||
|
{
|
||||||
|
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
|
||||||
|
array<System::String ^> ^mwinInfo = Global::AUTO_BRIDGE->enumWindowInfo(System::IntPtr(jwindowHandle), marshal_as<String ^>(properties));
|
||||||
|
if (mwinInfo == nullptr)
|
||||||
|
return NULL;
|
||||||
|
//create result object array to the same size as the managed children Ids string array
|
||||||
|
jclass stringClass = env->FindClass("java/lang/String");
|
||||||
|
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
|
||||||
|
marshal_context context; //lets you marshal managed classes to unmanaged types
|
||||||
|
//char **childrenIds = new char *[mchildrenIds->Length];
|
||||||
|
for(int i = 0 ; i < mwinInfo->Length ; i++)
|
||||||
|
{
|
||||||
|
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
|
||||||
|
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
|
||||||
|
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mwinInfo[i])));
|
||||||
|
}
|
||||||
|
//delete[] childrenIds;
|
||||||
|
env->ReleaseStringUTFChars(jproperties, properties); //release string
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: getWindowInfo
|
||||||
|
* Signature: (IILjava/lang/String;)Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__IILjava_lang_String_2(JNIEnv *env, jobject obj, jint jx, jint jy, jstring jproperties)
|
||||||
|
{
|
||||||
|
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
|
||||||
|
System::String ^mwinInfo = Global::AUTO_BRIDGE->getWindowInfo(jx, jy, marshal_as<String ^>(properties));
|
||||||
|
env->ReleaseStringUTFChars(jproperties, properties); //release string
|
||||||
|
marshal_context context;
|
||||||
|
return env->NewStringUTF(context.marshal_as<const char *>(mwinInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: getWindowInfo
|
||||||
|
* Signature: (ILjava/lang/String;)Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__ILjava_lang_String_2(JNIEnv *env, jobject obj, jint jwindowHandle, jstring jproperties)
|
||||||
|
{
|
||||||
|
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
|
||||||
|
System::String ^mwinInfo = Global::AUTO_BRIDGE->getWindowInfo(System::IntPtr(jwindowHandle), marshal_as<String ^>(properties));
|
||||||
|
env->ReleaseStringUTFChars(jproperties, properties); //release string
|
||||||
|
marshal_context context;
|
||||||
|
return env->NewStringUTF(context.marshal_as<const char *>(mwinInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: getWindowInfo
|
||||||
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__Ljava_lang_String_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdStr, jstring jproperties)
|
||||||
|
{
|
||||||
|
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
|
||||||
|
const char *runtimeIdStr = env->GetStringUTFChars(jruntimeIdStr, 0);//convert string
|
||||||
|
System::String ^mwinInfo = Global::AUTO_BRIDGE->getWindowInfo(marshal_as<String ^>(runtimeIdStr), marshal_as<String ^>(properties));
|
||||||
|
env->ReleaseStringUTFChars(jruntimeIdStr, runtimeIdStr); //release string
|
||||||
|
env->ReleaseStringUTFChars(jproperties, properties); //release string
|
||||||
|
marshal_context context;
|
||||||
|
return env->NewStringUTF(context.marshal_as<const char *>(mwinInfo));
|
||||||
|
}
|
||||||
85
native/uiabridge/org_synthuse_UiaBridge.h
Normal file
85
native/uiabridge/org_synthuse_UiaBridge.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
|
#include <jni.h>
|
||||||
|
/* Header for class org_synthuse_UiaBridge */
|
||||||
|
|
||||||
|
#ifndef _Included_org_synthuse_UiaBridge
|
||||||
|
#define _Included_org_synthuse_UiaBridge
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: initialize
|
||||||
|
* Signature: (Ljava/lang/String;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_initialize
|
||||||
|
(JNIEnv *, jobject, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: shutdown
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_shutdown
|
||||||
|
(JNIEnv *, jobject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: addEnumFilter
|
||||||
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_org_synthuse_UiaBridge_addEnumFilter
|
||||||
|
(JNIEnv *, jobject, jstring, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: clearEnumFilters
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_clearEnumFilters
|
||||||
|
(JNIEnv *, jobject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: enumWindowInfo
|
||||||
|
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__Ljava_lang_String_2
|
||||||
|
(JNIEnv *, jobject, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: enumWindowInfo
|
||||||
|
* Signature: (ILjava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__ILjava_lang_String_2
|
||||||
|
(JNIEnv *, jobject, jint, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: getWindowInfo
|
||||||
|
* Signature: (IILjava/lang/String;)Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__IILjava_lang_String_2
|
||||||
|
(JNIEnv *, jobject, jint, jint, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: getWindowInfo
|
||||||
|
* Signature: (ILjava/lang/String;)Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__ILjava_lang_String_2
|
||||||
|
(JNIEnv *, jobject, jint, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_synthuse_UiaBridge
|
||||||
|
* Method: getWindowInfo
|
||||||
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__Ljava_lang_String_2Ljava_lang_String_2
|
||||||
|
(JNIEnv *, jobject, jstring, jstring);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
422
native/uiabridge/uiabridge.cpp
Normal file
422
native/uiabridge/uiabridge.cpp
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski7@gmail.com
|
||||||
|
*/
|
||||||
|
// This is the main DLL file.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "uiabridge.h"
|
||||||
|
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Collections::Generic;
|
||||||
|
using namespace System::Windows::Automation;
|
||||||
|
using namespace uiabridge;
|
||||||
|
|
||||||
|
AutomationBridge::AutomationBridge()
|
||||||
|
{
|
||||||
|
enumFilters = gcnew Dictionary<System::String ^, System::String ^>();
|
||||||
|
cacheRequest = nullptr;
|
||||||
|
initializeCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
AutomationBridge::~AutomationBridge()
|
||||||
|
{
|
||||||
|
enumFilters->Clear();
|
||||||
|
if (cacheRequest != nullptr)
|
||||||
|
cacheRequest->Pop(); //disable UI Automation Cache
|
||||||
|
//Console::WriteLine("disposing of AutomationBridge");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutomationBridge::initializeCache()
|
||||||
|
{
|
||||||
|
cacheRequest = gcnew CacheRequest();
|
||||||
|
//cacheRequest->AutomationElementMode = AutomationElementMode::Full;
|
||||||
|
cacheRequest->TreeFilter = Automation::RawViewCondition;
|
||||||
|
cacheRequest->TreeScope = TreeScope::Element;// | TreeScope::Children;
|
||||||
|
/*
|
||||||
|
cacheRequest->Add(AutomationElement::RuntimeIdProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::ProcessIdProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::FrameworkIdProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::LocalizedControlTypeProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::ControlTypeProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::ClassNameProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::NameProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::BoundingRectangleProperty);
|
||||||
|
*/
|
||||||
|
System::String ^cachedPropStr = L"RuntimeIdProperty,ParentRuntimeIdProperty,NativeWindowHandleProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ControlTypeProperty,ClassNameProperty,NameProperty,BoundingRectangleProperty";
|
||||||
|
array<AutomationProperty^> ^rootProperties = AutomationElement::RootElement->GetSupportedProperties();
|
||||||
|
List<AutomationProperty^> ^cacheList = gcnew List<AutomationProperty^>();
|
||||||
|
if (cachedPropStr->Contains(L"NativeWindowHandleProperty")) //special property not in the root property list
|
||||||
|
{
|
||||||
|
cacheList->Add(AutomationElement::NativeWindowHandleProperty);
|
||||||
|
cacheRequest->Add(AutomationElement::NativeWindowHandleProperty);
|
||||||
|
}
|
||||||
|
for each(AutomationProperty ^ap in rootProperties) //loop through all supported Properties for a child
|
||||||
|
{
|
||||||
|
System::String ^currentPropertyStr = L""; //current property values
|
||||||
|
System::String ^shortPropName = L" null ";
|
||||||
|
if (ap->ProgrammaticName->Contains(L".")) //get short Property name
|
||||||
|
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
|
||||||
|
if (cachedPropStr->Contains(shortPropName) || cachedPropStr->Contains(ap->ProgrammaticName))
|
||||||
|
{
|
||||||
|
cacheList->Add(ap);// add property to cachedRootProperties
|
||||||
|
cacheRequest->Add(ap); // add property to cacheRequest
|
||||||
|
//Console::WriteLine("caching property {0}", ap->ProgrammaticName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cachedRootProperties = cacheList->ToArray();
|
||||||
|
cacheRequest->Push(); //enable UI Automation Cache
|
||||||
|
//cachedRootProperties = AutomationElement::RootElement->GetSupportedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AutomationBridge::addEnumFilter(System::String ^propertyName, System::String ^propertyValue)
|
||||||
|
{
|
||||||
|
enumFilters->Add(propertyName, propertyValue);
|
||||||
|
return enumFilters->Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutomationBridge::clearEnumFilters()
|
||||||
|
{
|
||||||
|
enumFilters->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean AutomationBridge::isElementFiltered(System::Windows::Automation::AutomationElement ^element)
|
||||||
|
{
|
||||||
|
return isElementFiltered(element, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean AutomationBridge::isElementFiltered(System::Windows::Automation::AutomationElement ^element, List<System::String ^> ^filterModifierList)
|
||||||
|
{
|
||||||
|
Boolean result = false;
|
||||||
|
int filterMatchCount = 0;
|
||||||
|
if (enumFilters->Count == 0)
|
||||||
|
return result;
|
||||||
|
array<AutomationProperty^> ^aps = cachedRootProperties;//element->GetSupportedProperties();
|
||||||
|
for each(AutomationProperty ^ap in aps) //loop through all supported Properties for a child
|
||||||
|
{
|
||||||
|
System::String ^currentPropertyStr = L""; //current property values
|
||||||
|
System::String ^shortPropName = L" null ";
|
||||||
|
if (ap->ProgrammaticName->Contains(L".")) //get short Property name
|
||||||
|
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
|
||||||
|
//System::Console::WriteLine("property: {0}", shortPropName);
|
||||||
|
for each(System::String ^key in enumFilters->Keys)
|
||||||
|
{
|
||||||
|
if (filterModifierList != nullptr)
|
||||||
|
if (filterModifierList->Contains(key) && key->StartsWith(PARENT_MODIFIER+ "/") ) // modifier has been applied and filters should be ignored
|
||||||
|
{
|
||||||
|
++filterMatchCount;
|
||||||
|
//System::Console::WriteLine("PARENT_MODIFIER {0}", key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(filterModifierList->Contains(key) && key->StartsWith(FIRST_MODIFIER+ "/")) //first already found stop!
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("FIRST_MODIFIER {0}", key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
System::String ^filterProp = key;
|
||||||
|
System::String ^modifier = L"";
|
||||||
|
int pos = key->IndexOf(L"/");
|
||||||
|
if (pos != -1)//tree modifier
|
||||||
|
{
|
||||||
|
modifier = filterProp->Substring(0, pos);
|
||||||
|
filterProp = filterProp->Substring(pos+1);
|
||||||
|
//System::Console::WriteLine("modifier: {0}, {1}, {2}", modifier, filterProp, key);
|
||||||
|
}
|
||||||
|
if (shortPropName->Equals(filterProp) || ap->ProgrammaticName->Equals(filterProp))
|
||||||
|
{//this element has a matching filter property
|
||||||
|
//System::Console::WriteLine("matched property: {0}", filterProp);
|
||||||
|
System::String ^valStr = L"";
|
||||||
|
if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty"))
|
||||||
|
{//runtimeId are int array so need to test it differently
|
||||||
|
array<System::Int32> ^idArray = (array<System::Int32> ^)element->GetCurrentPropertyValue(ap);
|
||||||
|
for each(System::Int32 val in idArray)
|
||||||
|
{
|
||||||
|
valStr += System::Convert::ToString(val) + L"-";
|
||||||
|
}
|
||||||
|
valStr = valStr->TrimEnd('-');
|
||||||
|
//System::Console::WriteLine("runtimeId: {0}", valStr);
|
||||||
|
}
|
||||||
|
else //all other property types that are strings
|
||||||
|
{
|
||||||
|
valStr = element->GetCachedPropertyValue(ap)->ToString();
|
||||||
|
//valStr = element->GetCurrentPropertyValue(ap)->ToString();
|
||||||
|
}
|
||||||
|
//System::Console::WriteLine("test property vals: {0} , {1}", valStr, enumFilters[key]);
|
||||||
|
|
||||||
|
if (valStr->Equals(enumFilters[key])) // value matches filter value
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("matched property vals: {0} , {1}", valStr, enumFilters[key]);
|
||||||
|
//result = false;
|
||||||
|
++filterMatchCount;
|
||||||
|
if (filterModifierList != nullptr)
|
||||||
|
if (modifier->Equals(PARENT_MODIFIER)) //if modifier is parent then add to modifier list
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("modifier added1 {0}", key);
|
||||||
|
filterModifierList->Add(key);
|
||||||
|
}
|
||||||
|
else if(modifier->Equals(FIRST_MODIFIER)) {
|
||||||
|
//System::Console::WriteLine("first modifier added1 {0} {1}", key, filterModifierList->Count);
|
||||||
|
//for each (System::String ^mod in filterModifierList)
|
||||||
|
// System::Console::WriteLine("mod {0}", mod);
|
||||||
|
filterModifierList->Add(key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else// not matched
|
||||||
|
if (filterModifierList != nullptr)
|
||||||
|
if (modifier->Equals(ALL_MODIFIER)) //doesn't matter if ALL modifier doesn't match, need to keep searching
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("modifier added2 {0}", key);
|
||||||
|
filterModifierList->Add(key);
|
||||||
|
}
|
||||||
|
else if(modifier->Equals(FIRST_MODIFIER))
|
||||||
|
filterModifierList->Add(ALL_MODIFIER + "/" + filterProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//System::Console::WriteLine("filterMatchCount: {0}", filterMatchCount);
|
||||||
|
if (filterMatchCount > 0)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
//return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutomationBridge::processFilterModifier(Boolean filtered, Boolean modifierChanged, List<System::String ^> ^filterModifierList)
|
||||||
|
{
|
||||||
|
if (!filtered) //not filtered so return element
|
||||||
|
{
|
||||||
|
//winInfoList->Add(getWindowInfo(currentElement, properties));
|
||||||
|
//winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
|
||||||
|
if (modifierChanged && filterModifierList[filterModifierList->Count - 1]->StartsWith(FIRST_MODIFIER) == false) //modifier was added and needs to be removed
|
||||||
|
{// don't remove First modifier
|
||||||
|
//System::Console::WriteLine("modifier removed1 {0}", filterModifierList[filterModifierList->Count - 1]);
|
||||||
|
filterModifierList->RemoveAt(filterModifierList->Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //filtered, but if modifier used keep searching children
|
||||||
|
{
|
||||||
|
if (modifierChanged) //modifier was added and needs to be removed (ALL)
|
||||||
|
{
|
||||||
|
//winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
|
||||||
|
if (filterModifierList[filterModifierList->Count - 1]->StartsWith(FIRST_MODIFIER) == false)// don't remove First modifier
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("modifier removed2 {0}", filterModifierList[filterModifierList->Count - 1]);
|
||||||
|
filterModifierList->RemoveAt(filterModifierList->Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String ^ AutomationBridge::getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element)
|
||||||
|
{
|
||||||
|
System::String ^result = L"";
|
||||||
|
System::Object ^currentVal = element->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
|
||||||
|
if (currentVal != nullptr)
|
||||||
|
{
|
||||||
|
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
|
||||||
|
for each(System::Int32 val in idArray)
|
||||||
|
{
|
||||||
|
result += System::Convert::ToString(val) + L"-";
|
||||||
|
}
|
||||||
|
result = result->TrimEnd('-');
|
||||||
|
//System::Console::WriteLine("id: {0}", result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
array<System::String ^> ^ AutomationBridge::enumWindowInfo(System::String ^properties)
|
||||||
|
{
|
||||||
|
return enumWindowInfo(AutomationElement::RootElement, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
array<System::String ^> ^ AutomationBridge::enumWindowInfo(System::IntPtr windowHandle, System::String ^properties)
|
||||||
|
{
|
||||||
|
AutomationElement ^element = AutomationElement::FromHandle(windowHandle);
|
||||||
|
List<System::String ^> ^winInfoList = gcnew List<System::String ^>();
|
||||||
|
if (!isElementFiltered(element)) //test parent should be filtered
|
||||||
|
winInfoList->Add(getWindowInfo(element, properties));
|
||||||
|
winInfoList->AddRange(enumWindowInfo(element, properties));
|
||||||
|
return winInfoList->ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
array<System::String ^> ^ AutomationBridge::enumWindowInfo(AutomationElement ^element, System::String ^properties)
|
||||||
|
{
|
||||||
|
List<System::String ^> ^filterModifierList = gcnew List<System::String ^>(); //can change descendants filters based on parent's filters
|
||||||
|
return enumWindowInfo(element, properties, filterModifierList);
|
||||||
|
}
|
||||||
|
|
||||||
|
array<System::String ^> ^ AutomationBridge::enumWindowInfo(AutomationElement ^element, System::String ^properties, List<System::String ^> ^filterModifierList)
|
||||||
|
{
|
||||||
|
List<System::String ^> ^winInfoList = gcnew List<System::String ^>();
|
||||||
|
if (element == nullptr)
|
||||||
|
return winInfoList->ToArray();
|
||||||
|
TreeWalker ^tw = TreeWalker::RawViewWalker;
|
||||||
|
//System::Console::WriteLine("get info: {0}", getWindowInfo(element, properties));
|
||||||
|
//AutomationElement ^currentElement = tw->GetFirstChild(element, cacheRequest);
|
||||||
|
AutomationElement ^currentElement = nullptr;
|
||||||
|
/*if (element->CachedChildren != nullptr)
|
||||||
|
{
|
||||||
|
System::Console::WriteLine("using cached child");
|
||||||
|
currentElement = element->CachedChildren[0];
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("not cached child");
|
||||||
|
currentElement = tw->GetFirstChild(element, cacheRequest);
|
||||||
|
}
|
||||||
|
if (currentElement == nullptr)
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("no children {0}", element->CachedChildren->Count);
|
||||||
|
//System::Console::WriteLine("no children");
|
||||||
|
return winInfoList->ToArray();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// System::Console::WriteLine("yes children");
|
||||||
|
|
||||||
|
while (currentElement != nullptr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int fmlOriginalSize = filterModifierList->Count;
|
||||||
|
Boolean filtered = isElementFiltered(currentElement, filterModifierList);
|
||||||
|
Boolean modifierChanged = fmlOriginalSize != filterModifierList->Count;
|
||||||
|
if (!filtered) //not filtered so return element
|
||||||
|
{
|
||||||
|
winInfoList->Add(getWindowInfo(currentElement, properties));
|
||||||
|
winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
|
||||||
|
}
|
||||||
|
else //filtered, but if modifier used keep searching children
|
||||||
|
{
|
||||||
|
if (modifierChanged) //modifier was added search children
|
||||||
|
winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
|
||||||
|
}
|
||||||
|
processFilterModifier(filtered, modifierChanged, filterModifierList); //cleans filterModifierList
|
||||||
|
//System::Console::WriteLine("element: {0}", currentElement);
|
||||||
|
//currentElement->
|
||||||
|
currentElement = tw->GetNextSibling(currentElement, cacheRequest);
|
||||||
|
} catch (Exception ^ex)
|
||||||
|
{
|
||||||
|
System::Console::WriteLine("Exception: {0} {1}", ex->Message, ex->StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return winInfoList->ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String ^ AutomationBridge::getWindowInfo(AutomationElement ^element, System::String ^properties)
|
||||||
|
{
|
||||||
|
System::String ^resultProperties = L"";
|
||||||
|
System::String ^propertyNameErrorCheck = L"";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//when wildcard is enabled it will pull all property names & values
|
||||||
|
System::Boolean wildcardEnabled = false;
|
||||||
|
if (properties->Equals(L"*"))
|
||||||
|
wildcardEnabled = true;
|
||||||
|
|
||||||
|
//create array for keeping order of properties
|
||||||
|
System::String ^delim = L",";
|
||||||
|
array<System::String ^> ^propSpltArray = properties->Split(delim->ToCharArray());
|
||||||
|
TreeWalker ^tw = TreeWalker::ControlViewWalker;
|
||||||
|
System::Int32 count = 0;
|
||||||
|
array<AutomationProperty^> ^aps = cachedRootProperties;//element->GetSupportedProperties();
|
||||||
|
array<System::String ^> ^propValues = gcnew array<System::String ^>(propSpltArray->Length);//keep order
|
||||||
|
System::String ^wildcardProperties = L"";
|
||||||
|
if (wildcardEnabled) {
|
||||||
|
wildcardProperties += "ParentRuntimeIdProperty:" + getRuntimeIdFromElement(tw->GetParent(element, cacheRequest)) + ",";
|
||||||
|
//propValues = gcnew array<System::String ^>(aps->Length +1 );//add one for parent property since it doesn't exist
|
||||||
|
}
|
||||||
|
for(int i=0 ; i < propValues->Length ; i++)
|
||||||
|
{
|
||||||
|
propValues[i] = L"";
|
||||||
|
if (propSpltArray[i]->Equals("ParentRuntimeIdProperty"))//custom property for getting parent
|
||||||
|
{
|
||||||
|
propValues[i] = getRuntimeIdFromElement(tw->GetParent(element, cacheRequest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for each(AutomationProperty ^ap in aps) //loop through all supported Properties for a child
|
||||||
|
{
|
||||||
|
propertyNameErrorCheck = ap->ProgrammaticName;//debug purposes
|
||||||
|
System::String ^currentPropertyStr = L""; //current property values
|
||||||
|
//System::Console::WriteLine("property: {0}", ap->ProgrammaticName);
|
||||||
|
System::String ^shortPropName = L" null ";
|
||||||
|
if (ap->ProgrammaticName->Contains(L"."))
|
||||||
|
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
|
||||||
|
if (properties->Contains(shortPropName) || properties->Contains(ap->ProgrammaticName) || ap->ProgrammaticName->Equals(properties) || wildcardEnabled)
|
||||||
|
{
|
||||||
|
//System::Console::WriteLine("shortPropName: {0}", shortPropName);
|
||||||
|
//System::Object ^currentVal = element->GetCurrentPropertyValue(ap);
|
||||||
|
System::Object ^currentVal = element->GetCachedPropertyValue(ap);
|
||||||
|
if (currentVal == nullptr)
|
||||||
|
continue;
|
||||||
|
if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty"))
|
||||||
|
{
|
||||||
|
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
|
||||||
|
for each(System::Int32 val in idArray)
|
||||||
|
{
|
||||||
|
currentPropertyStr += System::Convert::ToString(val) + L"-";
|
||||||
|
}
|
||||||
|
currentPropertyStr = currentPropertyStr->TrimEnd('-');
|
||||||
|
//System::Console::WriteLine("id: {0}", result);
|
||||||
|
}
|
||||||
|
else//not runtimeId which is an Int32[]
|
||||||
|
{
|
||||||
|
currentPropertyStr = currentVal->ToString();
|
||||||
|
currentPropertyStr = currentPropertyStr->Replace(",",",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentPropertyStr->Equals(L"")) //if there isn't a value skip
|
||||||
|
continue;
|
||||||
|
if (wildcardEnabled) {
|
||||||
|
wildcardProperties += shortPropName + ":" +currentPropertyStr + ",";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//System::Console::WriteLine("currentPropertyStr: {0}", currentPropertyStr);
|
||||||
|
//find the correct order to return this property
|
||||||
|
for(int i=0 ; i < propSpltArray->Length ; i++)
|
||||||
|
{
|
||||||
|
if (propSpltArray[i]->Equals(shortPropName) || propSpltArray[i]->Equals(ap->ProgrammaticName))
|
||||||
|
propValues[i] = currentPropertyStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//output properties in the correct order
|
||||||
|
for(int i=0 ; i < propSpltArray->Length ; i++)
|
||||||
|
resultProperties += propValues[i] + L",";
|
||||||
|
if (wildcardEnabled)
|
||||||
|
resultProperties += wildcardProperties;
|
||||||
|
} catch (Exception ^ex) //when some elements close during enumeration it might cause valid exceptions
|
||||||
|
{
|
||||||
|
System::Console::WriteLine("Exception ({2}): {0} {1}", ex->Message, ex->StackTrace, propertyNameErrorCheck);
|
||||||
|
}
|
||||||
|
return resultProperties;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String ^ AutomationBridge::getWindowInfo(System::Int32 x, System::Int32 y, System::String ^properties)
|
||||||
|
{
|
||||||
|
AutomationElement ^element = AutomationElement::FromPoint(System::Windows::Point(x, y));
|
||||||
|
return getWindowInfo(element, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String ^ AutomationBridge::getWindowInfo(System::IntPtr windowHandle, System::String ^properties)
|
||||||
|
{
|
||||||
|
AutomationElement ^element = AutomationElement::FromHandle(windowHandle);
|
||||||
|
return getWindowInfo(element, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String ^ AutomationBridge::getWindowInfo(System::String ^runtimeIdStr, System::String ^properties)
|
||||||
|
{
|
||||||
|
System::String ^filter = L"First/RuntimeIdProperty"; //get first matching runtimeIdProperty
|
||||||
|
enumFilters->Add(filter, runtimeIdStr);
|
||||||
|
array<System::String ^> ^props = enumWindowInfo(properties);
|
||||||
|
enumFilters->Remove(filter);
|
||||||
|
if (props->Length > 0) //if result array has a match return first result
|
||||||
|
return props[0];
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
//return getWindowInfo(element, properties);
|
||||||
|
}
|
||||||
46
native/uiabridge/uiabridge.h
Normal file
46
native/uiabridge/uiabridge.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski7@gmail.com
|
||||||
|
*/
|
||||||
|
// uiabridge.h
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Collections::Generic;
|
||||||
|
using namespace System::Windows::Automation;
|
||||||
|
|
||||||
|
namespace uiabridge {
|
||||||
|
|
||||||
|
public ref class AutomationBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutomationBridge(void);
|
||||||
|
~AutomationBridge();
|
||||||
|
int addEnumFilter(System::String ^propertyName, System::String ^propertyValue);
|
||||||
|
void clearEnumFilters();
|
||||||
|
Boolean isElementFiltered(System::Windows::Automation::AutomationElement ^element);
|
||||||
|
Boolean isElementFiltered(System::Windows::Automation::AutomationElement ^element, List<System::String ^> ^filterModifierList);
|
||||||
|
System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element);
|
||||||
|
array<System::String ^> ^ enumWindowInfo(System::String ^properties);
|
||||||
|
array<System::String ^> ^ enumWindowInfo(System::IntPtr windowHandle, System::String ^properties);
|
||||||
|
array<System::String ^> ^ enumWindowInfo(AutomationElement ^element, System::String ^properties);
|
||||||
|
array<System::String ^> ^ enumWindowInfo(AutomationElement ^element, System::String ^properties, List<System::String ^> ^filterModifierList);
|
||||||
|
System::String ^ getWindowInfo(AutomationElement ^element, System::String ^properties);
|
||||||
|
System::String ^ getWindowInfo(System::Int32 x, System::Int32 y, System::String ^properties);
|
||||||
|
System::String ^ getWindowInfo(System::IntPtr windowHandle, System::String ^properties);
|
||||||
|
System::String ^ getWindowInfo(System::String ^runtimeIdStr, System::String ^properties);
|
||||||
|
|
||||||
|
static System::String ^ALL_MODIFIER = L"All";// find all matching elements of this filter
|
||||||
|
static System::String ^PARENT_MODIFIER = L"Parent";//find all children of this matching parent filter
|
||||||
|
static System::String ^FIRST_MODIFIER = L"First"; //find first element matching this filter then stop
|
||||||
|
private:
|
||||||
|
void initializeCache();
|
||||||
|
Dictionary<System::String ^, System::String ^> ^enumFilters;
|
||||||
|
void AutomationBridge::processFilterModifier(Boolean filtered, Boolean modifierChanged, List<System::String ^> ^filterModifierList);
|
||||||
|
CacheRequest ^cacheRequest;
|
||||||
|
array<AutomationProperty^> ^cachedRootProperties;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{3141812E-36D5-4E7C-A388-EFED9AE250A5}</ProjectGuid>
|
<ProjectGuid>{BAC1B079-7B87-4396-B17F-91A86DF1AE29}</ProjectGuid>
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
<Keyword>ManagedCProj</Keyword>
|
<Keyword>ManagedCProj</Keyword>
|
||||||
<RootNamespace>WpfBridge</RootNamespace>
|
<RootNamespace>uiabridge</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
@@ -120,8 +120,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>mkdir "$(ProjectDir)bin"
|
<Command>mkdir "$(ProjectDir)bin"
|
||||||
copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)"
|
copy /Y "$(TargetPath)" "$(ProjectDir)bin\uiabridge$(PlatformArchitecture)$(TargetExt)"</Command>
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -137,8 +136,7 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(Targ
|
|||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>mkdir "$(ProjectDir)bin"
|
<Command>mkdir "$(ProjectDir)bin"
|
||||||
copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)"
|
copy /Y "$(TargetPath)" "$(ProjectDir)bin\uiabridge$(PlatformArchitecture)$(TargetExt)"</Command>
|
||||||
</Command>
|
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -146,28 +144,29 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(Targ
|
|||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="UIAutomationClient" />
|
<Reference Include="UIAutomationClient" />
|
||||||
|
<Reference Include="UIAutomationClientsideProviders" />
|
||||||
<Reference Include="UIAutomationProvider" />
|
<Reference Include="UIAutomationProvider" />
|
||||||
<Reference Include="UIAutomationTypes" />
|
<Reference Include="UIAutomationTypes" />
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Global.h" />
|
<ClInclude Include="Global.h" />
|
||||||
<ClInclude Include="org_synthuse_WpfBridge.h" />
|
<ClInclude Include="org_synthuse_UiaBridge.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
<ClInclude Include="Stdafx.h" />
|
<ClInclude Include="Stdafx.h" />
|
||||||
<ClInclude Include="WpfAutomation.h" />
|
<ClInclude Include="uiabridge.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AssemblyInfo.cpp" />
|
<ClCompile Include="AssemblyInfo.cpp" />
|
||||||
<ClCompile Include="Global.cpp" />
|
<ClCompile Include="Global.cpp" />
|
||||||
<ClCompile Include="org_synthuse_WpfBridge.cpp" />
|
<ClCompile Include="org_synthuse_UiaBridge.cpp" />
|
||||||
<ClCompile Include="Stdafx.cpp">
|
<ClCompile Include="Stdafx.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="WpfAutomation.cpp" />
|
<ClCompile Include="uiabridge.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.ico" />
|
<None Include="app.ico" />
|
||||||
@@ -15,16 +15,16 @@
|
|||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="uiabridge.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Stdafx.h">
|
<ClInclude Include="Stdafx.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="resource.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="org_synthuse_WpfBridge.h">
|
<ClInclude Include="org_synthuse_UiaBridge.h">
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="WpfAutomation.h">
|
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Global.h">
|
<ClInclude Include="Global.h">
|
||||||
@@ -32,16 +32,16 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="uiabridge.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="AssemblyInfo.cpp">
|
<ClCompile Include="AssemblyInfo.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Stdafx.cpp">
|
<ClCompile Include="Stdafx.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="WpfAutomation.cpp">
|
<ClCompile Include="org_synthuse_UiaBridge.cpp">
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="org_synthuse_WpfBridge.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Global.cpp">
|
<ClCompile Include="Global.cpp">
|
||||||
40
native/uiabtest/AssemblyInfo.cpp
Normal file
40
native/uiabtest/AssemblyInfo.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Reflection;
|
||||||
|
using namespace System::Runtime::CompilerServices;
|
||||||
|
using namespace System::Runtime::InteropServices;
|
||||||
|
using namespace System::Security::Permissions;
|
||||||
|
|
||||||
|
//
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
//
|
||||||
|
[assembly:AssemblyTitleAttribute("uiabtest")];
|
||||||
|
[assembly:AssemblyDescriptionAttribute("")];
|
||||||
|
[assembly:AssemblyConfigurationAttribute("")];
|
||||||
|
[assembly:AssemblyCompanyAttribute("na")];
|
||||||
|
[assembly:AssemblyProductAttribute("uiabtest")];
|
||||||
|
[assembly:AssemblyCopyrightAttribute("Copyright (c) na 2014")];
|
||||||
|
[assembly:AssemblyTrademarkAttribute("")];
|
||||||
|
[assembly:AssemblyCultureAttribute("")];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the value or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||||
|
|
||||||
|
[assembly:ComVisible(false)];
|
||||||
|
|
||||||
|
[assembly:CLSCompliantAttribute(true)];
|
||||||
|
|
||||||
|
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
|
||||||
35
native/uiabtest/ReadMe.txt
Normal file
35
native/uiabtest/ReadMe.txt
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
========================================================================
|
||||||
|
APPLICATION : uiabtest Project Overview
|
||||||
|
========================================================================
|
||||||
|
|
||||||
|
AppWizard has created this uiabtest Application for you.
|
||||||
|
|
||||||
|
This file contains a summary of what you will find in each of the files that
|
||||||
|
make up your uiabtest application.
|
||||||
|
|
||||||
|
uiabtest.vcxproj
|
||||||
|
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||||
|
It contains information about the version of Visual C++ that generated the file, and
|
||||||
|
information about the platforms, configurations, and project features selected with the
|
||||||
|
Application Wizard.
|
||||||
|
|
||||||
|
uiabtest.vcxproj.filters
|
||||||
|
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||||
|
It contains information about the association between the files in your project
|
||||||
|
and the filters. This association is used in the IDE to show grouping of files with
|
||||||
|
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||||
|
"Source Files" filter).
|
||||||
|
|
||||||
|
uiabtest.cpp
|
||||||
|
This is the main application source file.
|
||||||
|
|
||||||
|
AssemblyInfo.cpp
|
||||||
|
Contains custom attributes for modifying assembly metadata.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
Other notes:
|
||||||
|
|
||||||
|
AppWizard uses "TODO:" to indicate parts of the source code you
|
||||||
|
should add to or customize.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
BIN
native/uiabtest/app.ico
Normal file
BIN
native/uiabtest/app.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
native/uiabtest/app.rc
Normal file
BIN
native/uiabtest/app.rc
Normal file
Binary file not shown.
3
native/uiabtest/resource.h
Normal file
3
native/uiabtest/resource.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by app.rc
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
// stdafx.cpp : source file that includes just the standard includes
|
// stdafx.cpp : source file that includes just the standard includes
|
||||||
// WpfBridge.pch will be the pre-compiled header
|
// uiabtest.pch will be the pre-compiled header
|
||||||
// stdafx.obj will contain the pre-compiled type information
|
// stdafx.obj will contain the pre-compiled type information
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
|
||||||
11
native/uiabtest/stdafx.h
Normal file
11
native/uiabtest/stdafx.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// stdafx.h : include file for standard system include files,
|
||||||
|
// or project specific include files that are used frequently, but
|
||||||
|
// are changed infrequently
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// TODO: reference additional headers your program requires here
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <tchar.h>
|
||||||
71
native/uiabtest/uiabtest.cpp
Normal file
71
native/uiabtest/uiabtest.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Synthuse.org
|
||||||
|
* Released under the Apache Version 2.0 License.
|
||||||
|
*
|
||||||
|
* last modified by ejakubowski7@gmail.com
|
||||||
|
*/
|
||||||
|
// uiabtest.cpp : main project file.
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Windows::Automation;
|
||||||
|
using namespace uiabridge;
|
||||||
|
|
||||||
|
void outputResults(array<System::String ^> ^winInfo)
|
||||||
|
{
|
||||||
|
System::IO::StreamWriter ^file = gcnew System::IO::StreamWriter("c:\\temp.txt");
|
||||||
|
for each(System::String ^prop in winInfo)
|
||||||
|
{
|
||||||
|
Console::WriteLine(prop);
|
||||||
|
file->WriteLine(prop);
|
||||||
|
}
|
||||||
|
file->Flush();
|
||||||
|
file->Close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(array<System::String ^> ^args)
|
||||||
|
{
|
||||||
|
Console::WriteLine(L"UI Automation Bridge Test");
|
||||||
|
AutomationBridge ^ab = gcnew AutomationBridge();
|
||||||
|
System::String ^propList = L"RuntimeIdProperty,ParentRuntimeIdProperty,NativeWindowHandleProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty";
|
||||||
|
//System::String ^propList = L"RuntimeIdProperty,BoundingRectangleProperty";
|
||||||
|
Console::WriteLine(propList);
|
||||||
|
//System::String ^winInfo1 = ab->getWindowInfo(System::IntPtr(3409618), propList);
|
||||||
|
|
||||||
|
System::DateTime start = System::DateTime::Now;
|
||||||
|
//ab->addEnumFilter("Parent/ClassNameProperty", "Notepad");
|
||||||
|
//ab->addEnumFilter("First/RuntimeIdProperty", "42-4784952");
|
||||||
|
//ab->addEnumFilter("ClassNameProperty", "Notepad");
|
||||||
|
//ab->addEnumFilter("All/ClassNameProperty", "Edit");
|
||||||
|
//ab->addEnumFilter("All/LocalizedControlTypeProperty", "menu item");
|
||||||
|
ab->addEnumFilter("Parent/FrameworkIdProperty", "WinForm");
|
||||||
|
//ab->addEnumFilter("Parent/FrameworkIdProperty", "WPF");
|
||||||
|
//ab->addEnumFilter("Parent/ClassNameProperty", "WindowsForms10.Window.8.app.0.2bf8098_r13_ad1");
|
||||||
|
array<System::String ^> ^winInfo = ab->enumWindowInfo(propList); //L"*"
|
||||||
|
//ab->clearEnumFilters();
|
||||||
|
//ab->addEnumFilter("Parent/FrameworkIdProperty", "WinForm");
|
||||||
|
//array<System::String ^> ^winInfo = ab->enumWindowInfo(System::IntPtr(3409618), propList); //L"*"
|
||||||
|
//array<System::String ^> ^winInfo = ab->enumWindowInfo(System::IntPtr(12977932), propList); //L"*"
|
||||||
|
//Console::WriteLine("enumWindowInfo x,y: {0}", ab->getWindowInfo(100,100, propList); //L"*"
|
||||||
|
|
||||||
|
outputResults(winInfo);
|
||||||
|
//Globals::Global::AUTO_BRIDGE->clearEnumFilters();
|
||||||
|
//winInfo = nullptr;
|
||||||
|
//winInfo = Globals::Global::AUTO_BRIDGE->enumWindowInfo(System::IntPtr(7603636), propList);
|
||||||
|
//Console::WriteLine("winInfo length: {0}", winInfo->Length);
|
||||||
|
//winInfo = Globals::Global::AUTO_BRIDGE->enumWindowInfo(System::IntPtr(7603636), propList);
|
||||||
|
//Console::WriteLine("winInfo length: {0}", winInfo->Length);
|
||||||
|
|
||||||
|
//Console::WriteLine("getWindowInfo RuntimeIdProperty: {0}", ab->getWindowInfo("42-4784952", propList));
|
||||||
|
|
||||||
|
//System::Threading::Thread::Sleep(10000); //10 seconds sleep
|
||||||
|
//array<System::String ^> ^winInfo2 = ab->enumWindowInfo(propList); //L"*"
|
||||||
|
//outputResults(winInfo2);
|
||||||
|
|
||||||
|
System::Double seconds = System::Math::Round(System::DateTime::Now.Subtract(start).TotalSeconds, 4);
|
||||||
|
Console::WriteLine(L"Total Elements: {0} in {1} seconds", winInfo->Length, seconds);
|
||||||
|
getch();//wait for user input
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
169
native/uiabtest/uiabtest.vcxproj
Normal file
169
native/uiabtest/uiabtest.vcxproj
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}</ProjectGuid>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<Keyword>ManagedCProj</Keyword>
|
||||||
|
<RootNamespace>uiabtest</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CLRSupport>true</CLRSupport>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CLRSupport>true</CLRSupport>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<CLRSupport>true</CLRSupport>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<CLRSupport>true</CLRSupport>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>
|
||||||
|
</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>
|
||||||
|
</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>
|
||||||
|
</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>
|
||||||
|
</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="UIAutomationClient" />
|
||||||
|
<Reference Include="UIAutomationClientsideProviders" />
|
||||||
|
<Reference Include="UIAutomationProvider" />
|
||||||
|
<Reference Include="UIAutomationTypes" />
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.ico" />
|
||||||
|
<None Include="ReadMe.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="stdafx.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="app.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="AssemblyInfo.cpp" />
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="uiabtest.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\uiabridge\uiabridge.vcxproj">
|
||||||
|
<Project>{bac1b079-7b87-4396-b17f-91a86df1ae29}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
47
native/uiabtest/uiabtest.vcxproj.filters
Normal file
47
native/uiabtest/uiabtest.vcxproj.filters
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="ReadMe.txt" />
|
||||||
|
<None Include="app.ico">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="stdafx.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="app.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="uiabtest.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="AssemblyInfo.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
3
native/uiabtest/uiabtest.vcxproj.user
Normal file
3
native/uiabtest/uiabtest.vcxproj.user
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
</Project>
|
||||||
@@ -195,14 +195,142 @@ public class RobotMacro {
|
|||||||
lastException = e;
|
lastException = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* SendKeys Special Keys List
|
||||||
|
{BACKSPACE}, {BS}, or {BKSP}
|
||||||
|
{BREAK}
|
||||||
|
{CAPSLOCK}
|
||||||
|
{DELETE} or {DEL}
|
||||||
|
{DOWN}
|
||||||
|
{END}
|
||||||
|
{ENTER} or ~
|
||||||
|
{ESC}
|
||||||
|
{HELP}
|
||||||
|
{HOME}
|
||||||
|
{INSERT} or {INS}
|
||||||
|
{LEFT}
|
||||||
|
{NUMLOCK}
|
||||||
|
{PGDN}
|
||||||
|
{PGUP}
|
||||||
|
{PRTSC} (reserved for future use)
|
||||||
|
{RIGHT}
|
||||||
|
{SCROLLLOCK}
|
||||||
|
{TAB}
|
||||||
|
{UP}
|
||||||
|
{F1}
|
||||||
|
{F2}
|
||||||
|
{F3}
|
||||||
|
{F4}
|
||||||
|
{F5}
|
||||||
|
{F6}
|
||||||
|
{F7}
|
||||||
|
{F8}
|
||||||
|
{F9}
|
||||||
|
{F10}
|
||||||
|
{F11}
|
||||||
|
{F12}
|
||||||
|
{F13}
|
||||||
|
{F14}
|
||||||
|
{F15}
|
||||||
|
{F16}
|
||||||
|
{ADD}
|
||||||
|
{SUBTRACT}
|
||||||
|
{MULTIPLY}
|
||||||
|
{DIVIDE}
|
||||||
|
{{}
|
||||||
|
{}}
|
||||||
|
SHIFT +
|
||||||
|
CTRL ^
|
||||||
|
ALT %
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
public static boolean sendKeys(String keyCommands) {
|
public static boolean sendKeys(String keyCommands) {
|
||||||
try {
|
try {
|
||||||
Robot robot = new Robot();
|
Robot robot = new Robot();
|
||||||
|
boolean specialKeyFlag = false;
|
||||||
|
String specialKey = "";
|
||||||
|
boolean modifierKeyFlag = false;
|
||||||
|
String modifierKeys = "";
|
||||||
for (int i = 0; i < keyCommands.length(); i++) {
|
for (int i = 0; i < keyCommands.length(); i++) {
|
||||||
char key = keyCommands.charAt(i);
|
char key = keyCommands.charAt(i);
|
||||||
int[] keyCode = getKeyCode(key);
|
if (specialKeyFlag)
|
||||||
pressKeyCodes(robot, keyCode);
|
specialKey += key;
|
||||||
|
if (key == '{' && specialKeyFlag == false) {
|
||||||
|
specialKeyFlag = true;
|
||||||
|
specialKey = "{";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!specialKeyFlag) { //not special key(tab,enter,...) just press normal keys and modifiers
|
||||||
|
// Modifier key logic
|
||||||
|
if (key == '+' || key == '^' || key == '%') { //shift alt or ctrl
|
||||||
|
if (!modifierKeyFlag) {
|
||||||
|
modifierKeys = key + "";
|
||||||
|
modifierKeyFlag = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
modifierKeys += key + ""; //append multiple modifiers
|
||||||
|
if (key == '+')
|
||||||
|
robot.keyPress(KeyEvent.VK_SHIFT);
|
||||||
|
if (key == '^')
|
||||||
|
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||||
|
if (key == '%')
|
||||||
|
robot.keyPress(KeyEvent.VK_ALT);
|
||||||
|
continue; //skip to next key
|
||||||
|
}
|
||||||
|
pressKeyCodes(robot, getKeyCode(key));
|
||||||
|
}
|
||||||
|
if (specialKeyFlag) {
|
||||||
|
if (specialKey.equals("{ENTER}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_ENTER} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{ESC}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_ESCAPE} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{HOME}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_HOME} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{END}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_END} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{PGDN}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_PAGE_DOWN} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{PGUP}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_PAGE_UP} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{TAB}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_TAB} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{UP}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_UP} );
|
||||||
|
}
|
||||||
|
else if (specialKey.equals("{DOWN}")) {
|
||||||
|
specialKeyFlag = false;
|
||||||
|
pressKeyCodes(robot, new int[]{KeyEvent.VK_DOWN} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifierKeyFlag) { //time to release all the modifier keys
|
||||||
|
modifierKeyFlag = false;
|
||||||
|
for (int m = 0; m < modifierKeys.length(); m++) {
|
||||||
|
char mkey = modifierKeys.charAt(m);
|
||||||
|
if (mkey == '+')
|
||||||
|
robot.keyRelease(KeyEvent.VK_SHIFT);
|
||||||
|
if (mkey == '^')
|
||||||
|
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||||
|
if (mkey == '%')
|
||||||
|
robot.keyRelease(KeyEvent.VK_ALT);
|
||||||
|
}
|
||||||
|
modifierKeys = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
lastException = e;
|
lastException = e;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class SynthuseDlg extends JFrame {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static String VERSION_STR = "1.1.0";
|
public static String VERSION_STR = "1.1.2";
|
||||||
|
|
||||||
public static String RES_STR_MAIN_ICON = "/org/synthuse/img/gnome-robots.png";
|
public static String RES_STR_MAIN_ICON = "/org/synthuse/img/gnome-robots.png";
|
||||||
public static String RES_STR_REFRESH_IMG = "/org/synthuse/img/rapidsvn.png";
|
public static String RES_STR_REFRESH_IMG = "/org/synthuse/img/rapidsvn.png";
|
||||||
@@ -102,7 +102,7 @@ public class SynthuseDlg extends JFrame {
|
|||||||
private TestIdeFrame testIde = null;
|
private TestIdeFrame testIde = null;
|
||||||
private int targetX;
|
private int targetX;
|
||||||
private int targetY;
|
private int targetY;
|
||||||
private WpfBridge wpf = new WpfBridge();
|
private UiaBridge uiabridge = new UiaBridge();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch the application.
|
* Launch the application.
|
||||||
@@ -449,7 +449,8 @@ public class SynthuseDlg extends JFrame {
|
|||||||
String handleStr = Api.GetHandleAsString(hwnd);
|
String handleStr = Api.GetHandleAsString(hwnd);
|
||||||
String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd));
|
String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd));
|
||||||
String parentStr = Api.GetHandleAsString(User32.instance.GetParent(hwnd));
|
String parentStr = Api.GetHandleAsString(User32.instance.GetParent(hwnd));
|
||||||
String runtimeId = wpf.getRuntimeIdFromPoint(targetX, targetY);
|
String enumProperties = uiabridge.getWindowInfo(targetX, targetY, WindowInfo.UIA_PROPERTY_LIST);
|
||||||
|
String runtimeId = WindowInfo.getRuntimeIdFromProperties(enumProperties);
|
||||||
lblStatus.setText("rid:" + runtimeId + " class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y: " + targetX + ", " + targetY);
|
lblStatus.setText("rid:" + runtimeId + " class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y: " + targetX + ", " + targetY);
|
||||||
if (!lastDragHwnd.equals(handleStr) || !lastRuntimeId.equals(runtimeId)) {
|
if (!lastDragHwnd.equals(handleStr) || !lastRuntimeId.equals(runtimeId)) {
|
||||||
if (!lastDragHwnd.isEmpty()) {
|
if (!lastDragHwnd.isEmpty()) {
|
||||||
@@ -459,7 +460,7 @@ public class SynthuseDlg extends JFrame {
|
|||||||
lastRuntimeId = runtimeId;
|
lastRuntimeId = runtimeId;
|
||||||
//lastDragHwnd = (hwnd + "");
|
//lastDragHwnd = (hwnd + "");
|
||||||
Api.highlightWindow(hwnd);
|
Api.highlightWindow(hwnd);
|
||||||
XpathManager.buildXpathStatementThreaded(hwnd, runtimeId, textPane, xpathEvents);
|
XpathManager.buildXpathStatementThreaded(hwnd, enumProperties, textPane, xpathEvents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,14 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014, Synthuse.org
|
|
||||||
* Released under the Apache Version 2.0 License.
|
|
||||||
*
|
|
||||||
* last modified by ejakubowski7@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.synthuse;
|
package org.synthuse;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
public class WpfBridge {
|
public class UiaBridge {
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
String archDataModel = System.getProperty("sun.arch.data.model");//32 or 64 bit
|
String archDataModel = System.getProperty("sun.arch.data.model");//32 or 64 bit
|
||||||
|
|
||||||
//System.loadLibrary("native/WpfBridge" + archDataModel); // WpfBridge32.dll (Windows) or WpfBridge32.so (Unixes)
|
//System.loadLibrary("native/WpfBridge" + archDataModel); // WpfBridge32.dll (Windows) or WpfBridge32.so (Unixes)
|
||||||
loadNativeLibraryFromJar("/wpfbridge" + archDataModel + ".dll");
|
loadNativeLibraryFromJar("/uiabridge" + archDataModel + ".dll");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadNativeLibraryFromJar(String path) {
|
public static void loadNativeLibraryFromJar(String path) {
|
||||||
@@ -49,7 +40,7 @@ public class WpfBridge {
|
|||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int readBytes;
|
int readBytes;
|
||||||
// Open and check input stream
|
// Open and check input stream
|
||||||
InputStream is = WpfBridge.class.getResourceAsStream(path);
|
InputStream is = UiaBridge.class.getResourceAsStream(path);
|
||||||
if (is == null) { //check if valid
|
if (is == null) { //check if valid
|
||||||
System.out.println("File " + path + " was not found inside JAR.");
|
System.out.println("File " + path + " was not found inside JAR.");
|
||||||
return;
|
return;
|
||||||
@@ -69,7 +60,27 @@ public class WpfBridge {
|
|||||||
// Finally, load the library
|
// Finally, load the library
|
||||||
System.load(temp.getAbsolutePath());
|
System.load(temp.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UiaBridge ()
|
||||||
|
{
|
||||||
|
initialize("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public native void initialize(String properties);
|
||||||
|
public native void shutdown();
|
||||||
|
public native int addEnumFilter(String propertyName, String propertyValue);
|
||||||
|
public native void clearEnumFilters();
|
||||||
|
public native String[] enumWindowInfo(String properties);
|
||||||
|
public native String[] enumWindowInfo(int windowHandle, String properties);
|
||||||
|
//native String[] enumWindowInfo(AutomationElement ^element, String properties);
|
||||||
|
//native String[] enumWindowInfo(AutomationElement ^element, String properties, String[] filterModifierList);
|
||||||
|
//native String getWindowInfo(AutomationElement ^element, String properties);
|
||||||
|
public native String getWindowInfo(int x, int y, String properties);
|
||||||
|
public native String getWindowInfo(int windowHandle, String properties);
|
||||||
|
public native String getWindowInfo(String runtimeId, String properties);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
public native void setFrameworkId(String propertyValue); //default is WPF, but also accepts Silverlight, Win32
|
public native void setFrameworkId(String propertyValue); //default is WPF, but also accepts Silverlight, Win32
|
||||||
public native void setTouchableOnly(boolean val); //default is true
|
public native void setTouchableOnly(boolean val); //default is true
|
||||||
|
|
||||||
@@ -80,7 +91,7 @@ public class WpfBridge {
|
|||||||
public native int countChildrenWindows();
|
public native int countChildrenWindows();
|
||||||
public native int countChildrenWindows(String runtimeIdValue);
|
public native int countChildrenWindows(String runtimeIdValue);
|
||||||
|
|
||||||
public native String[] enumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop
|
public String[] enumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop
|
||||||
public native String[] enumDescendantWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop
|
public native String[] enumDescendantWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop
|
||||||
public native String[] enumDescendantWindowIds(long processId);
|
public native String[] enumDescendantWindowIds(long processId);
|
||||||
//In all the above Enumerate methods will return a list of Runtime Ids for all related windows.
|
//In all the above Enumerate methods will return a list of Runtime Ids for all related windows.
|
||||||
@@ -92,11 +103,12 @@ public class WpfBridge {
|
|||||||
public native String getProperty(String propertyName, String runtimeIdValue);
|
public native String getProperty(String propertyName, String runtimeIdValue);
|
||||||
public native String[] getProperties(String runtimeIdValue);
|
public native String[] getProperties(String runtimeIdValue);
|
||||||
public native String[] getPropertiesAndValues(String runtimeIdValue);
|
public native String[] getPropertiesAndValues(String runtimeIdValue);
|
||||||
|
*/
|
||||||
public Point getCenterOfElement(String runtimeIdValue) {
|
public Point getCenterOfElement(String runtimeIdValue) {
|
||||||
Point p = new Point();
|
Point p = new Point();
|
||||||
String boundary = getProperty("BoundingRectangleProperty", runtimeIdValue);
|
String boundary = getWindowInfo(runtimeIdValue, "BoundingRectangleProperty");
|
||||||
//System.out.println("boundary: " + boundary); //boundary: 841,264,125,29
|
boundary = WindowInfo.replaceEscapedCodes(boundary);
|
||||||
|
//System.out.println("runtimeId: " + runtimeIdValue + ", boundary: " + boundary); //boundary: 841,264,125,29
|
||||||
String[] boundarySplt = boundary.split(",");
|
String[] boundarySplt = boundary.split(",");
|
||||||
int x = Integer.parseInt(boundarySplt[0]);
|
int x = Integer.parseInt(boundarySplt[0]);
|
||||||
int y = Integer.parseInt(boundarySplt[1]);
|
int y = Integer.parseInt(boundarySplt[1]);
|
||||||
@@ -106,25 +118,4 @@ public class WpfBridge {
|
|||||||
p.y = ((height) /2) + y;
|
p.y = ((height) /2) + y;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWindowClass(String runtimeIdValue) {
|
|
||||||
return getProperty("ClassNameProperty", runtimeIdValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWindowText(String runtimeIdValue) {
|
|
||||||
return getProperty("NameProperty", runtimeIdValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWindowValue(String runtimeIdValue) {
|
|
||||||
return getProperty("ValueProperty", runtimeIdValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWindowAutomationId(String runtimeIdValue) {
|
|
||||||
return getProperty("AutomationIdProperty", runtimeIdValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWindowFramework(String runtimeIdValue) {
|
|
||||||
return getProperty("FrameworkIdProperty", runtimeIdValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,9 @@ import com.sun.jna.ptr.PointerByReference;
|
|||||||
|
|
||||||
public class WindowInfo {
|
public class WindowInfo {
|
||||||
|
|
||||||
public static String WPF_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,ClassNameProperty,NameProperty,ValueProperty";
|
public static String UIA_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty,ValueProperty";
|
||||||
|
public static String UIA_RUNTIME_ID = "RuntimeIdProperty";
|
||||||
|
public static int MAX_TEXT_SIZE = 200;
|
||||||
|
|
||||||
public HWND hwnd;
|
public HWND hwnd;
|
||||||
public String hwndStr = "";
|
public String hwndStr = "";
|
||||||
@@ -33,6 +35,7 @@ public class WindowInfo {
|
|||||||
public RECT rect;
|
public RECT rect;
|
||||||
public String text;
|
public String text;
|
||||||
public String value;
|
public String value;
|
||||||
|
public String controlType = "";
|
||||||
public String className = "";
|
public String className = "";
|
||||||
public boolean isChild = false;
|
public boolean isChild = false;
|
||||||
public String processName = "";
|
public String processName = "";
|
||||||
@@ -53,9 +56,11 @@ public class WindowInfo {
|
|||||||
text = Native.toString(buffer);
|
text = Native.toString(buffer);
|
||||||
if (text.isEmpty())
|
if (text.isEmpty())
|
||||||
text = new Api().sendWmGetText(hWnd);
|
text = new Api().sendWmGetText(hWnd);
|
||||||
if (text.isEmpty()) {
|
//if (text.isEmpty()) {
|
||||||
//System.out.println("getting toolbar text");
|
//System.out.println("getting toolbar text");
|
||||||
}
|
//}
|
||||||
|
if (text.length() > MAX_TEXT_SIZE) //if text is too large it will slow down xml display
|
||||||
|
text = text.substring(0, MAX_TEXT_SIZE);
|
||||||
|
|
||||||
//Get item count depending on what type of control it is
|
//Get item count depending on what type of control it is
|
||||||
LRESULT tbCount = Api.User32.instance.SendMessage(hWnd, Api.TB_BUTTONCOUNT, new WPARAM(0), new LPARAM(0));
|
LRESULT tbCount = Api.User32.instance.SendMessage(hWnd, Api.TB_BUTTONCOUNT, new WPARAM(0), new LPARAM(0));
|
||||||
@@ -146,9 +151,11 @@ public class WindowInfo {
|
|||||||
}
|
}
|
||||||
this.hwnd = hWnd;
|
this.hwnd = hWnd;
|
||||||
hwndStr = Api.GetHandleAsString(hWnd);
|
hwndStr = Api.GetHandleAsString(hWnd);
|
||||||
|
if (this.hwndStr == null)
|
||||||
|
this.hwndStr = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String replaceEscapedCodes(String input) {
|
public static String replaceEscapedCodes(String input) {
|
||||||
//, is a comma ,
|
//, is a comma ,
|
||||||
String result = input;
|
String result = input;
|
||||||
result = result.replaceAll(",", ",");
|
result = result.replaceAll(",", ",");
|
||||||
@@ -160,9 +167,9 @@ public class WindowInfo {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//support for WPF and Silverlight
|
//support for WPF, Silverlight, WinForms
|
||||||
public WindowInfo(String enumProperties, boolean isChild) {
|
public WindowInfo(String enumProperties, boolean isChild) {
|
||||||
//WPF_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,ClassNameProperty,NameProperty";
|
//WPF_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty,ValueProperty";
|
||||||
String[] spltProperties = enumProperties.split(",");
|
String[] spltProperties = enumProperties.split(",");
|
||||||
this.isChild = isChild;
|
this.isChild = isChild;
|
||||||
if (SynthuseDlg.config.isFilterWpfDisabled()) { //use wildcard mode
|
if (SynthuseDlg.config.isFilterWpfDisabled()) { //use wildcard mode
|
||||||
@@ -180,6 +187,8 @@ public class WindowInfo {
|
|||||||
this.pid = Long.parseLong(propertyNameAndValue[1]);
|
this.pid = Long.parseLong(propertyNameAndValue[1]);
|
||||||
else if (propertyNameAndValue[0].equals("FrameworkIdProperty"))
|
else if (propertyNameAndValue[0].equals("FrameworkIdProperty"))
|
||||||
this.framework = propertyNameAndValue[1];
|
this.framework = propertyNameAndValue[1];
|
||||||
|
else if (propertyNameAndValue[0].equals("LocalizedControlTypeProperty"))
|
||||||
|
this.controlType = propertyNameAndValue[1];
|
||||||
else if (propertyNameAndValue[0].equals("ClassNameProperty"))
|
else if (propertyNameAndValue[0].equals("ClassNameProperty"))
|
||||||
this.className = propertyNameAndValue[1];
|
this.className = propertyNameAndValue[1];
|
||||||
else if (propertyNameAndValue[0].equals("NameProperty"))
|
else if (propertyNameAndValue[0].equals("NameProperty"))
|
||||||
@@ -191,6 +200,13 @@ public class WindowInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.hwndStr = this.runtimeId;
|
this.hwndStr = this.runtimeId;
|
||||||
|
if (text != null)
|
||||||
|
if (text.length() > MAX_TEXT_SIZE)
|
||||||
|
text = text.substring(0, MAX_TEXT_SIZE);
|
||||||
|
if (this.hwndStr == null)
|
||||||
|
this.hwndStr = "";
|
||||||
|
//if (this.framework == null)
|
||||||
|
// this.framework = "na";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// non-wildcard mode
|
// non-wildcard mode
|
||||||
@@ -204,11 +220,21 @@ public class WindowInfo {
|
|||||||
if (spltProperties.length > 3)
|
if (spltProperties.length > 3)
|
||||||
this.framework = spltProperties[3];
|
this.framework = spltProperties[3];
|
||||||
if (spltProperties.length > 4)
|
if (spltProperties.length > 4)
|
||||||
this.className = replaceEscapedCodes(spltProperties[4]);
|
this.controlType = replaceEscapedCodes(spltProperties[4]);
|
||||||
if (spltProperties.length > 5)
|
if (spltProperties.length > 5)
|
||||||
this.text = replaceEscapedCodes(spltProperties[5]);
|
this.className = replaceEscapedCodes(spltProperties[5]);
|
||||||
if (spltProperties.length > 6)
|
if (spltProperties.length > 6)
|
||||||
this.value = replaceEscapedCodes(spltProperties[6]);
|
this.text = replaceEscapedCodes(spltProperties[6]);
|
||||||
|
if (spltProperties.length > 7)
|
||||||
|
this.value = replaceEscapedCodes(spltProperties[7]);
|
||||||
|
if (this.className == "")
|
||||||
|
this.className = this.controlType;
|
||||||
|
if (text != null)
|
||||||
|
if (text.length() > MAX_TEXT_SIZE)
|
||||||
|
text = text.substring(0, MAX_TEXT_SIZE);
|
||||||
|
if (this.hwndStr == null)
|
||||||
|
this.hwndStr = "";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this.rect = new RECT();
|
this.rect = new RECT();
|
||||||
try {
|
try {
|
||||||
@@ -224,8 +250,16 @@ public class WindowInfo {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getRuntimeIdFromProperties(String enumProperties)
|
||||||
|
{
|
||||||
|
String[] spltProperties = enumProperties.split(",");
|
||||||
|
if (spltProperties.length > 0)
|
||||||
|
return spltProperties[0];
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("(%d,%d)-(%d,%d) : \"%s\" [%s] {%s}", rect.left,rect.top,rect.right,rect.bottom,text,className,hwnd.toString());
|
return String.format("%s \"%s\" [%s] (%s) {%s}", framework, text, className, controlType, hwndStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import com.sun.jna.platform.win32.WinUser;
|
|||||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
|
||||||
public class WindowsEnumeratedXml implements Runnable{
|
public class WindowsEnumeratedXml implements Runnable{
|
||||||
|
|
||||||
public static Exception lastException = null;
|
public static Exception lastException = null;
|
||||||
public static AtomicBoolean enumeratingXmlFlag = new AtomicBoolean(false);
|
public static AtomicBoolean enumeratingXmlFlag = new AtomicBoolean(false);
|
||||||
public JTextPane outputPane = null;
|
public JTextPane outputPane = null;
|
||||||
@@ -81,10 +82,16 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
final Map<String, String> processList = new LinkedHashMap<String, String>();
|
final Map<String, String> processList = new LinkedHashMap<String, String>();
|
||||||
final List<String> wpfParentList = new ArrayList<String>();//HwndWrapper
|
final List<String> wpfParentList = new ArrayList<String>();//HwndWrapper
|
||||||
final List<String> silverlightParentList = new ArrayList<String>();//MicrosoftSilverlight
|
final List<String> silverlightParentList = new ArrayList<String>();//MicrosoftSilverlight
|
||||||
|
final List<String> winFormParentList = new ArrayList<String>();//class="WindowsForms*"
|
||||||
int wpfCount = 0;
|
int wpfCount = 0;
|
||||||
|
int winFormCount = 0;
|
||||||
int silverlightCount = 0;
|
int silverlightCount = 0;
|
||||||
int menuCount = 0;
|
int menuCount = 0;
|
||||||
|
|
||||||
|
//wpf.setTouchableOnly(false);
|
||||||
|
//wpf.countChildrenWindows();//fix for missing cached elements
|
||||||
|
|
||||||
|
|
||||||
class ChildWindowCallback implements WinUser.WNDENUMPROC {
|
class ChildWindowCallback implements WinUser.WNDENUMPROC {
|
||||||
@Override
|
@Override
|
||||||
public boolean callback(HWND hWnd, Pointer lParam) {
|
public boolean callback(HWND hWnd, Pointer lParam) {
|
||||||
@@ -105,22 +112,31 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
infoList.put(wi.hwndStr, wi);
|
infoList.put(wi.hwndStr, wi);
|
||||||
if (wi.className.startsWith("HwndWrapper"))
|
if (wi.className.startsWith("HwndWrapper"))
|
||||||
wpfParentList.add(wi.hwndStr);
|
wpfParentList.add(wi.hwndStr);
|
||||||
|
if (wi.className.startsWith("WindowsForms"))
|
||||||
|
winFormParentList.add(wi.hwndStr);
|
||||||
Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0));
|
Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0);
|
Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0);
|
||||||
|
|
||||||
//Enumerate WPF windows and add to list
|
//Enumerate WPF, WinForm, Silverlight windows and add to list
|
||||||
if (!SynthuseDlg.config.isWpfBridgeDisabled())
|
if (!SynthuseDlg.config.isWpfBridgeDisabled())
|
||||||
{
|
{
|
||||||
|
UiaBridge uiabridge = new UiaBridge();
|
||||||
for (String handle : wpfParentList) {
|
for (String handle : wpfParentList) {
|
||||||
Map<String, WindowInfo> wpfInfoList = EnumerateWindowsWithWpfBridge(handle, "WPF");
|
Map<String, WindowInfo> wpfInfoList = EnumerateWindowsWithUiaBridge(uiabridge, handle, "*");
|
||||||
wpfCount += wpfInfoList.size();
|
wpfCount += wpfInfoList.size();
|
||||||
infoList.putAll(wpfInfoList);
|
infoList.putAll(wpfInfoList);
|
||||||
}
|
}
|
||||||
|
for (String handle : winFormParentList) {
|
||||||
|
//System.out.println("winform parent " + handle);
|
||||||
|
Map<String, WindowInfo> winFormInfoList = EnumerateWindowsWithUiaBridge(uiabridge, handle, "*");
|
||||||
|
winFormCount += winFormInfoList.size();
|
||||||
|
infoList.putAll(winFormInfoList);
|
||||||
|
}
|
||||||
for (String handle : silverlightParentList) {
|
for (String handle : silverlightParentList) {
|
||||||
Map<String, WindowInfo> slInfoList = EnumerateWindowsWithWpfBridge(handle, "Silverlight");
|
Map<String, WindowInfo> slInfoList = EnumerateWindowsWithUiaBridge(uiabridge, handle, "Silverlight");
|
||||||
silverlightCount += slInfoList.size();
|
silverlightCount += slInfoList.size();
|
||||||
infoList.putAll(slInfoList);
|
infoList.putAll(slInfoList);
|
||||||
}
|
}
|
||||||
@@ -147,8 +163,13 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
win = doc.createElement("win");
|
win = doc.createElement("win");
|
||||||
else if (w.framework.equals("WPF"))
|
else if (w.framework.equals("WPF"))
|
||||||
win = doc.createElement("wpf");
|
win = doc.createElement("wpf");
|
||||||
|
else if (w.framework.equals("WinForm"))
|
||||||
|
win = doc.createElement("winfrm");
|
||||||
else if (w.framework.equals("Silverlight"))
|
else if (w.framework.equals("Silverlight"))
|
||||||
win = doc.createElement("silver");
|
win = doc.createElement("silver");
|
||||||
|
else
|
||||||
|
win = doc.createElement("win");
|
||||||
|
//System.out.println(w.toString());
|
||||||
|
|
||||||
win.setAttribute("hwnd", w.hwndStr);
|
win.setAttribute("hwnd", w.hwndStr);
|
||||||
win.setAttribute("text", w.text);
|
win.setAttribute("text", w.text);
|
||||||
@@ -159,6 +180,9 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
win.setAttribute("class", w.className);
|
win.setAttribute("class", w.className);
|
||||||
if (w.className != null)
|
if (w.className != null)
|
||||||
win.setAttribute("CLASS", w.className.toUpperCase());
|
win.setAttribute("CLASS", w.className.toUpperCase());
|
||||||
|
if (w.controlType != null)
|
||||||
|
if (!w.controlType.isEmpty())
|
||||||
|
win.setAttribute("type", w.controlType);
|
||||||
if (!w.isChild) {
|
if (!w.isChild) {
|
||||||
parentCount++;
|
parentCount++;
|
||||||
if (w.processName != null && !w.processName.isEmpty()) {
|
if (w.processName != null && !w.processName.isEmpty()) {
|
||||||
@@ -207,6 +231,7 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
totals.setAttribute("windowCount", infoList.size()+"");
|
totals.setAttribute("windowCount", infoList.size()+"");
|
||||||
totals.setAttribute("wpfWrapperCount", wpfParentList.size()+"");
|
totals.setAttribute("wpfWrapperCount", wpfParentList.size()+"");
|
||||||
totals.setAttribute("wpfCount", wpfCount+"");
|
totals.setAttribute("wpfCount", wpfCount+"");
|
||||||
|
totals.setAttribute("winFormCount", winFormCount+"");
|
||||||
totals.setAttribute("silverlightCount", silverlightCount+"");
|
totals.setAttribute("silverlightCount", silverlightCount+"");
|
||||||
totals.setAttribute("menuCount", menuCount+"");
|
totals.setAttribute("menuCount", menuCount+"");
|
||||||
totals.setAttribute("processCount", processList.size()+"");
|
totals.setAttribute("processCount", processList.size()+"");
|
||||||
@@ -242,22 +267,19 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
return xmlElement;
|
return xmlElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, WindowInfo> EnumerateWindowsWithWpfBridge(String parentHwndStr, String frameworkType) {
|
public static Map<String, WindowInfo> EnumerateWindowsWithUiaBridge(UiaBridge uiabridge, String parentHwndStr, String frameworkType) {
|
||||||
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
|
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
|
||||||
WpfBridge wb = new WpfBridge();
|
//WpfBridge wb = new WpfBridge();
|
||||||
wb.setFrameworkId(frameworkType);
|
//wpf.setFrameworkId(frameworkType);
|
||||||
if (SynthuseDlg.config.isFilterWpfDisabled())
|
|
||||||
wb.setTouchableOnly(false);
|
|
||||||
long hwnd = Long.parseLong(parentHwndStr);
|
long hwnd = Long.parseLong(parentHwndStr);
|
||||||
//List<String> parentIds = new ArrayList<String>(Arrays.asList(wb.enumChildrenWindowIds("")));
|
//System.out.println("getRuntimeIdFromHandle of " + hwnd);
|
||||||
//System.out.println("getRuntimeIdFromHandle");
|
String parentRuntimeId = uiabridge.getWindowInfo((int) hwnd, WindowInfo.UIA_RUNTIME_ID);
|
||||||
String parentRuntimeId = wb.getRuntimeIdFromHandle(hwnd);
|
|
||||||
//System.out.println("runtimeId=" + runtimeId);
|
//System.out.println("runtimeId=" + runtimeId);
|
||||||
String[] allIds = null;
|
String[] allIds = null;
|
||||||
if (SynthuseDlg.config.isFilterWpfDisabled())
|
if (SynthuseDlg.config.isFilterWpfDisabled())
|
||||||
allIds = wb.enumDescendantWindowInfo(parentRuntimeId, "*");
|
allIds = uiabridge.enumWindowInfo((int) hwnd, "*");
|
||||||
else
|
else
|
||||||
allIds = wb.enumDescendantWindowInfo(parentRuntimeId, WindowInfo.WPF_PROPERTY_LIST);
|
allIds = uiabridge.enumWindowInfo((int) hwnd, WindowInfo.UIA_PROPERTY_LIST);
|
||||||
if (allIds == null)
|
if (allIds == null)
|
||||||
return infoList; //empty list
|
return infoList; //empty list
|
||||||
//System.out.println("enumDescendantWindowIds " + allIds.length);
|
//System.out.println("enumDescendantWindowIds " + allIds.length);
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ import com.sun.jna.platform.win32.WinDef.HWND;
|
|||||||
public class XpathManager implements Runnable{
|
public class XpathManager implements Runnable{
|
||||||
|
|
||||||
private HWND hwnd = null;
|
private HWND hwnd = null;
|
||||||
private String runtimeId = null;
|
private String enumProperties = null;
|
||||||
private JTextPane windowsXmlTextPane = null;
|
private JTextPane windowsXmlTextPane = null;
|
||||||
private WpfBridge wpf = null;
|
|
||||||
|
|
||||||
public static interface Events {
|
public static interface Events {
|
||||||
void statusChanged(String status);
|
void statusChanged(String status);
|
||||||
@@ -44,12 +43,11 @@ public class XpathManager implements Runnable{
|
|||||||
this.windowsXmlTextPane = windowsXmlTextPane;
|
this.windowsXmlTextPane = windowsXmlTextPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
public XpathManager(HWND hwnd, String runtimeId, JTextPane windowsXmlTextPane, Events events) {
|
public XpathManager(HWND hwnd, String enumProperties, JTextPane windowsXmlTextPane, Events events) {
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.hwnd = hwnd;
|
this.hwnd = hwnd;
|
||||||
this.runtimeId = runtimeId;
|
this.enumProperties = enumProperties;
|
||||||
this.windowsXmlTextPane = windowsXmlTextPane;
|
this.windowsXmlTextPane = windowsXmlTextPane;
|
||||||
this.wpf = new WpfBridge();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -78,44 +76,46 @@ public class XpathManager implements Runnable{
|
|||||||
return escapedTxtStr;
|
return escapedTxtStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String buildWpfXpathStatement() {
|
public String buildUiaXpathStatement() {
|
||||||
|
if (enumProperties == null)
|
||||||
|
return "";
|
||||||
|
if (enumProperties.isEmpty())
|
||||||
|
return "";
|
||||||
String builtXpath = "";
|
String builtXpath = "";
|
||||||
String xml = this.windowsXmlTextPane.getText();
|
String xml = this.windowsXmlTextPane.getText();
|
||||||
String classStr = wpf.getWindowClass(runtimeId);
|
|
||||||
//System.out.println("class: " + classStr);
|
WindowInfo wi = new WindowInfo(enumProperties, true);
|
||||||
String txtOrig = wpf.getWindowText(runtimeId);
|
String onlyRuntimeIdXpath = "//*[@hwnd='" + wi.runtimeId + "']";
|
||||||
String winValueOrig = wpf.getWindowValue(runtimeId);
|
List<String> wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, onlyRuntimeIdXpath);
|
||||||
if (classStr == null || txtOrig == null)
|
//System.out.println("evaluateXpathGetValues1: " + onlyRuntimeIdXpath + " = " + wpfResultList.size());
|
||||||
|
if (wpfResultList.size() == 0)
|
||||||
|
return"";
|
||||||
|
//System.out.println("enumProperties: " + enumProperties);
|
||||||
|
String typeStr = wi.controlType;
|
||||||
|
String txtOrig = wi.text;
|
||||||
|
//String winValueOrig = wpf.getWindowValue(runtimeId);
|
||||||
|
if (typeStr == null || txtOrig == null)
|
||||||
return "";
|
return "";
|
||||||
//System.out.println("text: " + txtOrig);
|
//System.out.println("text: " + txtOrig);
|
||||||
String txtStr = compareLongTextString(txtOrig);
|
String txtStr = compareLongTextString(txtOrig);
|
||||||
|
|
||||||
String valueStr = "";
|
builtXpath = "//*[@type='" + typeStr + "' and starts-with(@text,'" + txtStr + "')" + "]";
|
||||||
if (winValueOrig != null)
|
|
||||||
if (!winValueOrig.isEmpty()) //if value attribute exists then use it too
|
|
||||||
valueStr = " and starts-with(@value,'" + compareLongTextString(winValueOrig) + "')";
|
|
||||||
|
|
||||||
builtXpath = "//*[@class='" + classStr + "' and starts-with(@text,'" + txtStr + "')" + valueStr + "]";
|
|
||||||
|
|
||||||
//builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
//builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
||||||
//System.out.println("evaluateXpathGetValues: " + builtXpath);
|
wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
||||||
List<String> wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
//System.out.println("evaluateXpathGetValues2: " + builtXpath + " = " + wpfResultList.size());
|
||||||
if (wpfResultList.size() == 1)
|
if (wpfResultList.size() == 1)
|
||||||
return builtXpath;
|
return builtXpath;
|
||||||
builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
return onlyRuntimeIdXpath;
|
||||||
wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
|
||||||
if (wpfResultList.size() > 0)
|
|
||||||
return builtXpath;
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String buildXpathStatement() {
|
public String buildXpathStatement() {
|
||||||
String builtXpath = "";
|
String builtXpath = "";
|
||||||
try {
|
try {
|
||||||
String xml = this.windowsXmlTextPane.getText();
|
String xml = this.windowsXmlTextPane.getText();
|
||||||
if (runtimeId != null && !SynthuseDlg.config.isWpfBridgeDisabled()) {
|
if (enumProperties != null && !SynthuseDlg.config.isWpfBridgeDisabled()) {
|
||||||
if (!runtimeId.isEmpty()) {
|
if (!enumProperties.isEmpty()) {
|
||||||
builtXpath = buildWpfXpathStatement();
|
builtXpath = buildUiaXpathStatement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (builtXpath != "")
|
if (builtXpath != "")
|
||||||
@@ -164,6 +164,9 @@ public class XpathManager implements Runnable{
|
|||||||
}
|
}
|
||||||
builtXpath = "//win[@class='" + classStr + "'" + txtStr + "]";
|
builtXpath = "//win[@class='" + classStr + "'" + txtStr + "]";
|
||||||
}
|
}
|
||||||
|
resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
||||||
|
if (resultList.size() > 1) //still too many matched, only use hwnd
|
||||||
|
builtXpath = "//win[@hwnd='" + handleStr + "']";
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class BaseCommand {
|
|||||||
static long LAST_UPDATED_XML = 0;
|
static long LAST_UPDATED_XML = 0;
|
||||||
|
|
||||||
protected Api api = new Api();
|
protected Api api = new Api();
|
||||||
protected WpfBridge wpf = new WpfBridge();
|
protected UiaBridge wpf = new UiaBridge();
|
||||||
protected CommandProcessor parentProcessor = null;
|
protected CommandProcessor parentProcessor = null;
|
||||||
|
|
||||||
protected int getExecuteErrorCount() {
|
protected int getExecuteErrorCount() {
|
||||||
@@ -116,6 +116,7 @@ public class BaseCommand {
|
|||||||
resultStr = item;
|
resultStr = item;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
resultStr = resultStr.replaceAll("[^\\d-.]", ""); //remove all non-numeric values (except dash -)
|
||||||
if (WinPtr.isWpfRuntimeIdFormat(resultStr)) {
|
if (WinPtr.isWpfRuntimeIdFormat(resultStr)) {
|
||||||
result.runtimeId = resultStr;
|
result.runtimeId = resultStr;
|
||||||
if (!ignoreFailedFind && result.isEmpty())
|
if (!ignoreFailedFind && result.isEmpty())
|
||||||
@@ -143,7 +144,7 @@ public class BaseCommand {
|
|||||||
if (item.contains("hmenu=")) {
|
if (item.contains("hmenu=")) {
|
||||||
List<String> list = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@id");
|
List<String> list = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@id");
|
||||||
if (list.size() > 0)
|
if (list.size() > 0)
|
||||||
resultStr = list.get(0); //get first id;
|
resultStr = list.get(0); //get first id
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
resultStr = item;
|
resultStr = item;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class UnitTestHelper {
|
|||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int readBytes;
|
int readBytes;
|
||||||
// Open and check input stream
|
// Open and check input stream
|
||||||
InputStream is = WpfBridgeTest.class.getResourceAsStream(path);
|
InputStream is = UnitTestHelper.class.getResourceAsStream(path);
|
||||||
if (is == null) { //check if valid
|
if (is == null) { //check if valid
|
||||||
System.out.println("File " + path + " was not found inside JAR.");
|
System.out.println("File " + path + " was not found inside JAR.");
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
package org.synthuse.test;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.synthuse.*;
|
|
||||||
|
|
||||||
public class WpfBridgeTest {
|
|
||||||
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void setUpBeforeClass() {
|
|
||||||
//this runs only once for this class
|
|
||||||
UnitTestHelper.RunApp("/org/synthuse/test/WpfMockTestApp.exe");
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void tearDownAfterClass() {
|
|
||||||
//this runs only once for this class
|
|
||||||
UnitTestHelper.DestroyApp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void countChildrenWin32() {
|
|
||||||
WpfBridge wb = new WpfBridge();
|
|
||||||
wb.setFrameworkId("Win32");//We should find some Win32 windows, maybe not WPF
|
|
||||||
int win32Cnt = wb.countChildrenWindows();
|
|
||||||
System.out.println("win32 countChildrenWindows: " + win32Cnt);
|
|
||||||
assertTrue(win32Cnt > 0);
|
|
||||||
wb.setTouchableOnly(false);//disable filter
|
|
||||||
int ufwin32Cnt = wb.countChildrenWindows();
|
|
||||||
System.out.println("win32 unfiltered countChildrenWindows: " + ufwin32Cnt);
|
|
||||||
assertTrue(ufwin32Cnt >= win32Cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void countChildrenWpf() {
|
|
||||||
WpfBridge wb = new WpfBridge();
|
|
||||||
wb.setFrameworkId("WPF");// maybe not WPF
|
|
||||||
wb.setTouchableOnly(true);//enable filter
|
|
||||||
System.out.println("wpf countChildrenWindows: " + wb.countChildrenWindows());
|
|
||||||
wb.setTouchableOnly(false);//disable filter
|
|
||||||
System.out.println("wpf unfiltered countChildrenWindows: " + wb.countChildrenWindows());
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Test
|
|
||||||
public void countDescendantsWin32() {
|
|
||||||
WpfBridge wb = new WpfBridge();
|
|
||||||
wb.setFrameworkId("Win32");//We should find some Win32 windows, maybe not WPF
|
|
||||||
int win32Cnt = wb.countDescendantWindows();
|
|
||||||
System.out.println("win32 countDescendantWindows: " + win32Cnt);
|
|
||||||
assertTrue(win32Cnt > 0);
|
|
||||||
wb.setTouchableOnly(false);//disable filter
|
|
||||||
int ufwin32Cnt = wb.countDescendantWindows();
|
|
||||||
System.out.println("win32 unfiltered countDescendantWindows: " + ufwin32Cnt);
|
|
||||||
assertTrue(ufwin32Cnt >= win32Cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Test
|
|
||||||
public void countDescendantsWpf() {
|
|
||||||
WpfBridge wb = new WpfBridge();
|
|
||||||
wb.setFrameworkId("WPF");// maybe not WPF
|
|
||||||
wb.setTouchableOnly(true);//enable filter
|
|
||||||
System.out.println("wpf countDescendantWindows: " + wb.countDescendantWindows());
|
|
||||||
wb.setTouchableOnly(false);//disable filter
|
|
||||||
System.out.println("wpf unfiltered countDescendantWindows: " + wb.countDescendantWindows());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRuntimeFromHandle() {
|
|
||||||
WpfBridge wb = new WpfBridge();
|
|
||||||
Api api = new Api();
|
|
||||||
wb.setFrameworkId("WPF");
|
|
||||||
WinPtr wp = new WinPtr(api.user32.FindWindow(null, "MainWindow"));//find WpfMockTestApp.exe
|
|
||||||
long handle = Long.parseLong(wp.hWndStr);
|
|
||||||
if (handle == 0)
|
|
||||||
return;
|
|
||||||
System.out.println("calling getRuntimeIdFromHandle: " + handle);
|
|
||||||
String rid = wb.getRuntimeIdFromHandle(handle);
|
|
||||||
System.out.println(wp.hWndStr + " getRuntimeIdFromHandle: " + rid);
|
|
||||||
assertTrue(rid != null);
|
|
||||||
|
|
||||||
String[] props = wb.getPropertiesAndValues(rid);
|
|
||||||
assertTrue(props != null);
|
|
||||||
|
|
||||||
//for(String p : props)
|
|
||||||
// System.out.println(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void enumerateWindowInfo() {
|
|
||||||
WpfBridge wb = new WpfBridge();
|
|
||||||
Api api = new Api();
|
|
||||||
wb.setFrameworkId("WPF");
|
|
||||||
wb.setTouchableOnly(false);
|
|
||||||
WinPtr wp = new WinPtr(api.user32.FindWindow(null, "MainWindow"));//find WpfMockTestApp.exe
|
|
||||||
long handle = Long.parseLong(wp.hWndStr);
|
|
||||||
if (handle == 0)
|
|
||||||
return;
|
|
||||||
String rid = wb.getRuntimeIdFromHandle(handle);
|
|
||||||
System.out.println(wp.hWndStr + " getRuntimeIdFromHandle: " + rid);
|
|
||||||
if (rid == null)
|
|
||||||
return;
|
|
||||||
String[] wInfo = wb.enumDescendantWindowInfo(rid, WindowInfo.WPF_PROPERTY_LIST);
|
|
||||||
System.out.println("enumDescendantWindowInfo length: " + wInfo.length);
|
|
||||||
System.out.println(WindowInfo.WPF_PROPERTY_LIST);
|
|
||||||
for(String w : wInfo)
|
|
||||||
System.out.println(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
#Tue Apr 08 22:36:47 EDT 2014
|
#Tue Apr 29 23:17:11 EDT 2014
|
||||||
DEFAULT_PROP_FILENAME=
|
DEFAULT_PROP_FILENAME=
|
||||||
urlList=
|
urlList=
|
||||||
disableFiltersWpf=false
|
disableFiltersWpf=false
|
||||||
xpathList=
|
xpathList=//*[@class\='TextBlock' and starts-with(@text,'CheckBox is here')]\u00BA//win[@class\='HwndWrapper[WpfMockTestApp.exe;;e0e45a66-6643-4c32-a6b8-6313b79ee700]']\u00BA//win[starts-with(@class,'HwndWrapper[WpfMockTestApp.exe;;')]\u00BA//win[starts-with(@class,'HwndWrapper[WpfMockTestApp.exe;;' and @TEXT\="MAINWINDOW")]\u00BA//win[starts-with(@class,'HwndWrapper[WpfMockTestApp.exe;;' and @TEXT\='MAINWINDOW')]\u00BA//win[starts-with(@class,'HwndWrapper[WpfMockTestApp.exe;;') and @TEXT\='MAINWINDOW']\u00BA//win[@class\='HwndWrapper[WpfMockTestApp.exe;;7c11a88a-1622-4ec8-8a29-0d7f20d3f36d]']\u00BA//win[@class\='HwndWrapper']\u00BA//win[starts-with(@class,'HwndWrapper')]\u00BA//wpf\u00BA//*[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1' and starts-with(@text,'')]\u00BA//*[@ListViewCount]\u00BA//*[@menuCount]\u00BA//*[@dgText]\u00BA//menus\u00BA//menu\u00BA//win[@class\='SunAwtFrame']\u00BA//win[@class\='Edit']\u00BA//win[@class\='Notepad']\u00BA//*[@class\='\#32768']\u00BA//menu[@text\='Help']\u00BA//win[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1']/win[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1'][2]\u00BA//*[@tbCount]\u00BA//win[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1']/win[@class\='WindowsForms10.EDIT.app.0.2bf8098_r13_ad1']\u00BA//*[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1' and starts-with(@text,'Form1')]\u00BA//*[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1' and starts-with(@text,'Win Forms Mock Test ')]\u00BA//*[@class\='' and starts-with(@text,'toolStripButton1')]\u00BA//win[@class\='3147770']\u00BA//*[@hwnd\='52298946']\u00BA//*[@hwnd\='14222438']\u00BA//*[@hwnd\='9175840']\u00BA//*[@hwnd\='6751400']\u00BA//*[starts-with(@class,'WindowsForms')]\u00BA//win[starts-with(@class,'WindowsForms')]\u00BA/*/win[starts-with(@class,'WindowsForms')]\u00BA//winfrm\u00BA//win[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1']/win[@class\='WindowsForms10.EDIT.app.0.2bf8098_r13_ad1'][2]\u00BA//*[@class\='WindowsForms10.Window.8.app.0.2bf8098_r13_ad1']/win[@class\='WindowsForms10.EDIT.app.0.2bf8098_r13_ad1']\u00BA//*[@type\='button' and starts-with(@text,'button1')]\u00BA
|
||||||
xpathHightlight=.*process\="([^"]*)".*
|
|
||||||
disableWpf=false
|
disableWpf=false
|
||||||
|
xpathHightlight=.*process\="([^"]*)".*
|
||||||
|
|||||||
Reference in New Issue
Block a user