WPF and regular Win32 windows are now supported

Added support for dragging target on WPF windows and building simple
xpath statements.  Fixed some null results in native library and
increased performance of enumerating wpf windows.  Still need to tweak
filters for picking up Silverlight handles too.
This commit is contained in:
Edward Jakubowski
2014-04-07 22:19:47 -04:00
parent 1809e2ad55
commit bc3c070ea8
20 changed files with 500 additions and 157 deletions

View File

@@ -37,7 +37,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.0.*")]; [assembly:AssemblyVersionAttribute("1.1.*")];
[assembly:ComVisible(false)]; [assembly:ComVisible(false)];

View File

@@ -13,6 +13,7 @@ using namespace System::Windows::Automation;
WpfAutomation::WpfAutomation(void) WpfAutomation::WpfAutomation(void)
{ {
this->frameworkId = WpfAutomation::DEFAULT_FRAMEWORK; this->frameworkId = WpfAutomation::DEFAULT_FRAMEWORK;
this->touchableOnly = true;
} }
void WpfAutomation::setFrameworkId(System::String ^propertyValue) void WpfAutomation::setFrameworkId(System::String ^propertyValue)
@@ -20,6 +21,21 @@ void WpfAutomation::setFrameworkId(System::String ^propertyValue)
this->frameworkId = 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 = gcnew array<System::Windows::Automation::Condition ^>(3);
cons[0] = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);//is WPF framework
cons[1] = gcnew PropertyCondition(AutomationElement::IsEnabledProperty, this->touchableOnly);//is enabled
cons[2] = gcnew PropertyCondition(AutomationElement::IsOffscreenProperty, !this->touchableOnly);// is off screen
System::Windows::Automation::Condition ^result = gcnew System::Windows::Automation::AndCondition(cons);
return result;
}
array<System::Int32> ^ WpfAutomation::convertRuntimeIdString(System::String ^runtimeIdValue) array<System::Int32> ^ WpfAutomation::convertRuntimeIdString(System::String ^runtimeIdValue)
{ {
System::String ^delim = L"-"; System::String ^delim = L"-";
@@ -37,9 +53,9 @@ AutomationElement ^ WpfAutomation::findAutomationElementById(System::String ^run
if (runtimeIdValue == nullptr || runtimeIdValue->Equals(L"")) if (runtimeIdValue == nullptr || runtimeIdValue->Equals(L""))
return AutomationElement::RootElement; return AutomationElement::RootElement;
array<System::Int32> ^idArray = this->convertRuntimeIdString(runtimeIdValue); array<System::Int32> ^idArray = this->convertRuntimeIdString(runtimeIdValue);
Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId); //Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);
Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray); Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray);
Condition ^frameworkAndRuntimeId = gcnew AndCondition(pcFramework, pcRunId); Condition ^frameworkAndRuntimeId = gcnew AndCondition(getSearchConditions(), pcRunId);
return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndRuntimeId); return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndRuntimeId);
} }
@@ -76,7 +92,9 @@ System::String ^ WpfAutomation::getRuntimeIdFromElement(System::Windows::Automat
System::Int32 WpfAutomation::countDescendantWindows() System::Int32 WpfAutomation::countDescendantWindows()
{ {
//AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition); //AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition);
AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count; System::Int32 result = aec->Count;
//delete aec; //delete aec;
return result; return result;
@@ -85,7 +103,9 @@ System::Int32 WpfAutomation::countDescendantWindows()
System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdValue) System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count; System::Int32 result = aec->Count;
//delete aec; //delete aec;
//delete frameworkAndRuntimeId; //delete frameworkAndRuntimeId;
@@ -95,7 +115,9 @@ System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdVal
System::Int32 WpfAutomation::countChildrenWindows() System::Int32 WpfAutomation::countChildrenWindows()
{ {
//AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition); //AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition);
AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Children, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count; System::Int32 result = aec->Count;
//delete aec; //delete aec;
return result; return result;
@@ -104,7 +126,9 @@ System::Int32 WpfAutomation::countChildrenWindows()
System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue) System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count; System::Int32 result = aec->Count;
//delete aec; //delete aec;
//delete frameworkAndRuntimeId; //delete frameworkAndRuntimeId;
@@ -114,14 +138,18 @@ System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue
array<System::String ^> ^ WpfAutomation::enumChildrenWindowIds(System::String ^runtimeIdValue) array<System::String ^> ^ WpfAutomation::enumChildrenWindowIds(System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, getSearchConditions());
if (aec == nullptr)
return nullptr;
return getRuntimeIdsFromCollection(aec); return getRuntimeIdsFromCollection(aec);
} }
array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::String ^runtimeIdValue) array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return nullptr;
return getRuntimeIdsFromCollection(aec); return getRuntimeIdsFromCollection(aec);
} }
@@ -131,22 +159,27 @@ array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::Int32 p
gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId), gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId),
gcnew PropertyCondition(AutomationElement::ProcessIdProperty, processId)); gcnew PropertyCondition(AutomationElement::ProcessIdProperty, processId));
AutomationElement ^parent = AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndProcessId); AutomationElement ^parent = AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndProcessId);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return nullptr;
return getRuntimeIdsFromCollection(aec); return getRuntimeIdsFromCollection(aec);
} }
array<System::String ^> ^ WpfAutomation::EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle) System::String ^ WpfAutomation::getRuntimeIdFromHandle(System::IntPtr windowHandle)
{ {
//AutomationElement test = AutomationElement.FromHandle(new System.IntPtr(123123)); //AutomationElement test = AutomationElement.FromHandle(new System.IntPtr(123123));
AutomationElement ^parent = AutomationElement::FromHandle(windowHandle); AutomationElement ^target = AutomationElement::FromHandle(windowHandle);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); if (target == nullptr)
return getRuntimeIdsFromCollection(aec); return nullptr;
return getRuntimeIdFromElement(target);
} }
array<System::String ^> ^ WpfAutomation::EnumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties) array<System::String ^> ^ WpfAutomation::enumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); if (parent == nullptr)
return nullptr;
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
//create array for keeping order of properties //create array for keeping order of properties
System::String ^delim = L","; System::String ^delim = L",";
@@ -213,9 +246,19 @@ array<System::String ^> ^ WpfAutomation::EnumDescendantWindowInfo(System::String
return winInfoList; 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) System::String ^ WpfAutomation::getParentRuntimeId(System::String ^runtimeIdValue)
{ {
AutomationElement ^target = findAutomationElementById(runtimeIdValue); AutomationElement ^target = findAutomationElementById(runtimeIdValue);
if (target == nullptr)
return nullptr;
TreeWalker ^tw = TreeWalker::ControlViewWalker; TreeWalker ^tw = TreeWalker::ControlViewWalker;
AutomationElement ^parent = tw->GetParent(target); AutomationElement ^parent = tw->GetParent(target);
return getRuntimeIdFromElement(parent); return getRuntimeIdFromElement(parent);
@@ -224,6 +267,8 @@ System::String ^ WpfAutomation::getParentRuntimeId(System::String ^runtimeIdValu
System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System::String ^runtimeIdValue) System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
if (parent == nullptr)
return nullptr;
//System::Object ^currentVal = parent->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty); //System::Object ^currentVal = parent->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
array<AutomationProperty^> ^aps = parent->GetSupportedProperties(); array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
for each(AutomationProperty ^ap in aps) for each(AutomationProperty ^ap in aps)
@@ -238,9 +283,12 @@ System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System
return nullptr; return nullptr;
} }
array<System::String ^> ^ WpfAutomation::getProperties(System::String ^runtimeIdValue) array<System::String ^> ^ WpfAutomation::getProperties(System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
if (parent == nullptr)
return nullptr;
array<AutomationProperty^> ^aps = parent->GetSupportedProperties(); array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length); array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length);
System::Int32 count = 0; System::Int32 count = 0;
@@ -258,6 +306,8 @@ array<System::String ^> ^ WpfAutomation::getProperties(System::String ^runtimeId
array<System::String ^> ^ WpfAutomation::getPropertiesAndValues(System::String ^runtimeIdValue) array<System::String ^> ^ WpfAutomation::getPropertiesAndValues(System::String ^runtimeIdValue)
{ {
AutomationElement ^parent = findAutomationElementById(runtimeIdValue); AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
if (parent == nullptr)
return nullptr;
array<AutomationProperty^> ^aps = parent->GetSupportedProperties(); array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length); array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length);
System::Int32 count = 0; System::Int32 count = 0;

View File

@@ -11,6 +11,7 @@ public ref class WpfAutomation
public: public:
WpfAutomation(void); WpfAutomation(void);
void setFrameworkId(System::String ^propertyValue); //default is WPF, but also accepts Silverlight, Win32 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 //Descendants will walk the full tree of windows, NOT just one level of children
System::Int32 countDescendantWindows(); System::Int32 countDescendantWindows();
@@ -22,11 +23,11 @@ public:
array<System::String ^> ^ enumChildrenWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop 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::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop
array<System::String ^> ^ enumDescendantWindowIds(System::Int32 processId); array<System::String ^> ^ enumDescendantWindowIds(System::Int32 processId);
array<System::String ^> ^ EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle);
//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.
array<System::String ^> ^ EnumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties); 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 ^ getParentRuntimeId(System::String ^runtimeIdValue);
System::String ^ getProperty(System::String ^propertyName, System::String ^runtimeIdValue); System::String ^ getProperty(System::String ^propertyName, System::String ^runtimeIdValue);
array<System::String ^> ^ getProperties(System::String ^runtimeIdValue); array<System::String ^> ^ getProperties(System::String ^runtimeIdValue);
@@ -36,8 +37,11 @@ private:
System::Windows::Automation::AutomationElement ^ findAutomationElementById(System::String ^runtimeIdValue); System::Windows::Automation::AutomationElement ^ findAutomationElementById(System::String ^runtimeIdValue);
System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element); System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element);
array<System::String ^> ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection); array<System::String ^> ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection);
System::Windows::Automation::Condition ^ getSearchConditions();
static System::String ^DEFAULT_FRAMEWORK = L"WPF"; static System::String ^DEFAULT_FRAMEWORK = L"WPF";
static System::Boolean ^DEFAULT_TOUCHABLE = true;
System::String ^frameworkId; System::String ^frameworkId;
System::Boolean ^touchableOnly;
}; };

View File

@@ -148,6 +148,7 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(Targ
<Reference Include="UIAutomationClient" /> <Reference Include="UIAutomationClient" />
<Reference Include="UIAutomationProvider" /> <Reference Include="UIAutomationProvider" />
<Reference Include="UIAutomationTypes" /> <Reference Include="UIAutomationTypes" />
<Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Global.h" /> <ClInclude Include="Global.h" />

Binary file not shown.

Binary file not shown.

View File

@@ -22,6 +22,16 @@ JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId(JNIEnv *env, j
env->ReleaseStringUTFChars(jpropertyValue, propertyValue); //release string 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 * Class: org_synthuse_WpfBridge
* Method: CountDescendantWindows * Method: CountDescendantWindows
@@ -80,7 +90,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds
{ {
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumChildrenWindowIds(marshal_as<String ^>(runtimeIdValue)); 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 //create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String"); jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
@@ -107,7 +118,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
{ {
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds(marshal_as<String ^>(runtimeIdValue)); 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 //create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String"); jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
@@ -133,7 +145,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J(JNIEnv *env, jobject obj, jlong jprocessId) 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); 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 //create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String"); jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
@@ -148,22 +161,17 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
/* /*
* Class: org_synthuse_WpfBridge * Class: org_synthuse_WpfBridge
* Method: EnumDescendantWindowIdsFromHandle * Method: getRuntimeIdFromHandle
* Signature: (J)[Ljava/lang/String; * Signature: (J)Ljava/lang/String;
*/ */
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIdsFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle) JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle)
{ {
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->EnumDescendantWindowIdsFromHandle(System::IntPtr(jwindowHandle)); System::String ^mrunId = Global::WPF_AUTO->getRuntimeIdFromHandle(System::IntPtr(jwindowHandle));
if (mrunId == nullptr)
//create result object array to the same size as the managed children Ids string array return NULL;
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 marshal_context context; //lets you marshal managed classes to unmanaged types
for(int i = 0 ; i < mchildrenIds->Length ; i++) jstring result = env->NewStringUTF(context.marshal_as<const char *>(mrunId));
{ return result;
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
}
return results;
} }
/* /*
@@ -175,7 +183,9 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
{ {
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
const char *properties = env->GetStringUTFChars(jproperties, 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)); 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 //create result object array to the same size as the managed window info string array
jclass stringClass = env->FindClass("java/lang/String"); jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0); jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
@@ -190,6 +200,21 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
} }
/*
* 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 * Class: org_synthuse_WpfBridge
* Method: getParentRuntimeId * Method: getParentRuntimeId
@@ -199,6 +224,8 @@ JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getParentRuntimeId(JNIEnv
{ {
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
System::String ^mresult = Global::WPF_AUTO->getParentRuntimeId(marshal_as<String ^>(runtimeIdValue)); 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 marshal_context context; //lets you marshal managed classes to unmanaged types
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult)); jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
@@ -215,6 +242,8 @@ JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getProperty(JNIEnv *env, j
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
const char *propertyName = env->GetStringUTFChars(jpropertyName, 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)); 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 marshal_context context; //lets you marshal managed classes to unmanaged types
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult)); jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
env->ReleaseStringUTFChars(jpropertyName, propertyName); //release string env->ReleaseStringUTFChars(jpropertyName, propertyName); //release string
@@ -232,7 +261,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getProperties(JNIEnv
{ {
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mprops = Global::WPF_AUTO->getProperties(marshal_as<String ^>(runtimeIdValue)); 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 //create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String"); jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0); jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0);
@@ -255,7 +285,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getPropertiesAndValue
{ {
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mprops = Global::WPF_AUTO->getPropertiesAndValues(marshal_as<String ^>(runtimeIdValue)); 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 //create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String"); jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0); jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0);

View File

@@ -15,6 +15,14 @@ extern "C" {
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId
(JNIEnv *, jobject, jstring); (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 * Class: org_synthuse_WpfBridge
* Method: countDescendantWindows * Method: countDescendantWindows
@@ -71,14 +79,6 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J
(JNIEnv *, jobject, jlong); (JNIEnv *, jobject, jlong);
/*
* Class: org_synthuse_WpfBridge
* Method: enumDescendantWindowIdsFromHandle
* Signature: (J)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIdsFromHandle
(JNIEnv *, jobject, jlong);
/* /*
* Class: org_synthuse_WpfBridge * Class: org_synthuse_WpfBridge
* Method: enumDescendantWindowInfo * Method: enumDescendantWindowInfo
@@ -87,6 +87,22 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowI
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo
(JNIEnv *, jobject, jstring, jstring); (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 * Class: org_synthuse_WpfBridge
* Method: getParentRuntimeId * Method: getParentRuntimeId

View File

@@ -129,6 +129,7 @@ public class Api {
boolean EnumChildWindows(HWND hWnd, WNDENUMPROC lpEnumFunc, Pointer data); boolean EnumChildWindows(HWND hWnd, WNDENUMPROC lpEnumFunc, Pointer data);
HWND GetParent(HWND hWnd); HWND GetParent(HWND hWnd);
boolean IsWindowVisible(HWND hWnd); boolean IsWindowVisible(HWND hWnd);
boolean IsWindow(HWND hWnd);
int GetWindowRect(HWND hWnd, RECT r); int GetWindowRect(HWND hWnd, RECT r);
int MapWindowPoints(HWND hWndFrom, HWND hWndTo, RECT r, int cPoints); int MapWindowPoints(HWND hWndFrom, HWND hWndTo, RECT r, int cPoints);

View File

@@ -25,4 +25,9 @@ public class Config extends PropertiesSerializer {
super(propertyFilename); super(propertyFilename);
load(propertyFilename); load(propertyFilename);
} }
public boolean isWpfBridgeDisabled()
{
return disableWpf.equals("true") || disableWpf.equals("True");
}
} }

View File

@@ -95,12 +95,14 @@ public class SynthuseDlg extends JFrame {
public static Config config = new Config(Config.DEFAULT_PROP_FILENAME); public static Config config = new Config(Config.DEFAULT_PROP_FILENAME);
private String dialogResult = ""; private String dialogResult = "";
private String lastDragHwnd = ""; private String lastDragHwnd = "";
private String lastRuntimeId ="";
private JComboBox<String> cmbXpath; private JComboBox<String> cmbXpath;
private JButton btnTestIde; private JButton btnTestIde;
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();
/** /**
* Launch the application. * Launch the application.
@@ -423,16 +425,17 @@ 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);
lblStatus.setText("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)) { if (!lastDragHwnd.equals(handleStr) || !lastRuntimeId.equals(runtimeId)) {
if (!lastDragHwnd.isEmpty()) { if (!lastDragHwnd.isEmpty()) {
Api.refreshWindow(Api.GetHandleFromString(lastDragHwnd)); Api.refreshWindow(Api.GetHandleFromString(lastDragHwnd));
} }
lastDragHwnd = handleStr; lastDragHwnd = handleStr;
lastRuntimeId = runtimeId;
//lastDragHwnd = (hwnd + ""); //lastDragHwnd = (hwnd + "");
Api.highlightWindow(hwnd); Api.highlightWindow(hwnd);
XpathManager.buildXpathStatementThreaded(hwnd, textPane, xpathEvents); XpathManager.buildXpathStatementThreaded(hwnd, runtimeId, textPane, xpathEvents);
} }
} }
} }

View File

@@ -0,0 +1,52 @@
package org.synthuse;
import com.sun.jna.platform.win32.WinDef.HWND;
public class WinPtr {
public HWND hWnd = null;
public String hWndStr = "";
public String runtimeId = "";
public WinPtr() {
}
public WinPtr(HWND hWnd) {
this.hWnd = hWnd;
this.hWndStr = Api.GetHandleAsString(hWnd);
}
public WinPtr(String runtimeId) {
this.runtimeId = runtimeId;
}
public boolean isWin32() {
return (hWnd != null || !hWndStr.equals(""));
}
public boolean isWpf() {
return (!runtimeId.equals(""));
}
public boolean isEmpty() {
return (hWnd == null && hWndStr.equals("") && runtimeId.equals(""));
}
public static boolean isWpfRuntimeIdFormat(String runtimeIdTest) {
return (runtimeIdTest.contains("-"));
}
public String toString() {
if (isWin32() && !hWndStr.equals(""))
return hWndStr;
else if (isWin32() && hWnd != null)
{
hWndStr = Api.GetHandleAsString(hWnd);
return hWndStr;
}
else if (isWpf())
return runtimeId;
else
return null;
}
}

View File

@@ -12,7 +12,6 @@ import java.io.StringWriter;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@@ -74,11 +73,16 @@ public class WindowsEnumeratedXml implements Runnable{
public static String getXml() { public static String getXml() {
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>(); final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
final Map<String, String> processList = new LinkedHashMap<String, String>(); final Map<String, String> processList = new LinkedHashMap<String, String>();
final Map<String, WindowInfo> wpfParentList = new LinkedHashMap<String, WindowInfo>();
int wpfCount = 0;
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) {
infoList.put(Api.GetHandleAsString(hWnd), new WindowInfo(hWnd, true)); WindowInfo wi = new WindowInfo(hWnd, true);
infoList.put(wi.hwndStr, wi);
if (wi.className.startsWith("HwndWrapper"))
wpfParentList.put(wi.hwndStr, null);
return true; return true;
} }
} }
@@ -86,7 +90,10 @@ public class WindowsEnumeratedXml implements Runnable{
class ParentWindowCallback implements WinUser.WNDENUMPROC { class ParentWindowCallback implements WinUser.WNDENUMPROC {
@Override @Override
public boolean callback(HWND hWnd, Pointer lParam) { public boolean callback(HWND hWnd, Pointer lParam) {
infoList.put(Api.GetHandleAsString(hWnd), new WindowInfo(hWnd, false)); WindowInfo wi = new WindowInfo(hWnd, false);
infoList.put(wi.hwndStr, wi);
if (wi.className.startsWith("HwndWrapper"))
wpfParentList.put(wi.hwndStr, null);
Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0)); Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0));
return true; return true;
} }
@@ -94,8 +101,19 @@ public class WindowsEnumeratedXml implements Runnable{
Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0); Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0);
//Enumerate WPF windows and add to list //Enumerate WPF windows and add to list
if (!SynthuseDlg.config.disableWpf.equals("true")) if (!SynthuseDlg.config.isWpfBridgeDisabled())
infoList.putAll(EnumerateWindowsWithWpfBridge("WPF")); {
////win[starts-with(@class,'HwndWrapper')]
//WpfBridge wb = new WpfBridge();
//if (wb.countDescendantWindows() > 0)
for (String handle : wpfParentList.keySet()) {
//WindowInfo w = wpfParentList.get(handle);
//System.out.println("EnumerateWindowsWithWpfBridge: " + handle);
Map<String, WindowInfo> wpfInfoList = EnumerateWindowsWithWpfBridge(handle, "WPF");
wpfCount += wpfInfoList.size();
infoList.putAll(wpfInfoList);
}
}
// convert window info list to xml dom // convert window info list to xml dom
try { try {
@@ -159,6 +177,8 @@ public class WindowsEnumeratedXml implements Runnable{
totals.setAttribute("parentCount", parentCount+""); totals.setAttribute("parentCount", parentCount+"");
totals.setAttribute("childCount", childCount+""); totals.setAttribute("childCount", childCount+"");
totals.setAttribute("windowCount", infoList.size()+""); totals.setAttribute("windowCount", infoList.size()+"");
totals.setAttribute("wpfWrapperCount", wpfParentList.size()+"");
totals.setAttribute("wpfCount", wpfCount+"");
totals.setAttribute("processCount", processList.size()+""); totals.setAttribute("processCount", processList.size()+"");
totals.setAttribute("updatedLast", new Timestamp((new Date()).getTime()) + ""); totals.setAttribute("updatedLast", new Timestamp((new Date()).getTime()) + "");
rootElement.appendChild(totals); rootElement.appendChild(totals);
@@ -172,24 +192,26 @@ public class WindowsEnumeratedXml implements Runnable{
return ""; return "";
} }
public static Map<String, WindowInfo> EnumerateWindowsWithWpfBridge(String frameworkType) { public static Map<String, WindowInfo> EnumerateWindowsWithWpfBridge(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); wb.setFrameworkId(frameworkType);
List<String> parentIds = new ArrayList<String>(Arrays.asList(wb.enumChildrenWindowIds(""))); long hwnd = Long.parseLong(parentHwndStr);
//System.out.println("enumChildrenWindowIds"); //List<String> parentIds = new ArrayList<String>(Arrays.asList(wb.enumChildrenWindowIds("")));
String[] allIds = wb.enumDescendantWindowInfo("", WindowInfo.WPF_PROPERTY_LIST); //System.out.println("getRuntimeIdFromHandle");
String parentRuntimeId = wb.getRuntimeIdFromHandle(hwnd);
//System.out.println("runtimeId=" + runtimeId);
String[] allIds = wb.enumDescendantWindowInfo(parentRuntimeId, WindowInfo.WPF_PROPERTY_LIST);
if (allIds == null)
return infoList; //empty list
//System.out.println("enumDescendantWindowIds " + allIds.length); //System.out.println("enumDescendantWindowIds " + allIds.length);
for(String runtimeIdAndInfo : allIds) { for(String runtimeIdAndInfo : allIds) {
//System.out.println("getting window info for: " + runtimeIdAndInfo); //System.out.println("getting window info for: " + runtimeIdAndInfo);
String onlyRuntimeId = runtimeIdAndInfo; WindowInfo wi = new WindowInfo(runtimeIdAndInfo, true);
if (runtimeIdAndInfo.contains(",")) if (wi.parentStr.equals(parentRuntimeId))
onlyRuntimeId = runtimeIdAndInfo.substring(0, runtimeIdAndInfo.indexOf(",")); wi.parentStr = parentHwndStr;
//System.out.println("is parent? " + onlyRuntimeId); //System.out.println("is parent? " + onlyRuntimeId);
if (parentIds.contains(onlyRuntimeId)) //is Parent? infoList.put(wi.runtimeId, wi);
infoList.put(onlyRuntimeId, new WindowInfo(runtimeIdAndInfo, false));
else// must be child
infoList.put(onlyRuntimeId, new WindowInfo(runtimeIdAndInfo, true));
} }
return infoList; return infoList;
} }

View File

@@ -7,6 +7,7 @@
package org.synthuse; package org.synthuse;
import java.awt.Point;
import java.io.*; import java.io.*;
public class WpfBridge { public class WpfBridge {
@@ -69,24 +70,57 @@ public class WpfBridge {
System.load(temp.getAbsolutePath()); System.load(temp.getAbsolutePath());
} }
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
//Descendants will walk the full tree of windows, NOT just one level of children //Descendants will walk the full tree of windows, NOT just one level of children
native int countDescendantWindows(); public native int countDescendantWindows();
native int countDescendantWindows(String runtimeIdValue); public native int countDescendantWindows(String runtimeIdValue);
native int countChildrenWindows(); public native int countChildrenWindows();
native int countChildrenWindows(String runtimeIdValue); public native int countChildrenWindows(String runtimeIdValue);
native String[] enumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop public native String[] enumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop
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
native String[] enumDescendantWindowIds(long processId); public native String[] enumDescendantWindowIds(long processId);
native String[] enumDescendantWindowIdsFromHandle(long windowHandle);
//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.
native String[] enumDescendantWindowInfo(String runtimeIdValue, String properties); //returns properties comma separated public native String[] enumDescendantWindowInfo(String runtimeIdValue, String properties); //returns properties comma separated
public native String getRuntimeIdFromHandle(long windowHandle);
public native String getRuntimeIdFromPoint(int x, int y);
public native String getParentRuntimeId(String runtimeIdValue);
public native String getProperty(String propertyName, String runtimeIdValue);
public native String[] getProperties(String runtimeIdValue);
public native String[] getPropertiesAndValues(String runtimeIdValue);
public Point getCenterOfElement(String runtimeIdValue) {
Point p = new Point();
String boundary = getProperty("BoundingRectangleProperty", runtimeIdValue);
//System.out.println("boundary: " + boundary); //boundary: 841,264,125,29
String[] boundarySplt = boundary.split(",");
int x = Integer.parseInt(boundarySplt[0]);
int y = Integer.parseInt(boundarySplt[1]);
int width = Integer.parseInt(boundarySplt[2]);
int height = Integer.parseInt(boundarySplt[3]);
p.x = ((width) /2) + x;
p.y = ((height) /2) + y;
return p;
}
public String getWindowClass(String runtimeIdValue) {
return getProperty("ClassNameProperty", runtimeIdValue);
}
public String getWindowText(String runtimeIdValue) {
return getProperty("NameProperty", runtimeIdValue);
}
public String getWindowAutomationId(String runtimeIdValue) {
return getProperty("AutomationIdProperty", runtimeIdValue);
}
public String getWindowFramework(String runtimeIdValue) {
return getProperty("FrameworkIdProperty", runtimeIdValue);
}
native String getParentRuntimeId(String runtimeIdValue);
native String getProperty(String propertyName, String runtimeIdValue);
native String[] getProperties(String runtimeIdValue);
native String[] getPropertiesAndValues(String runtimeIdValue);
} }

View File

@@ -21,7 +21,9 @@ 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 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);
@@ -42,6 +44,14 @@ public class XpathManager implements Runnable{
this.windowsXmlTextPane = windowsXmlTextPane; this.windowsXmlTextPane = windowsXmlTextPane;
} }
public XpathManager(HWND hwnd, String runtimeId, JTextPane windowsXmlTextPane, Events events) {
this.events = events;
this.hwnd = hwnd;
this.runtimeId = runtimeId;
this.windowsXmlTextPane = windowsXmlTextPane;
this.wpf = new WpfBridge();
}
@Override @Override
public void run() { public void run() {
String results = buildXpathStatement(); String results = buildXpathStatement();
@@ -53,14 +63,56 @@ public class XpathManager implements Runnable{
t.start(); t.start();
} }
public static void buildXpathStatementThreaded(HWND hwnd, String runtimeId, JTextPane windowsXmlTextPane, Events events) {
Thread t = new Thread(new XpathManager(hwnd, runtimeId, windowsXmlTextPane, events));
t.start();
}
public String compareLongTextString(String rawText) {
String escapedTxtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(rawText);
if (!escapedTxtStr.isEmpty()) {
if (rawText.length() > 20) {// if the raw text is too long only test the first 20 characters
escapedTxtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(rawText.substring(0, 20));
}
}
return escapedTxtStr;
}
public String buildWpfXpathStatement() {
String builtXpath = "";
String xml = this.windowsXmlTextPane.getText();
String classStr = wpf.getWindowClass(runtimeId);
//System.out.println("class: " + classStr);
String txtOrig = wpf.getWindowText(runtimeId);
if (classStr == null || txtOrig == null)
return "";
//System.out.println("text: " + txtOrig);
String txtStr = compareLongTextString(txtOrig);
builtXpath = "//wpf[@class='" + classStr + "' and starts-with(@text,'" + txtStr + "')]";
//builtXpath = "//*[@hwnd='" + runtimeId + "']";
System.out.println("evaluateXpathGetValues: " + builtXpath);
List<String> wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
if (wpfResultList.size() == 0)
return "";
// return builtXpath;
return builtXpath;
}
public String buildXpathStatement() { public String buildXpathStatement() {
String builtXpath = ""; String builtXpath = "";
try { try {
String xml = this.windowsXmlTextPane.getText();
if (runtimeId != null && !SynthuseDlg.config.isWpfBridgeDisabled()) {
if (!runtimeId.isEmpty()) {
builtXpath = buildWpfXpathStatement();
}
}
if (builtXpath != "")
return builtXpath;
String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd)); String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd));
String handleStr = Api.GetHandleAsString(hwnd); String handleStr = Api.GetHandleAsString(hwnd);
String txtOrig = Api.GetWindowText(hwnd); String txtOrig = Api.GetWindowText(hwnd);
String txtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(txtOrig); String txtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(txtOrig);
String xml = this.windowsXmlTextPane.getText();
builtXpath = "//win[@class='" + classStr + "']"; builtXpath = "//win[@class='" + classStr + "']";
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath); List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
//int matches = nextXpathMatch(builtXpath, textPane, true); //int matches = nextXpathMatch(builtXpath, textPane, true);

View File

@@ -1,6 +1,7 @@
package org.synthuse.commands; package org.synthuse.commands;
import java.awt.Point;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.sql.Timestamp; import java.sql.Timestamp;
@@ -9,14 +10,13 @@ import java.util.List;
import org.synthuse.*; import org.synthuse.*;
import com.sun.jna.platform.win32.WinDef.HWND;
public class BaseCommand { public class BaseCommand {
static String WIN_XML = ""; static String WIN_XML = "";
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 CommandProcessor parentProcessor = null; protected CommandProcessor parentProcessor = null;
protected int getExecuteErrorCount() { protected int getExecuteErrorCount() {
@@ -92,12 +92,12 @@ public class BaseCommand {
return cmdResult; return cmdResult;
} }
public HWND findHandleWithXpath(String xpath) { public WinPtr findHandleWithXpath(String xpath) {
return findHandleWithXpath(xpath, false); return findHandleWithXpath(xpath, false);
} }
public HWND findHandleWithXpath(String xpath, boolean ignoreFailedFind) { public WinPtr findHandleWithXpath(String xpath, boolean ignoreFailedFind) {
HWND result = null; WinPtr result = new WinPtr();
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000); double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
if (secondsFromLastUpdate > CommandProcessor.XML_UPDATE_THRESHOLD) { //default 5 second threshold if (secondsFromLastUpdate > CommandProcessor.XML_UPDATE_THRESHOLD) { //default 5 second threshold
WIN_XML = WindowsEnumeratedXml.getXml(); WIN_XML = WindowsEnumeratedXml.getXml();
@@ -109,18 +109,34 @@ public class BaseCommand {
for(String item: resultList) { for(String item: resultList) {
if (item.contains("hwnd=")) { if (item.contains("hwnd=")) {
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hwnd"); List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hwnd");
resultStr = hwndList.get(0); if (hwndList.size() > 0)
resultStr = hwndList.get(0); //get first hwnd;
} }
else else
resultStr = item; resultStr = item;
break; break;
} }
result = Api.GetHandleFromString(resultStr); if (WinPtr.isWpfRuntimeIdFormat(resultStr))
if (result == null && !ignoreFailedFind) result.runtimeId = resultStr;
else {
result.hWnd = Api.GetHandleFromString(resultStr);
if (!api.user32.IsWindow(result.hWnd))
appendError("Error: Failed to located HWND(" + resultStr + ") from : " + xpath);
}
if (result.isEmpty())
appendError("Error: Failed to find window handle matching: " + xpath); appendError("Error: Failed to find window handle matching: " + xpath);
return result; return result;
} }
public Point getCenterWindowPosition(WinPtr handle) {
Point p = null;
if (handle.isWin32())
p = api.getWindowPosition(handle.hWnd);
else
p = wpf.getCenterOfElement(handle.runtimeId);
return p;
}
public String convertListToString(List<String> listStr, String delimiter) { public String convertListToString(List<String> listStr, String delimiter) {
StringBuilder result = new StringBuilder(""); StringBuilder result = new StringBuilder("");
for (String item: listStr) { for (String item: listStr) {

View File

@@ -5,7 +5,6 @@ import java.awt.Toolkit;
import java.io.IOException; import java.io.IOException;
import org.synthuse.*; import org.synthuse.*;
import com.sun.jna.platform.win32.WinDef.HWND;
public class MainCommands extends BaseCommand { public class MainCommands extends BaseCommand {
@@ -55,12 +54,12 @@ public class MainCommands extends BaseCommand {
long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000)); long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0; long attemptCount = 0;
String xpath = "/EnumeratedWindows/win[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']"; String xpath = "/EnumeratedWindows/win[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
HWND handle = findHandleWithXpath(xpath, true); WinPtr handle = findHandleWithXpath(xpath, true);
if (handle != null)// first test without a timeout if (!handle.isEmpty())// first test without a timeout
return true; return true;
while (attemptCount < totalAttempts) { while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(xpath, true); handle = findHandleWithXpath(xpath, true);
if (handle != null) if (!handle.isEmpty())
break; break;
try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();} try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount; ++attemptCount;
@@ -76,12 +75,12 @@ public class MainCommands extends BaseCommand {
long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000)); long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0; long attemptCount = 0;
String xpath = "//[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']"; String xpath = "//[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
HWND handle = findHandleWithXpath(xpath, true); WinPtr handle = findHandleWithXpath(xpath, true);
if (handle != null)// first test without a timeout if (!handle.isEmpty())// first test without a timeout
return true; return true;
while (attemptCount < totalAttempts) { while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(xpath, true); handle = findHandleWithXpath(xpath, true);
if (handle != null) if (!handle.isEmpty())
break; break;
try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();} try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount; ++attemptCount;
@@ -97,12 +96,12 @@ public class MainCommands extends BaseCommand {
long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000)); long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0; long attemptCount = 0;
String xpath = "//win[@CLASS='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']"; String xpath = "//win[@CLASS='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
HWND handle = findHandleWithXpath(xpath, true); WinPtr handle = findHandleWithXpath(xpath, true);
if (handle != null)// first test without a timeout if (!handle.isEmpty())// first test without a timeout
return true; return true;
while (attemptCount < totalAttempts) { while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(xpath, true); handle = findHandleWithXpath(xpath, true);
if (handle != null) if (!handle.isEmpty())
break; break;
try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();} try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount; ++attemptCount;
@@ -117,12 +116,12 @@ public class MainCommands extends BaseCommand {
return false; return false;
long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000)); long totalAttempts = (long) (CommandProcessor.WAIT_TIMEOUT_THRESHOLD / (CommandProcessor.XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0; long attemptCount = 0;
HWND handle = findHandleWithXpath(args[0], true); WinPtr handle = findHandleWithXpath(args[0], true);
if (handle != null)// first test without a timeout if (!handle.isEmpty())// first test without a timeout
return true; return true;
while (attemptCount < totalAttempts) { while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(args[0], true); handle = findHandleWithXpath(args[0], true);
if (handle != null) if (!handle.isEmpty())
break; break;
try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();} try {Thread.sleep((long)(CommandProcessor.XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount; ++attemptCount;

View File

@@ -4,8 +4,6 @@ import java.awt.Point;
import org.synthuse.*; import org.synthuse.*;
import com.sun.jna.platform.win32.WinDef.HWND;
public class MouseCommands extends BaseCommand { public class MouseCommands extends BaseCommand {
public MouseCommands(CommandProcessor commandProcessor) { public MouseCommands(CommandProcessor commandProcessor) {
@@ -15,10 +13,12 @@ public class MouseCommands extends BaseCommand {
public boolean cmdClick(String[] args) { public boolean cmdClick(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) //System.out.println("cmdClick1: " + args[0]);
if (handle.isEmpty())
return false; return false;
Point p = api.getWindowPosition(handle); Point p = getCenterWindowPosition(handle);
//System.out.println("cmdClick3: " + p.x + "," + p.y);
RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y); RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y);
RobotMacro.leftClickMouse(); RobotMacro.leftClickMouse();
return true; return true;
@@ -27,10 +27,10 @@ public class MouseCommands extends BaseCommand {
public boolean cmdDoubleClick(String[] args) { public boolean cmdDoubleClick(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
Point p = api.getWindowPosition(handle); Point p = getCenterWindowPosition(handle);
RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y); RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y);
RobotMacro.doubleClickMouse(); RobotMacro.doubleClickMouse();
return true; return true;
@@ -39,10 +39,10 @@ public class MouseCommands extends BaseCommand {
public boolean cmdRightClick(String[] args) { public boolean cmdRightClick(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
Point p = api.getWindowPosition(handle); Point p = getCenterWindowPosition(handle);
RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y); RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y);
RobotMacro.rightClickMouse(); RobotMacro.rightClickMouse();
return true; return true;
@@ -71,10 +71,10 @@ public class MouseCommands extends BaseCommand {
public boolean cmdMouseMove(String[] args) { public boolean cmdMouseMove(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
Point p = api.getWindowPosition(handle); Point p = getCenterWindowPosition(handle);
RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y); RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y);
//System.out.println("point " + p.x + "," + p.y); //System.out.println("point " + p.x + "," + p.y);
return true; return true;
@@ -101,30 +101,30 @@ public class MouseCommands extends BaseCommand {
public boolean cmdWinClick(String[] args) { public boolean cmdWinClick(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.sendClick(handle); api.sendClick(handle.hWnd);
return true; return true;
} }
public boolean cmdWinDoubleClick(String[] args) { public boolean cmdWinDoubleClick(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.sendDoubleClick(handle); api.sendDoubleClick(handle.hWnd);
return true; return true;
} }
public boolean cmdWinRightClick(String[] args) { public boolean cmdWinRightClick(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.sendRightClick(handle); api.sendRightClick(handle.hWnd);
return true; return true;
} }
} }

View File

@@ -2,8 +2,6 @@ package org.synthuse.commands;
import org.synthuse.*; import org.synthuse.*;
import com.sun.jna.platform.win32.WinDef.HWND;
public class WindowsCommands extends BaseCommand { public class WindowsCommands extends BaseCommand {
public WindowsCommands(CommandProcessor cp) { public WindowsCommands(CommandProcessor cp) {
@@ -13,10 +11,10 @@ public class WindowsCommands extends BaseCommand {
public boolean cmdWindowFocus(String[] args) { public boolean cmdWindowFocus(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.activateWindow(handle); api.activateWindow(handle.hWnd);
//api.showWindow(handle); //api.showWindow(handle);
return true; return true;
} }
@@ -24,60 +22,60 @@ public class WindowsCommands extends BaseCommand {
public boolean cmdWindowMinimize(String[] args) { public boolean cmdWindowMinimize(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.minimizeWindow(handle); api.minimizeWindow(handle.hWnd);
return true; return true;
} }
public boolean cmdWindowMaximize(String[] args) { public boolean cmdWindowMaximize(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.maximizeWindow(handle); api.maximizeWindow(handle.hWnd);
return true; return true;
} }
public boolean cmdWindowRestore(String[] args) { public boolean cmdWindowRestore(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.restoreWindow(handle); api.restoreWindow(handle.hWnd);
return true; return true;
} }
public boolean cmdWindowHide(String[] args) { public boolean cmdWindowHide(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.hideWindow(handle); api.hideWindow(handle.hWnd);
return true; return true;
} }
public boolean cmdWindowShow(String[] args) { public boolean cmdWindowShow(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.showWindow(handle); api.showWindow(handle.hWnd);
return true; return true;
} }
public boolean cmdWindowSwitchToThis(String[] args) { public boolean cmdWindowSwitchToThis(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.switchToThisWindow(handle, true); api.switchToThisWindow(handle.hWnd, true);
return true; return true;
} }
@@ -85,29 +83,29 @@ public class WindowsCommands extends BaseCommand {
public boolean cmdWindowClose(String[] args) { public boolean cmdWindowClose(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.closeWindow(handle); api.closeWindow(handle.hWnd);
return true; return true;
} }
public boolean cmdSetText(String[] args) { public boolean cmdSetText(String[] args) {
if (!checkArgumentLength(args, 2)) if (!checkArgumentLength(args, 2))
return false; return false;
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return false; return false;
api.sendWmSetText(handle, args[1]); api.sendWmSetText(handle.hWnd, args[1]);
return true; return true;
} }
public String cmdGetText(String[] args) { public String cmdGetText(String[] args) {
if (!checkArgumentLength(args, 1)) if (!checkArgumentLength(args, 1))
return ""; return "";
HWND handle = findHandleWithXpath(args[0]); WinPtr handle = findHandleWithXpath(args[0]);
if (handle == null) if (handle.isEmpty())
return ""; return "";
return api.sendWmGetText(handle); return api.sendWmGetText(handle.hWnd);
} }
} }

View File

@@ -0,0 +1,59 @@
package org.synthuse.test;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.synthuse.*;
public class WpfBridgeTest {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void countChildren() {
WpfBridge wb = new WpfBridge();
wb.setFrameworkId("Win32");//We should find some Win32 windows, maybe not WPF
int win32Cnt = wb.countChildrenWindows();
assertTrue(win32Cnt > 0);
System.out.println("win32 countChildrenWindows: " + win32Cnt);
wb.setFrameworkId("WPF");// maybe not WPF
//System.out.println("wpf countChildrenWindows: " + wb.countChildrenWindows());
}
@Test
public void getRuntimeFromHandle() {
long handle = 1639790;
//String rid = wb.getRuntimeIdFromHandle(handle);
//System.out.println("getRuntimeIdFromHandle: " + rid);
handle = 984416;
//rid = wb.getRuntimeIdFromHandle(handle);
//System.out.println("getRuntimeIdFromHandle: " + rid);
}
@Test
public void enumerateWindowInfo() {
WpfBridge wb = new WpfBridge();
/*
EnumerateWindowsWithWpfBridge: 1639790
getRuntimeIdFromHandle
runtimeId=42-1639790
enumDescendantWindowIds 18
EnumerateWindowsWithWpfBridge: 984416
getRuntimeIdFromHandle
runtimeId=42-984416
*/
//int count = wb.countDescendantWindows("42-984416");
String[] wInfo = wb.enumDescendantWindowInfo("42-984416", WindowInfo.WPF_PROPERTY_LIST);
if (wInfo != null)
System.out.println("enumDescendantWindowInfo: " + wInfo.length);
}
}