Added support for scripting menus, and showing counts for lists, comboboxes, treeviews, listviews
Support for scripting menus and seeing more information about various list types, and partially working toolbars
This commit is contained in:
@@ -188,10 +188,15 @@ System::String ^ WpfAutomation::getRuntimeIdFromHandle(System::IntPtr windowHand
|
|||||||
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, true);
|
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
|
||||||
if (parent == nullptr)
|
if (parent == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
|
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
|
//create array for keeping order of properties
|
||||||
System::String ^delim = L",";
|
System::String ^delim = L",";
|
||||||
array<System::String ^> ^propSpltArray = properties->Split(delim->ToCharArray());
|
array<System::String ^> ^propSpltArray = properties->Split(delim->ToCharArray());
|
||||||
@@ -203,6 +208,11 @@ array<System::String ^> ^ WpfAutomation::enumDescendantWindowInfo(System::String
|
|||||||
{
|
{
|
||||||
array<AutomationProperty^> ^aps = child->GetSupportedProperties();
|
array<AutomationProperty^> ^aps = child->GetSupportedProperties();
|
||||||
array<System::String ^> ^propValues = gcnew array<System::String ^>(propSpltArray->Length);//keep order
|
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++)
|
for(int i=0 ; i < propValues->Length ; i++)
|
||||||
{
|
{
|
||||||
propValues[i] = L"";
|
propValues[i] = L"";
|
||||||
@@ -218,7 +228,7 @@ array<System::String ^> ^ WpfAutomation::enumDescendantWindowInfo(System::String
|
|||||||
System::String ^shortPropName = L" null ";
|
System::String ^shortPropName = L" null ";
|
||||||
if (ap->ProgrammaticName->Contains(L"."))
|
if (ap->ProgrammaticName->Contains(L"."))
|
||||||
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
|
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
|
||||||
if (properties->Contains(shortPropName) || properties->Contains(ap->ProgrammaticName) || ap->ProgrammaticName->Equals(properties))
|
if (properties->Contains(shortPropName) || properties->Contains(ap->ProgrammaticName) || ap->ProgrammaticName->Equals(properties) || wildcardEnabled)
|
||||||
{
|
{
|
||||||
//System::Console::WriteLine("shortPropName: {0}", shortPropName);
|
//System::Console::WriteLine("shortPropName: {0}", shortPropName);
|
||||||
System::Object ^currentVal = child->GetCurrentPropertyValue(ap);
|
System::Object ^currentVal = child->GetCurrentPropertyValue(ap);
|
||||||
@@ -242,17 +252,23 @@ array<System::String ^> ^ WpfAutomation::enumDescendantWindowInfo(System::String
|
|||||||
}
|
}
|
||||||
if (currentPropertyStr->Equals(L"")) //if there isn't a value skip
|
if (currentPropertyStr->Equals(L"")) //if there isn't a value skip
|
||||||
continue;
|
continue;
|
||||||
|
if (wildcardEnabled) {
|
||||||
|
wildcardProperties += shortPropName + ":" +currentPropertyStr + ",";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
//System::Console::WriteLine("currentPropertyStr: {0}", currentPropertyStr);
|
//System::Console::WriteLine("currentPropertyStr: {0}", currentPropertyStr);
|
||||||
//find the correct order to return this property
|
//find the correct order to return this property
|
||||||
for(int i=0 ; i < propSpltArray->Length ; i++)
|
for(int i=0 ; i < propSpltArray->Length ; i++)
|
||||||
{
|
{
|
||||||
if (propSpltArray[i]->Equals(shortPropName) || propSpltArray[i]->Equals(ap->ProgrammaticName))
|
if (propSpltArray[i]->Equals(shortPropName) || propSpltArray[i]->Equals(ap->ProgrammaticName))
|
||||||
propValues[i] = currentPropertyStr;
|
propValues[i] = currentPropertyStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//output properties in the correct order
|
//output properties in the correct order
|
||||||
for(int i=0 ; i < propSpltArray->Length ; i++)
|
for(int i=0 ; i < propSpltArray->Length ; i++)
|
||||||
winInfoList[count] += propValues[i] + L",";
|
winInfoList[count] += propValues[i] + L",";
|
||||||
|
if (wildcardEnabled)
|
||||||
|
winInfoList[count] += wildcardProperties;
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
return winInfoList;
|
return winInfoList;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -8,18 +8,17 @@
|
|||||||
package org.synthuse;
|
package org.synthuse;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.sun.jna.Native;
|
import com.sun.jna.Native;
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import com.sun.jna.platform.win32.WinDef.HDC;
|
import com.sun.jna.Structure;
|
||||||
import com.sun.jna.platform.win32.WinDef.HPEN;
|
import com.sun.jna.platform.win32.WinDef.*;
|
||||||
|
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
|
||||||
|
import com.sun.jna.platform.win32.WinDef;
|
||||||
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
||||||
import com.sun.jna.platform.win32.WinUser;
|
import com.sun.jna.platform.win32.WinUser;
|
||||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
|
||||||
import com.sun.jna.platform.win32.WinDef.LPARAM;
|
|
||||||
import com.sun.jna.platform.win32.WinDef.LRESULT;
|
|
||||||
import com.sun.jna.platform.win32.WinDef.RECT;
|
|
||||||
import com.sun.jna.platform.win32.WinDef.WPARAM;
|
|
||||||
import com.sun.jna.platform.win32.WinNT.LARGE_INTEGER;
|
import com.sun.jna.platform.win32.WinNT.LARGE_INTEGER;
|
||||||
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
|
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
|
||||||
import com.sun.jna.ptr.PointerByReference;
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
@@ -27,6 +26,8 @@ import com.sun.jna.win32.W32APIOptions;
|
|||||||
|
|
||||||
public class Api {
|
public class Api {
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
|
||||||
public static int WM_SETTEXT = 0x000c;
|
public static int WM_SETTEXT = 0x000c;
|
||||||
public static int WM_GETTEXT = 0x000D;
|
public static int WM_GETTEXT = 0x000D;
|
||||||
public static int WM_GETTEXTLENGTH = 0x000E;
|
public static int WM_GETTEXTLENGTH = 0x000E;
|
||||||
@@ -84,6 +85,24 @@ public class Api {
|
|||||||
public static int RDW_INVALIDATE = 0x0001;
|
public static int RDW_INVALIDATE = 0x0001;
|
||||||
public static int RDW_UPDATENOW = 0x0100;
|
public static int RDW_UPDATENOW = 0x0100;
|
||||||
public static int RDW_ALLCHILDREN = 0x0080;
|
public static int RDW_ALLCHILDREN = 0x0080;
|
||||||
|
|
||||||
|
public static int TB_GETBUTTONTEXTA = (0x0400 + 45);
|
||||||
|
public static int TB_GETBUTTONTEXTW = (0x0400 + 75);
|
||||||
|
public static int TB_GETRECT = (0x0400 + 51);
|
||||||
|
public static int TB_GETTOOLTIPS = (0x0400 + 35);
|
||||||
|
public static int TB_BUTTONCOUNT = 0x0418;
|
||||||
|
|
||||||
|
public static int LVM_FIRST = 0x1000;
|
||||||
|
public static int LVM_GETITEMCOUNT = LVM_FIRST + 4;
|
||||||
|
public static int LVM_GETITEM = LVM_FIRST + 75;
|
||||||
|
public static int LVIF_TEXT = 0x0001;
|
||||||
|
|
||||||
|
public static int LB_GETCOUNT = 0x18B;
|
||||||
|
|
||||||
|
public static int CB_GETCOUNT = 0x146;
|
||||||
|
|
||||||
|
public static int TV_FIRST = 0x1100;
|
||||||
|
public static int TVM_GETCOUNT = TV_FIRST + 5;
|
||||||
|
|
||||||
public static int VK_SHIFT = 16;
|
public static int VK_SHIFT = 16;
|
||||||
public static int VK_LSHIFT = 0xA0;
|
public static int VK_LSHIFT = 0xA0;
|
||||||
@@ -95,6 +114,8 @@ public class Api {
|
|||||||
public static int VK_LMENU = 0xA4;
|
public static int VK_LMENU = 0xA4;
|
||||||
public static int VK_RMENU = 0xA5;
|
public static int VK_RMENU = 0xA5;
|
||||||
|
|
||||||
|
public static int WM_COMMAND = 0x111;
|
||||||
|
|
||||||
public static int CWP_ALL = 0x0000; // Does not skip any child windows
|
public static int CWP_ALL = 0x0000; // Does not skip any child windows
|
||||||
|
|
||||||
public User32 user32;
|
public User32 user32;
|
||||||
@@ -109,7 +130,60 @@ public class Api {
|
|||||||
public static final int POINT_X(long i)
|
public static final int POINT_X(long i)
|
||||||
{
|
{
|
||||||
return (int) (i & 0xFFFF);
|
return (int) (i & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface WinDefExt extends WinDef {
|
||||||
|
//Structures
|
||||||
|
public class MENUITEMINFO extends Structure {
|
||||||
|
public static final int MFS_CHECKED = 0x00000008;
|
||||||
|
public static final int MFS_DEFAULT = 0x00001000;
|
||||||
|
public static final int MFS_DISABLED = 0x00000003;
|
||||||
|
public static final int MFS_ENABLED = 0x00000000;
|
||||||
|
public static final int MFS_GRAYED = 0x00000003;
|
||||||
|
public static final int MFS_HILITE = 0x00000080;
|
||||||
|
public static final int MFS_UNCHECKED = 0x00000000;
|
||||||
|
public static final int MFS_UNHILITE = 0x00000000;
|
||||||
|
public static final int MFT_STRING = 0x0000;
|
||||||
|
public static final int MIIM_DATA = 0x00000020;
|
||||||
|
public static final int MIIM_STRING = 0x0040;
|
||||||
|
public static final int MIIM_SUBMENU = 0x0004;
|
||||||
|
public static final int MIIM_TYPE = 0x0010;
|
||||||
|
|
||||||
|
public static class ByValue extends MENUITEMINFO implements Structure.ByValue {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ByReference extends MENUITEMINFO implements Structure.ByReference {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MENUITEMINFO() {
|
||||||
|
cbSize = size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MENUITEMINFO(Pointer p) {
|
||||||
|
super(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<?> getFieldOrder() {
|
||||||
|
return Arrays.asList(new String[] { "cbSize", "fMask", "fType", "fState", "wID", "hSubMenu", "hbmpChecked",
|
||||||
|
"hbmpUnchecked", "dwItemData", "dwTypeData", "cch", "hbmpItem" });
|
||||||
|
}
|
||||||
|
|
||||||
|
public int cbSize; //The size of the structure, in bytes. The caller must set this member to sizeof(MENUITEMINFO).
|
||||||
|
public int fMask; //Indicates the members to be retrieved or set. MIIM_STRING or MIIM_SUBMENU or ...
|
||||||
|
public int fType; //The menu item type. fType is used only if fMask has a value of MIIM_FTYPE.
|
||||||
|
public int fState; //The menu item state. This member can be one or more of these values. Set fMask to MIIM_STATE to use fState.
|
||||||
|
public int wID; //An application-defined value that identifies the menu item. Set fMask to MIIM_ID to use wID.
|
||||||
|
public HMENU hSubMenu; //A handle to the drop-down menu or submenu associated with the menu item. Or NULL
|
||||||
|
public HBITMAP hbmpChecked; //A handle to the bitmap to display next to the item if it is selected.
|
||||||
|
public HBITMAP hbmpUnchecked; //A handle to the bitmap to display next to the item if it is not selected.
|
||||||
|
public ULONG_PTR dwItemData; //An application-defined value associated with the menu item. Set fMask to MIIM_DATA
|
||||||
|
//public byte[] dwTypeData = new byte[256];
|
||||||
|
public String dwTypeData; //The contents of the menu item, depends on the value of fType and is used only if the MIIM_TYPE flag is set in the fMask member
|
||||||
|
public int cch; //The length of the menu item text, in characters, when information is received about a menu item of the MFT_STRING type.
|
||||||
|
public HBITMAP hbmpItem; //A handle to the bitmap to be displayed, or it can be one of the values in the following table.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface User32 extends W32APIOptions {
|
public interface User32 extends W32APIOptions {
|
||||||
User32 instance = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
|
User32 instance = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
|
||||||
@@ -158,6 +232,20 @@ public class Api {
|
|||||||
boolean ScreenToClient(HWND hWnd, long[] lpPoint);//use macros POINT_X() and POINT_Y() on long lpPoint[0]
|
boolean ScreenToClient(HWND hWnd, long[] lpPoint);//use macros POINT_X() and POINT_Y() on long lpPoint[0]
|
||||||
//HWND WindowFromPoint(int xPoint, int yPoint);
|
//HWND WindowFromPoint(int xPoint, int yPoint);
|
||||||
//HWND WindowFromPoint(POINT point);
|
//HWND WindowFromPoint(POINT point);
|
||||||
|
|
||||||
|
HMENU GetMenu(HWND hWnd);
|
||||||
|
boolean IsMenu(HMENU hMenu);
|
||||||
|
int GetMenuString(HMENU hMenu, int uIDItem, char[] buffer, int nMaxCount, int uFlag);
|
||||||
|
HMENU GetSubMenu(HMENU hMenu, int nPos);
|
||||||
|
int GetMenuItemCount(HMENU hMenu);
|
||||||
|
int GetMenuItemID(HMENU hMenu, int nPos);
|
||||||
|
//BOOL WINAPI GetMenuItemInfo(_In_ HMENU hMenu, _In_ UINT uItem, _In_ BOOL fByPosition, _Inout_ LPMENUITEMINFO lpmii);
|
||||||
|
boolean GetMenuItemInfoA(HMENU hMenu, int uItem, boolean fByPosition, WinDefExt.MENUITEMINFO mii); //MENUITEMINFO
|
||||||
|
boolean TrackPopupMenu(HMENU hMenu, int uFlags, int x, int y, int nReserved, HWND hWnd, long prcRect);
|
||||||
|
//
|
||||||
|
|
||||||
|
int GetDlgCtrlID(HWND hwndCtl);
|
||||||
|
int GetDlgItemText(HWND hDlg, int nIDDlgItem, byte[] buffer, int nMaxCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Gdi32 extends W32APIOptions {
|
public interface Gdi32 extends W32APIOptions {
|
||||||
@@ -346,6 +434,32 @@ public class Api {
|
|||||||
user32.SendMessageA(handle, WM_KEYUP, keyCode, null);
|
user32.SendMessageA(handle, WM_KEYUP, keyCode, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String GetMenuItemText(HMENU hmenu, int position) {
|
||||||
|
if (user32.IsMenu(hmenu) == false)
|
||||||
|
return "";
|
||||||
|
char[] buffer = new char[256];
|
||||||
|
user32.GetMenuString(hmenu, position, buffer, 256, 0x0400);
|
||||||
|
return Native.toString(buffer);
|
||||||
|
/*
|
||||||
|
Api.WinDefExt.MENUITEMINFO mii = new Api.WinDefExt.MENUITEMINFO(); // = (MENUITEMINFO)Api.MENUITEMINFO.newInstance(Api.MENUITEMINFO.class);
|
||||||
|
mii.fMask = Api.WinDefExt.MENUITEMINFO.MIIM_TYPE;
|
||||||
|
mii.fType = Api.WinDefExt.MENUITEMINFO.MFT_STRING;
|
||||||
|
mii.cch = 0;
|
||||||
|
mii.dwTypeData = "";
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
boolean result = Api.User32.instance.GetMenuItemInfoA(hmenu, position, true, mii);
|
||||||
|
//System.out.println(position + " GetMenuItemInfo (" + result + ") : " + mii.cch + " " + mii.dwTypeData);
|
||||||
|
mii.fMask = Api.WinDefExt.MENUITEMINFO.MIIM_TYPE;
|
||||||
|
mii.fType = Api.WinDefExt.MENUITEMINFO.MFT_STRING;
|
||||||
|
mii.cch += 1;
|
||||||
|
mii.dwTypeData = "";//new String(new char[mii.cch]).replace("\0", " "); //buffer string with spaces
|
||||||
|
result = Api.User32.instance.GetMenuItemInfoA(hmenu, position, true, mii);
|
||||||
|
//System.out.println(position + " GetMenuItemInfo2 (" + result + ") Text: " + mii.dwTypeData + " " + mii.cch + " " + mii.wID);
|
||||||
|
//System.out.println("last error: " + Api.Kernel32.instance.GetLastError());
|
||||||
|
return mii.dwTypeData;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
public Point getWindowPosition(HWND handle) {
|
public Point getWindowPosition(HWND handle) {
|
||||||
Point windowPoint = new Point();
|
Point windowPoint = new Point();
|
||||||
RECT rect = new RECT();
|
RECT rect = new RECT();
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ public class CommandPopupMenu extends JPopupMenu {
|
|||||||
|
|
||||||
CommandMenuItem mntmWindowSwitchToThis = new CommandMenuItem("windowSwitchToThis", 2);
|
CommandMenuItem mntmWindowSwitchToThis = new CommandMenuItem("windowSwitchToThis", 2);
|
||||||
mnWinMessages.add(mntmWindowSwitchToThis);
|
mnWinMessages.add(mntmWindowSwitchToThis);
|
||||||
|
|
||||||
|
CommandMenuItem mntmSelectMenu = new CommandMenuItem("selectMenu", 2);
|
||||||
|
mnWinMessages.add(mntmSelectMenu);
|
||||||
|
|
||||||
CommandMenuItem mntmSetcursorposition = new CommandMenuItem("setCursorPosition", 3);
|
CommandMenuItem mntmSetcursorposition = new CommandMenuItem("setCursorPosition", 3);
|
||||||
mnWinMessages.add(mntmSetcursorposition);
|
mnWinMessages.add(mntmSetcursorposition);
|
||||||
|
|||||||
@@ -203,6 +203,8 @@ public class CommandProcessor implements Runnable{
|
|||||||
//Windows Api Commands
|
//Windows Api Commands
|
||||||
if (command.equals("windowFocus"))
|
if (command.equals("windowFocus"))
|
||||||
return win.cmdWindowFocus(args);
|
return win.cmdWindowFocus(args);
|
||||||
|
if (command.equals("selectMenu"))
|
||||||
|
return win.cmdSelectMenu(args);
|
||||||
if (command.equals("windowMinimize"))
|
if (command.equals("windowMinimize"))
|
||||||
return win.cmdWindowMinimize(args);
|
return win.cmdWindowMinimize(args);
|
||||||
if (command.equals("windowMaximize"))
|
if (command.equals("windowMaximize"))
|
||||||
|
|||||||
85
src/org/synthuse/MenuInfo.java
Normal file
85
src/org/synthuse/MenuInfo.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HMENU;
|
||||||
|
|
||||||
|
public class MenuInfo {
|
||||||
|
public HMENU hmenu = null;
|
||||||
|
public String hmenuStr = "";
|
||||||
|
public String hwndStr = "";
|
||||||
|
public int menuCount = 0;
|
||||||
|
public String text = "";
|
||||||
|
public String unaltered = "";
|
||||||
|
public int id = 0;
|
||||||
|
public int position = 0;
|
||||||
|
public boolean hasSubMenu = false;
|
||||||
|
public HMENU submenu = null;
|
||||||
|
public String submenuStr = "";
|
||||||
|
public int submenuCount = 0;
|
||||||
|
|
||||||
|
public MenuInfo(HMENU hmenu) {
|
||||||
|
loadMenuBase(hmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuInfo(HMENU hmenu, int position) {
|
||||||
|
loadMenuBase(hmenu);
|
||||||
|
if (this.menuCount > 0)
|
||||||
|
loadMenuDetails(hmenu, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadMenuBase(HMENU hmenu) {
|
||||||
|
Api api = new Api();
|
||||||
|
this.hmenu = hmenu;
|
||||||
|
this.hmenuStr = GetHandleMenuAsString(hmenu);
|
||||||
|
this.menuCount = api.user32.GetMenuItemCount(hmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadMenuDetails(HMENU hmenu, int position) {
|
||||||
|
Api api = new Api();
|
||||||
|
this.position = position;
|
||||||
|
this.unaltered = api.GetMenuItemText(hmenu, position);
|
||||||
|
this.text = unaltered;
|
||||||
|
if (this.unaltered.contains("\t"))
|
||||||
|
this.text = this.text.substring(0, this.text.indexOf("\t"));
|
||||||
|
this.text = text.replaceAll("[^a-zA-Z0-9.,\\+ ]", "");
|
||||||
|
this.id = api.user32.GetMenuItemID(hmenu, position);
|
||||||
|
HMENU submenu = api.user32.GetSubMenu(hmenu, position);
|
||||||
|
if (submenu != null) {
|
||||||
|
int subCount = api.user32.GetMenuItemCount(submenu);
|
||||||
|
if (subCount > 0) {
|
||||||
|
this.hasSubMenu = true;
|
||||||
|
this.submenu = submenu;
|
||||||
|
this.submenuStr = GetHandleMenuAsString(submenu);
|
||||||
|
this.submenuCount = subCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String GetHandleMenuAsString(HMENU hmenu) {
|
||||||
|
if (hmenu == null)
|
||||||
|
return "0";
|
||||||
|
//String longHexStr = hWnd.toString().substring("native@".length());
|
||||||
|
//String longHexStr = hmenu.getPointer()
|
||||||
|
String longHexStr = hmenu.getPointer().toString().substring("native@0x".length());
|
||||||
|
long l = new BigInteger(longHexStr, 16).longValue();
|
||||||
|
return l + "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HMENU GetHandleMenuFromString(String hmenu) {
|
||||||
|
if (hmenu == null)
|
||||||
|
return null;
|
||||||
|
if (hmenu.isEmpty())
|
||||||
|
return null;
|
||||||
|
String cleanNumericHandle = hmenu.replaceAll("[^\\d.]", "");
|
||||||
|
try {
|
||||||
|
return (new HMENU(new Pointer(Long.parseLong(cleanNumericHandle))));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,12 +7,19 @@
|
|||||||
|
|
||||||
package org.synthuse;
|
package org.synthuse;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.synthuse.Api.*;
|
import org.synthuse.Api.*;
|
||||||
|
|
||||||
import com.sun.jna.Native;
|
import com.sun.jna.Native;
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HMENU;
|
||||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.LPARAM;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.LRESULT;
|
||||||
import com.sun.jna.platform.win32.WinDef.RECT;
|
import com.sun.jna.platform.win32.WinDef.RECT;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.WPARAM;
|
||||||
import com.sun.jna.ptr.PointerByReference;
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
|
||||||
public class WindowInfo {
|
public class WindowInfo {
|
||||||
@@ -33,6 +40,10 @@ public class WindowInfo {
|
|||||||
public Object xmlObj = null;
|
public Object xmlObj = null;
|
||||||
public String framework = "win32";//default as win32
|
public String framework = "win32";//default as win32
|
||||||
public String runtimeId = "";
|
public String runtimeId = "";
|
||||||
|
public int menus = 0;
|
||||||
|
public HMENU menu = null;
|
||||||
|
|
||||||
|
public Map<String, String> extra = null;
|
||||||
|
|
||||||
//Default Win32 support
|
//Default Win32 support
|
||||||
public WindowInfo(HWND hWnd, boolean isChild) {
|
public WindowInfo(HWND hWnd, boolean isChild) {
|
||||||
@@ -42,7 +53,68 @@ 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()) {
|
||||||
|
//System.out.println("getting toolbar text");
|
||||||
|
}
|
||||||
|
|
||||||
|
//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));
|
||||||
|
if (tbCount.intValue() > 0) { // toolbar button count
|
||||||
|
//System.out.println("TB_BUTTONCOUNT: " + tbCount.intValue());
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("tbCount", tbCount.intValue() + "");
|
||||||
|
//Api.User32.instance.SendMessageA(hWnd, Api.TB_GETTOOLTIPS, 0, buffer);
|
||||||
|
//text = Native.toString(buffer);
|
||||||
|
}
|
||||||
|
LRESULT lvCount = Api.User32.instance.SendMessage(hWnd, Api.LVM_GETITEMCOUNT, new WPARAM(0), new LPARAM(0));
|
||||||
|
if (lvCount.intValue() > 0) { // listview item count
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("lvCount", lvCount.intValue() + "");
|
||||||
|
}
|
||||||
|
LRESULT lbCount = Api.User32.instance.SendMessage(hWnd, Api.LB_GETCOUNT, new WPARAM(0), new LPARAM(0));
|
||||||
|
if (lbCount.intValue() > 0) { // listbox item count
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("lbCount", lbCount.intValue() + "");
|
||||||
|
}
|
||||||
|
LRESULT cbCount = Api.User32.instance.SendMessage(hWnd, Api.CB_GETCOUNT, new WPARAM(0), new LPARAM(0));
|
||||||
|
if (cbCount.intValue() > 0) { // listbox item count
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("cbCount", cbCount.intValue() + "");
|
||||||
|
}
|
||||||
|
LRESULT tvCount = Api.User32.instance.SendMessage(hWnd, Api.TVM_GETCOUNT, new WPARAM(0), new LPARAM(0));
|
||||||
|
if (tvCount.intValue() > 0) { //treeview node count
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("tvCount", tvCount.intValue() + "");
|
||||||
|
}
|
||||||
|
//check if window has a menu
|
||||||
|
HMENU hmenu = Api.User32.instance.GetMenu(hWnd);
|
||||||
|
if (hmenu != null) { //menu item count
|
||||||
|
int menuCount = Api.User32.instance.GetMenuItemCount(hmenu);
|
||||||
|
if (menuCount > 0) {
|
||||||
|
this.menus = menuCount;
|
||||||
|
this.menu = hmenu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChild) {
|
||||||
|
int ctrlID = Api.User32.instance.GetDlgCtrlID(hWnd);
|
||||||
|
if (ctrlID > 0){
|
||||||
|
//parent = User32.instance.GetParent(hWnd);
|
||||||
|
int dtresult = Api.User32.instance.GetDlgItemText(hWnd, ctrlID, buffer, 1024);
|
||||||
|
if (dtresult > 0) {
|
||||||
|
String dgText = Native.toString(buffer);
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("dgText", dgText + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char[] buffer2 = new char[1026];
|
char[] buffer2 = new char[1026];
|
||||||
User32.instance.GetClassName(hWnd, buffer2, 1026);
|
User32.instance.GetClassName(hWnd, buffer2, 1026);
|
||||||
className = Native.toString(buffer2);
|
className = Native.toString(buffer2);
|
||||||
@@ -85,12 +157,41 @@ public class WindowInfo {
|
|||||||
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,ClassNameProperty,NameProperty";
|
||||||
String[] spltProperties = enumProperties.split(",");
|
String[] spltProperties = enumProperties.split(",");
|
||||||
|
this.isChild = isChild;
|
||||||
|
if (SynthuseDlg.config.isFilterWpfDisabled()) { //use wildcard mode
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
for(String prop: spltProperties) {
|
||||||
|
String[] propertyNameAndValue = prop.split(":", 2);
|
||||||
|
if (propertyNameAndValue.length < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (propertyNameAndValue[0].equals("RuntimeIdProperty"))
|
||||||
|
this.runtimeId = propertyNameAndValue[1];
|
||||||
|
else if (propertyNameAndValue[0].equals("ParentRuntimeIdProperty"))
|
||||||
|
this.parentStr = propertyNameAndValue[1];
|
||||||
|
else if (propertyNameAndValue[0].equals("ProcessIdProperty"))
|
||||||
|
this.pid = Long.parseLong(propertyNameAndValue[1]);
|
||||||
|
else if (propertyNameAndValue[0].equals("FrameworkIdProperty"))
|
||||||
|
this.framework = propertyNameAndValue[1];
|
||||||
|
else if (propertyNameAndValue[0].equals("ClassNameProperty"))
|
||||||
|
this.className = propertyNameAndValue[1];
|
||||||
|
else if (propertyNameAndValue[0].equals("NameProperty"))
|
||||||
|
this.text = propertyNameAndValue[1];
|
||||||
|
else if (propertyNameAndValue[0].equals("ValueProperty"))
|
||||||
|
this.value = propertyNameAndValue[1];
|
||||||
|
else{
|
||||||
|
extra.put(propertyNameAndValue[0], propertyNameAndValue[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.hwndStr = this.runtimeId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// non-wildcard mode
|
||||||
if (spltProperties.length > 0)
|
if (spltProperties.length > 0)
|
||||||
this.runtimeId = spltProperties[0];
|
this.runtimeId = spltProperties[0];
|
||||||
this.hwndStr = this.runtimeId;
|
this.hwndStr = this.runtimeId;
|
||||||
if (spltProperties.length > 1 && isChild)
|
if (spltProperties.length > 1 && isChild)
|
||||||
this.parentStr = spltProperties[1];
|
this.parentStr = spltProperties[1];
|
||||||
this.isChild = isChild;
|
|
||||||
if (spltProperties.length > 2)
|
if (spltProperties.length > 2)
|
||||||
this.pid = Long.parseLong(spltProperties[2]);
|
this.pid = Long.parseLong(spltProperties[2]);
|
||||||
if (spltProperties.length > 3)
|
if (spltProperties.length > 3)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import org.w3c.dom.NodeList;
|
|||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HMENU;
|
||||||
import com.sun.jna.platform.win32.WinUser;
|
import com.sun.jna.platform.win32.WinUser;
|
||||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
|
|
||||||
@@ -77,6 +78,7 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
final List<String> silverlightParentList = new ArrayList<String>();//MicrosoftSilverlight
|
final List<String> silverlightParentList = new ArrayList<String>();//MicrosoftSilverlight
|
||||||
int wpfCount = 0;
|
int wpfCount = 0;
|
||||||
int silverlightCount = 0;
|
int silverlightCount = 0;
|
||||||
|
int menuCount = 0;
|
||||||
|
|
||||||
class ChildWindowCallback implements WinUser.WNDENUMPROC {
|
class ChildWindowCallback implements WinUser.WNDENUMPROC {
|
||||||
@Override
|
@Override
|
||||||
@@ -142,6 +144,7 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
win = doc.createElement("wpf");
|
win = doc.createElement("wpf");
|
||||||
else if (w.framework.equals("Silverlight"))
|
else if (w.framework.equals("Silverlight"))
|
||||||
win = doc.createElement("silver");
|
win = doc.createElement("silver");
|
||||||
|
|
||||||
win.setAttribute("hwnd", w.hwndStr);
|
win.setAttribute("hwnd", w.hwndStr);
|
||||||
win.setAttribute("text", w.text);
|
win.setAttribute("text", w.text);
|
||||||
if (w.value != "" && w.value != null)
|
if (w.value != "" && w.value != null)
|
||||||
@@ -165,6 +168,18 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
win.setAttribute("pid", w.pid+"");
|
win.setAttribute("pid", w.pid+"");
|
||||||
//else
|
//else
|
||||||
//win.setAttribute("parent", w.parent + ""); // not really needed since child node is append to parent node
|
//win.setAttribute("parent", w.parent + ""); // not really needed since child node is append to parent node
|
||||||
|
if (w.extra != null) {
|
||||||
|
for(String extraName: w.extra.keySet()) {
|
||||||
|
win.setAttribute(extraName, w.extra.get(extraName)+"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w.menus > 0) {
|
||||||
|
win.setAttribute("menus", w.menus+"");
|
||||||
|
//String menuStr = MenuInfo.GetHandleMenuAsString(w.menu);
|
||||||
|
buildMenuXmlElements(doc, win, w.menu, w.hwndStr);
|
||||||
|
++menuCount;
|
||||||
|
}
|
||||||
|
|
||||||
if (w.isChild && infoList.containsKey(w.parentStr)) {
|
if (w.isChild && infoList.containsKey(w.parentStr)) {
|
||||||
childCount++;
|
childCount++;
|
||||||
@@ -188,6 +203,7 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
totals.setAttribute("wpfWrapperCount", wpfParentList.size()+"");
|
totals.setAttribute("wpfWrapperCount", wpfParentList.size()+"");
|
||||||
totals.setAttribute("wpfCount", wpfCount+"");
|
totals.setAttribute("wpfCount", wpfCount+"");
|
||||||
totals.setAttribute("silverlightCount", silverlightCount+"");
|
totals.setAttribute("silverlightCount", silverlightCount+"");
|
||||||
|
totals.setAttribute("menuCount", menuCount+"");
|
||||||
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);
|
||||||
@@ -201,6 +217,26 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Element buildMenuXmlElements(Document xmlDoc, Element xmlElement, HMENU targetMenu, String targetWin)
|
||||||
|
{
|
||||||
|
MenuInfo firstMi = new MenuInfo(targetMenu);
|
||||||
|
for (int i = 0 ; i < firstMi.menuCount ; i++ ) {
|
||||||
|
MenuInfo menuInfo = new MenuInfo(targetMenu, i);
|
||||||
|
Element menuElement = xmlDoc.createElement("menu");
|
||||||
|
menuElement.setAttribute("unaltered", menuInfo.unaltered + "");
|
||||||
|
menuElement.setAttribute("text", menuInfo.text + "");
|
||||||
|
menuElement.setAttribute("id", menuInfo.id + "");
|
||||||
|
menuElement.setAttribute("position", menuInfo.position + "");
|
||||||
|
menuElement.setAttribute("hmenu", menuInfo.hmenuStr + "");
|
||||||
|
menuElement.setAttribute("hwnd", targetWin + "");
|
||||||
|
if (menuInfo.hasSubMenu) {
|
||||||
|
buildMenuXmlElements(xmlDoc, menuElement, menuInfo.submenu, targetWin);
|
||||||
|
}
|
||||||
|
xmlElement.appendChild(menuElement);
|
||||||
|
}
|
||||||
|
return xmlElement;
|
||||||
|
}
|
||||||
|
|
||||||
public static Map<String, WindowInfo> EnumerateWindowsWithWpfBridge(String parentHwndStr, 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();
|
||||||
@@ -212,7 +248,11 @@ public class WindowsEnumeratedXml implements Runnable{
|
|||||||
//System.out.println("getRuntimeIdFromHandle");
|
//System.out.println("getRuntimeIdFromHandle");
|
||||||
String parentRuntimeId = wb.getRuntimeIdFromHandle(hwnd);
|
String parentRuntimeId = wb.getRuntimeIdFromHandle(hwnd);
|
||||||
//System.out.println("runtimeId=" + runtimeId);
|
//System.out.println("runtimeId=" + runtimeId);
|
||||||
String[] allIds = wb.enumDescendantWindowInfo(parentRuntimeId, WindowInfo.WPF_PROPERTY_LIST);
|
String[] allIds = null;
|
||||||
|
if (SynthuseDlg.config.isFilterWpfDisabled())
|
||||||
|
allIds = wb.enumDescendantWindowInfo(parentRuntimeId, "*");
|
||||||
|
else
|
||||||
|
allIds = wb.enumDescendantWindowInfo(parentRuntimeId, WindowInfo.WPF_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);
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class XpathManager implements Runnable{
|
|||||||
//builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
//builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
||||||
//System.out.println("evaluateXpathGetValues: " + builtXpath);
|
//System.out.println("evaluateXpathGetValues: " + builtXpath);
|
||||||
List<String> wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
List<String> wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
||||||
if (wpfResultList.size() > 0)
|
if (wpfResultList.size() == 1)
|
||||||
return builtXpath;
|
return builtXpath;
|
||||||
builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
builtXpath = "//*[@hwnd='" + runtimeId + "']";
|
||||||
wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
wpfResultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
|
||||||
@@ -181,7 +181,12 @@ public class XpathManager implements Runnable{
|
|||||||
if (targetText instanceof JTextPane) {
|
if (targetText instanceof JTextPane) {
|
||||||
final JTextPane target = (JTextPane)targetText;
|
final JTextPane target = (JTextPane)targetText;
|
||||||
target.requestFocus();
|
target.requestFocus();
|
||||||
int cPos = target.getCaretPosition();
|
int cPos = 0;
|
||||||
|
try {
|
||||||
|
cPos = target.getCaretPosition();
|
||||||
|
} catch(Exception ex) {
|
||||||
|
//return 0;//something is throwing nullpointer exception
|
||||||
|
}
|
||||||
if (alwaysFromTop)
|
if (alwaysFromTop)
|
||||||
cPos = 0;
|
cPos = 0;
|
||||||
int len = target.getStyledDocument().getLength();
|
int len = target.getStyledDocument().getLength();
|
||||||
|
|||||||
@@ -129,6 +129,36 @@ public class BaseCommand {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int findMenuIdWithXpath(String xpath) {
|
||||||
|
int result = 0;
|
||||||
|
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
|
||||||
|
if (secondsFromLastUpdate > CommandProcessor.XML_UPDATE_THRESHOLD) { //default 5 second threshold
|
||||||
|
WIN_XML = WindowsEnumeratedXml.getXml();
|
||||||
|
LAST_UPDATED_XML = System.nanoTime();
|
||||||
|
}
|
||||||
|
WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
|
||||||
|
String resultStr = "";
|
||||||
|
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
|
||||||
|
for(String item: resultList) {
|
||||||
|
if (item.contains("hmenu=")) {
|
||||||
|
List<String> list = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@id");
|
||||||
|
if (list.size() > 0)
|
||||||
|
resultStr = list.get(0); //get first id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resultStr = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resultStr = resultStr.replaceAll("[^\\d.]", ""); //remove all non-numeric values
|
||||||
|
//System.out.println("findMenuIdWithXpath: " + resultStr);
|
||||||
|
if (resultStr.isEmpty())
|
||||||
|
appendError("Error: Failed to find window handle matching: " + xpath);
|
||||||
|
else
|
||||||
|
result = Integer.parseInt(resultStr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Point getCenterWindowPosition(WinPtr handle) {
|
public Point getCenterWindowPosition(WinPtr handle) {
|
||||||
Point p = null;
|
Point p = null;
|
||||||
if (handle.isWin32())
|
if (handle.isWin32())
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package org.synthuse.commands;
|
|||||||
|
|
||||||
import org.synthuse.*;
|
import org.synthuse.*;
|
||||||
|
|
||||||
|
import com.sun.jna.platform.win32.WinDef.LPARAM;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.WPARAM;
|
||||||
|
|
||||||
public class WindowsCommands extends BaseCommand {
|
public class WindowsCommands extends BaseCommand {
|
||||||
|
|
||||||
public WindowsCommands(CommandProcessor cp) {
|
public WindowsCommands(CommandProcessor cp) {
|
||||||
@@ -108,4 +111,17 @@ public class WindowsCommands extends BaseCommand {
|
|||||||
return "";
|
return "";
|
||||||
return api.sendWmGetText(handle.hWnd);
|
return api.sendWmGetText(handle.hWnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean cmdSelectMenu(String[] args) {
|
||||||
|
if (!checkArgumentLength(args, 1))
|
||||||
|
return false;
|
||||||
|
WinPtr handle = findHandleWithXpath(args[0]);
|
||||||
|
if (handle.isEmpty())
|
||||||
|
return false;
|
||||||
|
int id = findMenuIdWithXpath(args[0]);
|
||||||
|
//LRESULT result =
|
||||||
|
//System.out.println("PostMessage to " + handle.hWndStr + " for id " + id);
|
||||||
|
api.user32.PostMessage(handle.hWnd, Api.WM_COMMAND, new WPARAM(id), new LPARAM(0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/org/synthuse/test/UnitTestHelper.java
Normal file
79
src/org/synthuse/test/UnitTestHelper.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package org.synthuse.test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
// This class doesn't contain Test, only some methods that are used by the unit tests
|
||||||
|
public class UnitTestHelper {
|
||||||
|
|
||||||
|
static Process runningApp = null;
|
||||||
|
public static void RunApp(String ResourceFilePath) {
|
||||||
|
String tempFilename = ExtractFileFromJar(ResourceFilePath);
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
try {
|
||||||
|
runningApp = runtime.exec(tempFilename);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DestroyApp() {
|
||||||
|
if (runningApp != null)
|
||||||
|
runningApp.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String ExtractFileFromJar(String path) {
|
||||||
|
// Obtain filename from path
|
||||||
|
String[] parts = path.split("/");
|
||||||
|
String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
|
||||||
|
// Split filename to prexif and suffix (extension)
|
||||||
|
String prefix = "";
|
||||||
|
String suffix = null;
|
||||||
|
if (filename != null) {
|
||||||
|
parts = filename.split("\\.", 2);
|
||||||
|
prefix = parts[0];
|
||||||
|
suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null;
|
||||||
|
}
|
||||||
|
File temp = null;
|
||||||
|
try {
|
||||||
|
// Prepare temporary file
|
||||||
|
temp = File.createTempFile(prefix, suffix);
|
||||||
|
temp.deleteOnExit();
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (!temp.exists()) { //some reason the temp file wasn't create so abort
|
||||||
|
System.out.println("File " + temp.getAbsolutePath() + " does not exist.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare buffer for data copying
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int readBytes;
|
||||||
|
// Open and check input stream
|
||||||
|
InputStream is = WpfBridgeTest.class.getResourceAsStream(path);
|
||||||
|
if (is == null) { //check if valid
|
||||||
|
System.out.println("File " + path + " was not found inside JAR.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Open output stream and copy data between source file in JAR and the temporary file
|
||||||
|
OutputStream os = null;
|
||||||
|
try {
|
||||||
|
os = new FileOutputStream(temp);
|
||||||
|
while ((readBytes = is.read(buffer)) != -1) {
|
||||||
|
os.write(buffer, 0, readBytes);
|
||||||
|
}
|
||||||
|
os.close();
|
||||||
|
is.close();
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return temp.getAbsolutePath();
|
||||||
|
// Finally, load the library
|
||||||
|
//System.load(temp.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,11 +20,13 @@ import org.synthuse.Api.User32;
|
|||||||
import com.sun.jna.Native;
|
import com.sun.jna.Native;
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import com.sun.jna.platform.win32.WinUser;
|
import com.sun.jna.platform.win32.WinUser;
|
||||||
|
import com.sun.jna.platform.win32.WinDef.HMENU;
|
||||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||||
import com.sun.jna.platform.win32.WinDef.RECT;
|
import com.sun.jna.platform.win32.WinDef.RECT;
|
||||||
import com.sun.jna.ptr.PointerByReference;
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
|
||||||
public class WinApiTest {
|
public class WinApiTest {
|
||||||
|
Api api = new Api();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -37,7 +39,7 @@ public class WinApiTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void output(String val) {
|
public static void output(String val) {
|
||||||
System.out.println(val);
|
//System.out.println(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
//copied and modified slightly from WindowInfo class
|
//copied and modified slightly from WindowInfo class
|
||||||
@@ -50,6 +52,8 @@ public class WinApiTest {
|
|||||||
String className = "";
|
String className = "";
|
||||||
String processName = "";
|
String processName = "";
|
||||||
long pid = 0;
|
long pid = 0;
|
||||||
|
|
||||||
|
Map<String, String> extra = null;
|
||||||
|
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
output("Calling GetWindowTextA");
|
output("Calling GetWindowTextA");
|
||||||
@@ -68,6 +72,32 @@ public class WinApiTest {
|
|||||||
className = Native.toString(buffer2);
|
className = Native.toString(buffer2);
|
||||||
output("GetClassName returned: " + className);
|
output("GetClassName returned: " + className);
|
||||||
|
|
||||||
|
HMENU hmenu = Api.User32.instance.GetMenu(hWnd);
|
||||||
|
//hmenu = Api.User32.instance.GetSubMenu(hmenu, 0);
|
||||||
|
if (hmenu != null) { //menu item count
|
||||||
|
int menuCount = Api.User32.instance.GetMenuItemCount(hmenu);
|
||||||
|
if (menuCount > 0) {
|
||||||
|
if (extra == null)
|
||||||
|
extra = new LinkedHashMap<String, String>();
|
||||||
|
extra.put("menuCount", menuCount + "");
|
||||||
|
System.out.println("className: " + className);
|
||||||
|
System.out.println("text: " + text);
|
||||||
|
System.out.println("menuCount: " + menuCount);
|
||||||
|
|
||||||
|
for (int m = 0 ; m < menuCount ; m++) {
|
||||||
|
String menuTxt = api.GetMenuItemText(hmenu, m);
|
||||||
|
System.out.println("Menu Text: " + menuTxt);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (menuCount == 5) {
|
||||||
|
HMENU smenu = Api.User32.instance.GetSubMenu(hmenu, 0);
|
||||||
|
boolean result = Api.User32.instance.TrackPopupMenu(smenu, 0, 1, 1, 0, hWnd, 0);
|
||||||
|
System.out.println("TrackPopupMenu: " + result);
|
||||||
|
System.out.println("last error: " + Api.Kernel32.instance.GetLastError());
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rect = new RECT();
|
rect = new RECT();
|
||||||
output("Calling GetWindowRect");
|
output("Calling GetWindowRect");
|
||||||
User32.instance.GetWindowRect(hWnd, rect);
|
User32.instance.GetWindowRect(hWnd, rect);
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
package org.synthuse.test;
|
package org.synthuse.test;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -16,28 +10,17 @@ import org.synthuse.*;
|
|||||||
|
|
||||||
public class WpfBridgeTest {
|
public class WpfBridgeTest {
|
||||||
|
|
||||||
static Process mockApp = null;
|
|
||||||
public static void RunMockWpfApp() {
|
|
||||||
String tempFilename = ExtractFileFromJar("/org/synthuse/test/WpfMockTestApp.exe");
|
|
||||||
Runtime runtime = Runtime.getRuntime();
|
|
||||||
try {
|
|
||||||
mockApp = runtime.exec(tempFilename);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUpBeforeClass() {
|
public static void setUpBeforeClass() {
|
||||||
//this runs only once for this class
|
//this runs only once for this class
|
||||||
RunMockWpfApp();
|
UnitTestHelper.RunApp("/org/synthuse/test/WpfMockTestApp.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void tearDownAfterClass() {
|
public static void tearDownAfterClass() {
|
||||||
//this runs only once for this class
|
//this runs only once for this class
|
||||||
if (mockApp != null)
|
UnitTestHelper.DestroyApp();
|
||||||
mockApp.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -139,54 +122,4 @@ public class WpfBridgeTest {
|
|||||||
System.out.println(w);
|
System.out.println(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String ExtractFileFromJar(String path) {
|
|
||||||
// Obtain filename from path
|
|
||||||
String[] parts = path.split("/");
|
|
||||||
String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
|
|
||||||
// Split filename to prexif and suffix (extension)
|
|
||||||
String prefix = "";
|
|
||||||
String suffix = null;
|
|
||||||
if (filename != null) {
|
|
||||||
parts = filename.split("\\.", 2);
|
|
||||||
prefix = parts[0];
|
|
||||||
suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null;
|
|
||||||
}
|
|
||||||
File temp = null;
|
|
||||||
try {
|
|
||||||
// Prepare temporary file
|
|
||||||
temp = File.createTempFile(prefix, suffix);
|
|
||||||
temp.deleteOnExit();
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (!temp.exists()) { //some reason the temp file wasn't create so abort
|
|
||||||
System.out.println("File " + temp.getAbsolutePath() + " does not exist.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare buffer for data copying
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int readBytes;
|
|
||||||
// Open and check input stream
|
|
||||||
InputStream is = WpfBridgeTest.class.getResourceAsStream(path);
|
|
||||||
if (is == null) { //check if valid
|
|
||||||
System.out.println("File " + path + " was not found inside JAR.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Open output stream and copy data between source file in JAR and the temporary file
|
|
||||||
OutputStream os = null;
|
|
||||||
try {
|
|
||||||
os = new FileOutputStream(temp);
|
|
||||||
while ((readBytes = is.read(buffer)) != -1) {
|
|
||||||
os.write(buffer, 0, readBytes);
|
|
||||||
}
|
|
||||||
os.close();
|
|
||||||
is.close();
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return temp.getAbsolutePath();
|
|
||||||
// Finally, load the library
|
|
||||||
//System.load(temp.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user