Fixed highlighting around WPF and Silverlight, fixed windows commands to use WPF runtimeIds,Adding Windows Message hook feature

When targeting WPF and silverlight applications synthuse will now target
each object with a red rectangle, just like it does with native win 32
applications.
Windows commands like setfocus and such are now supported with UIA
objects like (WPF, WinForm, Silverlight).
Adding support for hooking in to the Message Queue of a target window to
see what Messages are being sent, this will allow one to possible resend
the messages back for automation purposes.  This feature is not fully
working yet, but is close.
This commit is contained in:
Edward Jakubowski
2014-05-21 08:12:11 -04:00
parent c36aa19753
commit 1721d2a130
51 changed files with 2282 additions and 125 deletions

View File

@@ -77,6 +77,13 @@ public class Api {
public static int PROCESS_VM_READ = 0x0010;
public static int PS_SOLID = 0x0;
public static int PS_DASH = 0x1;
public static int PS_DOT = 0x2;
public static int PS_DASHDOT = 0x3;
public static int PS_DASHDOTDOT = 0x4;
public static int PS_NULL = 0x5;
public static int PS_INSIDEFRAME = 0x6;
public static int HOLLOW_BRUSH = 0x5;
public static int WM_PAINT = 0x0F;
@@ -521,14 +528,19 @@ public class Api {
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
// creates highlight around selected window
public static void highlightWindow(HWND hwnd){
RECT rect = new RECT();
User32.instance.GetWindowRect(hwnd, rect);
//System.out.println("RECT: " + rect.left + "," + rect.top + "," + (rect.right - rect.left) + "," + (rect.bottom - rect.top));
highlightWindow(hwnd, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
}
// creates highlight around selected window
public static void highlightWindow(HWND hwnd, int x, int y, int x2, int y2){
//COLORREF i.e. 0x00804070 Red = 0x70 green = 0x40 blue = 0x80
//g_hRectanglePen = CreatePen (PS_SOLID, 3, RGB(256, 0, 0));
HPEN rectPen = Gdi32.instance.CreatePen(PS_SOLID, 3, 0x00000099); //RGB(255, 0, 0)
RECT rect = new RECT();
User32.instance.GetWindowRect(hwnd, rect);
HDC dc = User32.instance.GetWindowDC(hwnd);
if (dc != null) {
// Select our created pen into the DC and backup the previous pen.
@@ -538,7 +550,7 @@ public class Api {
HANDLE prevBrush = Gdi32.instance.SelectObject(dc, Gdi32.instance.GetStockObject(HOLLOW_BRUSH));
// Draw a rectangle in the DC covering the entire window area of the found window.
Gdi32.instance.Rectangle (dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
Gdi32.instance.Rectangle (dc, x, y, x2, y2);
// Reinsert the previous pen and brush into the found window's DC.
Gdi32.instance.SelectObject(dc, prevPen);

View File

@@ -0,0 +1,142 @@
package org.synthuse;
import javax.swing.JFrame;
import javax.swing.JToolBar;
import java.awt.BorderLayout;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.HOOKPROC;
import com.sun.jna.platform.win32.WinUser.MSG;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MessageHookFrame extends JFrame {
private static final long serialVersionUID = -5863279004595502801L;
public static final int WH_CALLWNDPROC = 4;
public static final int WH_GETMESSAGE = 3;
public static final int WH_KEYBOARD_LL = 13;
private JTextArea textArea;
private JButton btnSave;
private JButton btnStartMsgHook;
private JButton btnPause;
private JButton btnClear;
public static HHOOK hHook = null;
//public static LowLevelKeyboardProc lpfn;
public static volatile boolean quit = false;
public MessageHookFrame() {
setTitle("Message Hook");
setBounds(100, 100, 700, 367);
JToolBar toolBar = new JToolBar();
getContentPane().add(toolBar, BorderLayout.NORTH);
btnStartMsgHook = new JButton("Start Hook");
btnStartMsgHook.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (btnStartMsgHook.getText().equals("Start Hook"))
{ //start Message Hook
btnStartMsgHook.setText("Stop Hook");
createMessageHook();
}
else
{ //stop message hook
btnStartMsgHook.setText("Start Hook");
stopMessageHook();
}
}
});
toolBar.add(btnStartMsgHook);
btnPause = new JButton("Pause");
btnPause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
toolBar.add(btnPause);
btnSave = new JButton("Save");
btnSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
toolBar.add(btnSave);
btnClear = new JButton("Clear");
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
textArea.setText("");
}
});
toolBar.add(btnClear);
JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
textArea = new JTextArea();
scrollPane.setViewportView(textArea);
super.setAlwaysOnTop(SynthuseDlg.config.isAlwaysOnTop());
}
public void createMessageHook() {
if (hHook != null)
return; //hook already running don't add anymore
System.out.println("starting global message hook");
HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
int threadId = Kernel32.INSTANCE.GetCurrentThreadId();
HOOKPROC lpfn = new HOOKPROC() {
@SuppressWarnings("unused")
public LRESULT callback(int nCode, WPARAM wParam, LPARAM lParam) {
//System.out.println("Msg " + nCode);
return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam, lParam);
}
};
hHook = User32.INSTANCE.SetWindowsHookEx(WH_CALLWNDPROC, lpfn, hMod, threadId);
if (hHook == null)
return;
MSG msg = new MSG();
try {
while (!quit) {
User32.INSTANCE.PeekMessage(msg, null, 0, 0, 1);
if (msg.message == User32.WM_HOTKEY){ // && msg.wParam.intValue() == 1
msg = new MSG(); //must clear msg so it doesn't repeat
}
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("message loop stopped");
unhook();
}
public void unhook() {
if (hHook == null)
return;
if (!User32.INSTANCE.UnhookWindowsHookEx(hHook))
System.out.println("Failed to unhook");
System.out.println("Unhooked");
hHook = null;
}
//stops Keyboard hook and causes the unhook command to be called
public static void stopMessageHook() {
quit = true;
}
}

View File

@@ -0,0 +1,6 @@
package org.synthuse;
public class MsgHook {
}

View File

@@ -13,32 +13,15 @@ import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;
import javax.swing.JSplitPane;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.*;
import java.awt.Component;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import java.awt.Dimension;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
/*
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
@@ -47,9 +30,6 @@ import com.jgoodies.forms.factories.FormFactory;
*/
import com.sun.jna.platform.win32.WinDef.HWND;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
@@ -60,8 +40,6 @@ import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextPane;
import org.synthuse.Api.User32;
import org.synthuse.DragTarget.dragEvents;
@@ -72,7 +50,7 @@ public class SynthuseDlg extends JFrame {
/**
*
*/
public static String VERSION_STR = "1.1.8";
public static String VERSION_STR = "1.2.0";
public static String RES_STR_MAIN_ICON = "/org/synthuse/img/gnome-robots.png";
public static String RES_STR_REFRESH_IMG = "/org/synthuse/img/rapidsvn.png";
@@ -82,6 +60,9 @@ public class SynthuseDlg extends JFrame {
public static String RES_STR_FIND_IMG = "/org/synthuse/img/edit-find-3.png";
public static String RES_STR_SETACTION_IMG = "/org/synthuse/img/document-new-5.png";
public static String RES_STR_CANCEL_IMG = "/org/synthuse/img/document-close-2.png";
public static String RES_STR_PREFERENCES_IMG = "/org/synthuse/img/preferences-desktop.png";
private static final int STRUT_WIDTH = 10;
public static List<String> actionListQueue = new ArrayList<String>();
private static final long serialVersionUID = 1L;
@@ -99,8 +80,10 @@ public class SynthuseDlg extends JFrame {
private String lastRuntimeId ="";
private JComboBox<String> cmbXpath;
private JButton btnTestIde;
private JButton btnAdvanced;
private TestIdeFrame testIde = null;
private MessageHookFrame msgHook = null;
private int targetX;
private int targetY;
private UiaBridge uiabridge = new UiaBridge();
@@ -141,7 +124,7 @@ public class SynthuseDlg extends JFrame {
rdbtnWindows.setSelected(true);
toolBar.add(rdbtnWindows);
Component horizontalStrut = Box.createHorizontalStrut(20);
Component horizontalStrut = Box.createHorizontalStrut(STRUT_WIDTH);
toolBar.add(horizontalStrut);
JRadioButton rdbtnUrl = new JRadioButton("Url: ");
@@ -158,7 +141,7 @@ public class SynthuseDlg extends JFrame {
cmbUrl.setEditable(true);
toolBar.add(cmbUrl);
Component horizontalStrut_1 = Box.createHorizontalStrut(20);
Component horizontalStrut_1 = Box.createHorizontalStrut(STRUT_WIDTH);
toolBar.add(horizontalStrut_1);
btnRefresh = new JButton(" Refresh ");
@@ -172,7 +155,7 @@ public class SynthuseDlg extends JFrame {
btnRefresh.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_REFRESH_IMG)));
toolBar.add(btnRefresh);
Component horizontalStrut_3 = Box.createHorizontalStrut(20);
Component horizontalStrut_3 = Box.createHorizontalStrut(STRUT_WIDTH);
toolBar.add(horizontalStrut_3);
btnTestIde = new JButton("Test IDE");
@@ -192,8 +175,40 @@ public class SynthuseDlg extends JFrame {
btnTestIde.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_TESTIDE_IMG)));
toolBar.add(btnTestIde);
Component horizontalStrut_2 = Box.createHorizontalStrut(20);
Component horizontalStrut_2 = Box.createHorizontalStrut(STRUT_WIDTH);
toolBar.add(horizontalStrut_2);
btnAdvanced = new JButton("Advanced");
btnAdvanced.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_PREFERENCES_IMG)));
btnAdvanced.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JPopupMenu menu = new JPopupMenu();
ActionListener menuListener = new ActionListener() {
public void actionPerformed(ActionEvent event) {
//System.out.println("Popup menu item [" + event.getActionCommand() + "] was pressed.");
if (event.getActionCommand() == "Message Hook"){
if (msgHook == null)
msgHook = new MessageHookFrame();
msgHook.setVisible(true);
}
}
};
JMenuItem mnMessageHook = new JMenuItem("Message Hook");
mnMessageHook.addActionListener(menuListener);
menu.add(mnMessageHook);
JMenuItem mnSettings = new JMenuItem("Settings");
mnSettings.setEnabled(false);
mnSettings.addActionListener(menuListener);
menu.add(mnSettings);
Component c = (Component) e.getSource();
menu.show(c, -1, c.getHeight());
}
});
toolBar.add(btnAdvanced);
Component horizontalStrut_4 = Box.createHorizontalStrut(STRUT_WIDTH);
toolBar.add(horizontalStrut_4);
JButton helpBtn = new JButton("Help");
helpBtn.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_HELP_IMG)));
@@ -480,9 +495,12 @@ public class SynthuseDlg extends JFrame {
String parentStr = Api.GetHandleAsString(User32.instance.GetParent(hwnd));
String enumProperties = "";
if (!SynthuseDlg.config.isUiaBridgeDisabled())
enumProperties = uiabridge.getWindowInfo(targetX, targetY, WindowInfo.UIA_PROPERTY_LIST);
enumProperties = uiabridge.getWindowInfo(targetX, targetY, WindowInfo.UIA_PROPERTY_LIST_ADV);
String runtimeId = WindowInfo.getRuntimeIdFromProperties(enumProperties);
lblStatus.setText("rid:" + runtimeId + " class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y: " + targetX + ", " + targetY);
String framework = WindowInfo.getFrameworkFromProperties(enumProperties);
Rectangle rect = UiaBridge.getBoundaryRect(enumProperties);
Point offsetPoint = WindowInfo.findOffset(rect, targetX, targetY);
lblStatus.setText("rid:" + runtimeId + " " + framework + " class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y (" + targetX + ", " + targetY + ") offset: " + offsetPoint.x + ", " + offsetPoint.y);
if (!lastDragHwnd.equals(handleStr) || !lastRuntimeId.equals(runtimeId)) {
if (!lastDragHwnd.isEmpty()) {
Api.refreshWindow(Api.GetHandleFromString(lastDragHwnd));
@@ -490,7 +508,12 @@ public class SynthuseDlg extends JFrame {
lastDragHwnd = handleStr;
lastRuntimeId = runtimeId;
//lastDragHwnd = (hwnd + "");
Api.highlightWindow(hwnd);
if (framework.equals(UiaBridge.FRAMEWORK_ID_WPF) || framework.equals(UiaBridge.FRAMEWORK_ID_SILVER))
{// WPF and Silverlight apps don't expose their child windows boundaries the same as win32 apps
Api.highlightWindow(Api.User32.instance.GetDesktopWindow(), rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
}
else
Api.highlightWindow(hwnd);
XpathManager.buildXpathStatementThreaded(hwnd, enumProperties, textPane, xpathEvents);
}
}

View File

@@ -1,6 +1,7 @@
package org.synthuse;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.*;
import javax.swing.JOptionPane;
@@ -8,7 +9,10 @@ import javax.swing.JOptionPane;
public class UiaBridge {
public static String CACHED_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty,ValueProperty,BoundingRectangleProperty";
public static final String FRAMEWORK_ID_WPF = "WPF";
public static final String FRAMEWORK_ID_SILVER = "Silverlight";
public static final String FRAMEWORK_ID_WINFORM = "WinForm";
public static final String FRAMEWORK_ID_WIN = "Win32";
static
{
@@ -128,18 +132,41 @@ public class UiaBridge {
public native String[] getProperties(String runtimeIdValue);
public native String[] getPropertiesAndValues(String runtimeIdValue);
*/
public static String replaceEscapedCodes(String input) {
//&#44; is a comma ,
String result = input;
result = result.replaceAll("&#44;", ",");
result = result.replaceAll("&lt;", "<");
result = result.replaceAll("&gt;", ">");
result = result.replaceAll("&apos;", "'");
result = result.replaceAll("&quot;", "\"");
result = result.replaceAll("&amp;", "&");
return result;
}
public Point getCenterOfElement(String runtimeIdValue) {
Point p = new Point();
String boundary = getWindowInfo(runtimeIdValue, "BoundingRectangleProperty");
boundary = WindowInfo.replaceEscapedCodes(boundary);
//System.out.println("runtimeId: " + runtimeIdValue + ", 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;
String boundaryProperty = getWindowInfo(runtimeIdValue, "BoundingRectangleProperty");
Rectangle rect = getBoundaryRect(boundaryProperty);
p.x = ((rect.width) /2) + rect.x;
p.y = ((rect.height) /2) + rect.y;
return p;
}
//BoundingRectangleProperty is the last property listed in comma separated properties string
public static Rectangle getBoundaryRect(String properties) {
Rectangle rect = new Rectangle();
String[] propSplt = properties.split(",");
if (propSplt.length > 0)
{
String[] boundarySplt = replaceEscapedCodes(propSplt[propSplt.length - 1]).split(",");
if (boundarySplt.length == 4 )
rect.x = Integer.parseInt(boundarySplt[0]);
rect.y = Integer.parseInt(boundarySplt[1]);
rect.width = Integer.parseInt(boundarySplt[2]);
rect.height = Integer.parseInt(boundarySplt[3]);
}
return rect;
}
}

View File

@@ -46,6 +46,14 @@ public class WinPtr {
return (runtimeIdTest.contains("-"));
}
public void convertToNativeHwnd()
{
if (isWpfRuntimeIdFormat(runtimeId)){
hWndStr = runtimeId.split("-")[1];
hWnd = Api.GetHandleFromString(hWndStr);
}
}
public String toString() {
if (isWin32() && !hWndStr.equals(""))
return hWndStr;

View File

@@ -7,6 +7,8 @@
package org.synthuse;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -25,6 +27,7 @@ import com.sun.jna.ptr.PointerByReference;
public class WindowInfo {
public static String UIA_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty,ValueProperty";
public static String UIA_PROPERTY_LIST_ADV = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty,ValueProperty,BoundingRectangleProperty";
public static String UIA_RUNTIME_ID = "RuntimeIdProperty";
public static String UIA_BOUNDING_RECT = "BoundingRectangleProperty";
public static int MAX_TEXT_SIZE = 200;
@@ -46,6 +49,7 @@ public class WindowInfo {
public String runtimeId = "";
public int menus = 0;
public HMENU menu = null;
public boolean useUiaBridge = false;
public Map<String, String> extra = null;
@@ -97,20 +101,6 @@ public class WindowInfo {
extra = new LinkedHashMap<String, String>();
extra.put("tvCount", tvCount.intValue() + "");
}
/*
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];
User32.instance.GetClassName(hWnd, buffer2, 1026);
@@ -151,6 +141,9 @@ public class WindowInfo {
if (isChild) {
parent = User32.instance.GetParent(hWnd);
parentStr = Api.GetHandleAsString(parent);
// test to see if uiaBridge should be used on this child
if (this.className.startsWith("HwndWrapper") || this.className.startsWith("MicrosoftSilverlight") || this.className.startsWith("GeckoPluginWindow"))
useUiaBridge = true;
}
else {
@@ -160,7 +153,9 @@ public class WindowInfo {
Pointer process = Kernel32.instance.OpenProcess(Api.PROCESS_QUERY_INFORMATION | Api.PROCESS_VM_READ, false, pointer.getValue());
Psapi.instance.GetModuleBaseNameW(process, null, buffer2, 512);
processName = Native.toString(buffer2);
//test to see if uiaBridge should be used on this parent
if (this.className.startsWith("HwndWrapper") || this.className.startsWith("WindowsForms"))
useUiaBridge = true;
}
this.hwnd = hWnd;
hwndStr = Api.GetHandleAsString(hWnd);
@@ -168,23 +163,12 @@ public class WindowInfo {
this.hwndStr = "";
}
public static String replaceEscapedCodes(String input) {
//&#44; is a comma ,
String result = input;
result = result.replaceAll("&#44;", ",");
result = result.replaceAll("&lt;", "<");
result = result.replaceAll("&gt;", ">");
result = result.replaceAll("&apos;", "'");
result = result.replaceAll("&quot;", "\"");
result = result.replaceAll("&amp;", "&");
return result;
}
//support for WPF, Silverlight, WinForms
public WindowInfo(String enumProperties, boolean isChild) {
//WPF_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty,ValueProperty";
String[] spltProperties = enumProperties.split(",");
this.isChild = isChild;
this.useUiaBridge = true;
if (SynthuseDlg.config.isFilterUiaDisabled()) { //use wildcard mode
extra = new LinkedHashMap<String, String>();
for(String prop: spltProperties) {
@@ -233,13 +217,13 @@ public class WindowInfo {
if (spltProperties.length > 3)
this.framework = spltProperties[3];
if (spltProperties.length > 4)
this.controlType = replaceEscapedCodes(spltProperties[4]);
this.controlType = UiaBridge.replaceEscapedCodes(spltProperties[4]);
if (spltProperties.length > 5)
this.className = replaceEscapedCodes(spltProperties[5]);
this.className = UiaBridge.replaceEscapedCodes(spltProperties[5]);
if (spltProperties.length > 6)
this.text = replaceEscapedCodes(spltProperties[6]);
this.text = UiaBridge.replaceEscapedCodes(spltProperties[6]);
if (spltProperties.length > 7)
this.value = replaceEscapedCodes(spltProperties[7]);
this.value = UiaBridge.replaceEscapedCodes(spltProperties[7]);
if (this.className == "")
this.className = this.controlType;
if (text != null)
@@ -266,6 +250,7 @@ public class WindowInfo {
*/
}
public static String getRuntimeIdFromProperties(String enumProperties)
{
String[] spltProperties = enumProperties.split(",");
@@ -274,6 +259,26 @@ public class WindowInfo {
return "";
}
public static String getFrameworkFromProperties(String enumProperties)
{
String[] spltProperties = enumProperties.split(",");
if (spltProperties.length > 3)
return spltProperties[3];
return "";
}
public static Point findOffset(Rectangle rect, int xPos, int yPos)
{
Point offset = new Point();
int x = ((rect.width) /2) + rect.x;
int y = ((rect.height) /2) + rect.y;
offset.x = xPos - x;
offset.y = yPos - y;
return offset;
}
public String toString() {
return String.format("%s \"%s\" [%s] (%s) {%s}", framework, text, className, controlType, hwndStr);
}

View File

@@ -79,62 +79,62 @@ public class WindowsEnumeratedXml implements Runnable{
public static String getXml() {
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
final List<String> wpfParentList = new ArrayList<String>();//HwndWrapper
final List<String> silverlightParentList = new ArrayList<String>();//MicrosoftSilverlight
final List<String> winFormParentList = new ArrayList<String>();//class="WindowsForms*"
//wpf.setTouchableOnly(false);
//wpf.countChildrenWindows();//fix for missing cached elements
class ChildWindowCallback implements WinUser.WNDENUMPROC {
@Override
public boolean callback(HWND hWnd, Pointer lParam) {
WindowInfo wi = new WindowInfo(hWnd, true);
infoList.put(wi.hwndStr, wi);
if (wi.className.startsWith("HwndWrapper"))
wpfParentList.add(wi.hwndStr);
if (wi.className.startsWith("MicrosoftSilverlight") || wi.className.startsWith("GeckoPluginWindow"))
silverlightParentList.add(wi.hwndStr);
return true;
}
}
HWND desktopRootHwnd = Api.User32.instance.GetDesktopWindow();
WindowInfo wi = new WindowInfo(desktopRootHwnd, false);
wi.controlType = "DesktopRoot";
infoList.put(wi.hwndStr, wi);
class ParentWindowCallback implements WinUser.WNDENUMPROC {
@Override
public boolean callback(HWND hWnd, Pointer lParam) {
WindowInfo wi = new WindowInfo(hWnd, false);
infoList.put(wi.hwndStr, wi);
if (wi.className.startsWith("HwndWrapper"))
wpfParentList.add(wi.hwndStr);
if (wi.className.startsWith("WindowsForms"))
winFormParentList.add(wi.hwndStr);
Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0));
infoList.putAll(EnumerateWin32ChildWindows(hWnd));
return true;
}
}
}
Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0);
//process all windows that have been flagged for uiaBridge (useUiaBridge == true)
appendUiaBridgeWindows(infoList);
return generateWindowsXml(infoList, "EnumeratedWindows");
}
public static void appendUiaBridgeWindows(Map<String, WindowInfo> infoList)
{
//Enumerate WPF, WinForm, Silverlight windows and add to list
if (!SynthuseDlg.config.isUiaBridgeDisabled())
{
UiaBridge uiabridge = new UiaBridge();
for (String handle : wpfParentList) {
Map<String, WindowInfo> wpfInfoList = EnumerateWindowsWithUiaBridge(uiabridge, handle, "*");
infoList.putAll(wpfInfoList);
}
for (String handle : winFormParentList) {
//System.out.println("winform parent " + handle);
Map<String, WindowInfo> winFormInfoList = EnumerateWindowsWithUiaBridge(uiabridge, handle, "*");
infoList.putAll(winFormInfoList);
}
for (String handle : silverlightParentList) {
Map<String, WindowInfo> slInfoList = EnumerateWindowsWithUiaBridge(uiabridge, handle, "Silverlight");
infoList.putAll(slInfoList);
}
Map<String, WindowInfo> uiaInfoList = new LinkedHashMap<String, WindowInfo>();
for (String handle : infoList.keySet()) {
if (infoList.get(handle).useUiaBridge) {
uiaInfoList.putAll(EnumerateWindowsWithUiaBridge(uiabridge, handle, "*"));
}
}
infoList.putAll(uiaInfoList);
}
return generateWindowsXml(infoList, "EnumeratedWindows");
//return infoList;
}
public static Map<String, WindowInfo> EnumerateWin32ChildWindows(HWND parentHwnd)
{
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
class ChildWindowCallback implements WinUser.WNDENUMPROC {
@Override
public boolean callback(HWND hWnd, Pointer lParam) {
WindowInfo wi = new WindowInfo(hWnd, true);
infoList.put(wi.hwndStr, wi);
return true;
}
}
Api.User32.instance.EnumChildWindows(parentHwnd, new ChildWindowCallback(), new Pointer(0));
return infoList;
}
public static String generateWindowsXml(Map<String, WindowInfo> infoList, String rootElementName)
@@ -163,17 +163,17 @@ public class WindowsEnumeratedXml implements Runnable{
Element win = null;
if (w.framework.equals("win32"))
win = doc.createElement("win");
else if (w.framework.equals("WPF"))
else if (w.framework.equals(UiaBridge.FRAMEWORK_ID_WPF))
{
win = doc.createElement("wpf");
++wpfCount;
}
else if (w.framework.equals("WinForm"))
else if (w.framework.equals(UiaBridge.FRAMEWORK_ID_WINFORM))
{
win = doc.createElement("winfrm");
++winFormCount;
}
else if (w.framework.equals("Silverlight"))
else if (w.framework.equals(UiaBridge.FRAMEWORK_ID_SILVER))
{
win = doc.createElement("silver");
++silverlightCount;

View File

@@ -6,11 +6,14 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.synthuse.*;
import com.sun.jna.platform.win32.WinDef.HWND;
public class BaseCommand {
static String WIN_XML = "";
@@ -132,7 +135,14 @@ public class BaseCommand {
}
else
{ // native target refresh
infoList = new LinkedHashMap<String, WindowInfo>();
HWND parentHwnd = Api.GetHandleFromString(resultHwndStr);
WindowInfo wi = new WindowInfo(parentHwnd, false);
infoList.put(wi.hwndStr, wi);
infoList.putAll(WindowsEnumeratedXml.EnumerateWin32ChildWindows(parentHwnd));
//WindowsEnumeratedXml.appendUiaBridgeWindows(infoList); //if we need this we should specify a runtimeID handle instead
newXml = WindowsEnumeratedXml.generateWindowsXml(infoList, "updates");
System.out.println("newNativeXml: " + newXml);
}
int pos = WIN_XML.indexOf(resultStr);

View File

@@ -18,9 +18,9 @@ public class MouseCommands extends BaseCommand {
if (handle.isEmpty())
return false;
String wtype = getWindowTypeWithXpath(args[0]);
//System.out.println("wtype: " + wtype + " hwnd " + handle.hWnd + " hmenu " + handle.hmenuStr + " pos " + handle.hmenuPos);
System.out.println("wtype: " + wtype + " hwnd " + handle.hWnd + " hmenu " + handle.hmenuStr + " pos " + handle.hmenuPos);
Point p = getCenterWindowPosition(handle, wtype);
//System.out.println("cmdClick: " + p.x + "," + p.y);
System.out.println("cmdClick: " + p.x + "," + p.y);
RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y);
RobotMacro.leftClickMouse();
return true;

View File

@@ -17,6 +17,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.activateWindow(handle.hWnd);
//api.showWindow(handle);
return true;
@@ -28,6 +29,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.minimizeWindow(handle.hWnd);
return true;
}
@@ -38,6 +40,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.maximizeWindow(handle.hWnd);
return true;
}
@@ -48,6 +51,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.restoreWindow(handle.hWnd);
return true;
}
@@ -58,6 +62,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.hideWindow(handle.hWnd);
return true;
}
@@ -68,6 +73,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.showWindow(handle.hWnd);
return true;
}
@@ -78,6 +84,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.switchToThisWindow(handle.hWnd, true);
return true;
}
@@ -89,6 +96,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.closeWindow(handle.hWnd);
return true;
}
@@ -99,6 +107,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return false;
handle.convertToNativeHwnd();
api.sendWmSetText(handle.hWnd, args[1]);
return true;
}
@@ -109,6 +118,7 @@ public class WindowsCommands extends BaseCommand {
WinPtr handle = findHandleWithXpath(args[0]);
if (handle.isEmpty())
return "";
handle.convertToNativeHwnd();
return api.sendWmGetText(handle.hWnd);
}
@@ -119,6 +129,7 @@ public class WindowsCommands extends BaseCommand {
if (handle.isEmpty())
return false;
int id = findMenuIdWithXpath(args[0]);
handle.convertToNativeHwnd();
//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));
@@ -133,6 +144,7 @@ public class WindowsCommands extends BaseCommand {
if (handle.isEmpty())
return false;
int id = Integer.parseInt(args[1]); //context menu id is supplied as second argument
handle.convertToNativeHwnd();
//LRESULT result =
System.out.println("PostMessage to " + handle.toString() + " for id " + id + " - " + Api.MAKELONG(id, 0));
//api.user32.PostMessage(handle.hWnd, Api.WM_COMMAND, new WPARAM(id), new LPARAM(0));

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B