Synthuse version 1.0.5

base version by ejakubowski
This commit is contained in:
Edward Jakubowski
2014-02-16 21:56:24 -05:00
parent 5cc705777b
commit 2a7d618f59
35 changed files with 3417 additions and 0 deletions

399
src/org/synthuse/Api.java Normal file
View File

@@ -0,0 +1,399 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.Point;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HDC;
import com.sun.jna.platform.win32.WinDef.HPEN;
import com.sun.jna.platform.win32.WinNT.HANDLE;
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.WinUser.WNDENUMPROC;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.W32APIOptions;
public class Api {
public static int WM_SETTEXT = 0x000c;
public static int WM_GETTEXT = 0x000D;
public static int WM_GETTEXTLENGTH = 0x000E;
public static int WM_MOUSEMOVE = 0x200;
public static int WM_LBUTTONDOWN = 0x0201;
public static int WM_LBUTTONUP = 0x0202;
public static int WM_LBUTTONDBLCLK = 0x203;
public static int WM_RBUTTONDOWN = 0x0204;
public static int WM_RBUTTONUP = 0x0205;
public static int WM_RBUTTONDBLCLK = 0x206;
public static int WM_MBUTTONDOWN = 0x207;
public static int WM_MBUTTONUP = 0x208;
public static int WM_MBUTTONDBLCLK = 0x209;
public static int WM_MOUSEWHEEL = 0x20A;
public static int WM_MOUSEHWHEEL = 0x20E;
public static int WM_MOUSEHOVER = 0x2A1;
public static int WM_NCMOUSELEAVE = 0x2A2;
public static int WM_MOUSELEAVE = 0x2A3;
public static int WM_CLOSE = 0x10;
public static int WM_DESTROY = 0x0002;
public static int WM_NCDESTROY = 0x0082;
public static int WM_QUIT = 0x12;
public static int WM_SETFOCUS = 0x0007;
public static int WM_NEXTDLGCTL = 0x0028;
public static int WM_ENABLE = 0x000A;
public static int WM_KEYFIRST = 0x100;
public static int WM_KEYDOWN = 0x100;
public static int WM_KEYUP = 0x101;
public static int WM_CHAR = 0x102;
public static int WM_DEADCHAR = 0x103;
public static int WM_SYSKEYDOWN = 0x104;
public static int WM_SYSKEYUP = 0x105;
public static int WM_SYSCHAR = 0x106;
public static int WM_CUT = 0x300;
public static int WM_COPY = 0x301;
public static int WM_PASTE = 0x302;
public static int WM_CLEAR = 0x303;
public static int WM_UNDO = 0x304;
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_READ = 0x0010;
public static int PS_SOLID = 0x0;
public static int HOLLOW_BRUSH = 0x5;
public static int WM_PAINT = 0x0F;
public static int WM_SETREDRAW = 0x0B;
public static int WM_ERASEBKGND = 0x14;
public static int RDW_FRAME = 0x0400;
public static int RDW_INVALIDATE = 0x0001;
public static int RDW_UPDATENOW = 0x0100;
public static int RDW_ALLCHILDREN = 0x0080;
public static int VK_SHIFT = 16;
public static int VK_LSHIFT = 0xA0;
public static int VK_RSHIFT = 0xA1;
public static int VK_CONTROL = 17;
public static int VK_LCONTROL = 0xA2;
public static int VK_RCONTROL = 0xA3;
public static int VK_MENU = 18;
public static int VK_LMENU = 0xA4;
public static int VK_RMENU = 0xA5;
public static int CWP_ALL = 0x0000; // Does not skip any child windows
public User32 user32;
public Psapi psapi;
public Kernel32 kernel32;
public static final int POINT_Y(long i)
{
return (int) (i >> 32);
}
public static final int POINT_X(long i)
{
return (int) (i & 0xFFFF);
}
public interface User32 extends W32APIOptions {
User32 instance = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
boolean ShowWindow(HWND hWnd, int nCmdShow);
boolean SetForegroundWindow(HWND hWnd);
void SwitchToThisWindow(HWND hWnd, boolean fAltTab);
HWND SetFocus(HWND hWnd);
HWND FindWindow(String winClass, String title);
LRESULT SendMessage(HWND hWnd, int Msg, WPARAM wParam, LPARAM lParam);
LRESULT SendMessageA(HWND editHwnd, int wmGettext, long l, byte[] lParamStr);
boolean DestroyWindow(HWND hWnd);
boolean EnumWindows (WNDENUMPROC wndenumproc, int lParam);
boolean EnumChildWindows(HWND hWnd, WNDENUMPROC lpEnumFunc, Pointer data);
HWND GetParent(HWND hWnd);
boolean IsWindowVisible(HWND hWnd);
int GetWindowRect(HWND hWnd, RECT r);
HDC GetWindowDC(HWND hWnd);
int ReleaseDC(HWND hWnd, HDC hDC);
boolean InvalidateRect(HWND hWnd, long lpRect, boolean bErase);
boolean UpdateWindow(HWND hWnd);
boolean RedrawWindow(HWND hWnd, long lprcUpdate, long hrgnUpdate, int flags);
void GetWindowTextA(HWND hWnd, byte[] buffer, int buflen);
int GetTopWindow(HWND hWnd);
int GetWindow(HWND hWnd, int flag);
final int GW_HWNDNEXT = 2;
int GetClassName(HWND hWnd, char[] buffer2, int i);
int GetWindowModuleFileName(HWND hWnd, char[] buffer2, int i);
int GetWindowThreadProcessId(HWND hWnd, PointerByReference pref);
boolean GetCursorPos(long[] lpPoint); //use macros POINT_X() and POINT_Y() on long lpPoint[0]
HWND WindowFromPoint(long point);
HWND ChildWindowFromPointEx(HWND hwndParent, long point, int uFlags);
boolean ClientToScreen(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(POINT point);
}
public interface Gdi32 extends W32APIOptions {
Gdi32 instance = (Gdi32) Native.loadLibrary("gdi32", Gdi32.class, DEFAULT_OPTIONS);
HANDLE SelectObject(HDC hdc, HANDLE hgdiobj);
HANDLE GetStockObject(int fnObject);
boolean Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
HPEN CreatePen(int fnPenStyle, int nWidth, int crColor);
}
public interface Psapi extends W32APIOptions {
Psapi instance = (Psapi) Native.loadLibrary("psapi", Psapi.class, DEFAULT_OPTIONS);
int GetModuleBaseNameW(Pointer hProcess, Pointer hmodule, char[] lpBaseName, int size);
}
public interface Kernel32 extends W32APIOptions {
Kernel32 instance = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class, DEFAULT_OPTIONS);
boolean GetDiskFreeSpaceEx(String lpDirectoryName, LARGE_INTEGER.ByReference lpFreeBytesAvailable, LARGE_INTEGER.ByReference lpTotalNumberOfBytes, LARGE_INTEGER.ByReference lpTotalNumberOfFreeBytes);
int GetLastError();
Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, Pointer pointer);
}
public Api() {
user32 = User32.instance;
psapi = Psapi.instance;
kernel32 = Kernel32.instance;
}
public static String GetHandleAsString(HWND hWnd) {
if (hWnd == null)
return "0";
//String longHexStr = hWnd.toString().substring("native@".length());
String longHexStr = hWnd.getPointer().toString().substring("native@".length());
Long l = Long.decode(longHexStr);
return l.toString();
}
public static HWND GetHandleFromString(String hWnd) {
if (hWnd == null)
return null;
if (hWnd.isEmpty())
return null;
String cleanNumericHandle = hWnd.replaceAll("[^\\d.]", "");
try {
return (new HWND(new Pointer(Long.parseLong(cleanNumericHandle))));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String GetWindowClassName(HWND hWnd) {
char[] buffer = new char[1026];
User32.instance.GetClassName(hWnd, buffer, 1026);
return Native.toString(buffer);
}
public static String GetWindowText(HWND hWnd) {
String text = "";
byte[] buffer = new byte[1024];
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
text = Native.toString(buffer);
if (text.isEmpty())
text = new Api().sendWmGetText(hWnd);
return text;
}
public static HWND GetWindowFromPoint(Point p) {
long[] getPos = new long [1];
User32.instance.GetCursorPos(getPos);
HWND hwnd = User32.instance.WindowFromPoint(getPos[0]);
HWND childHwnd = GetHiddenChildWindowFromPoint(hwnd, getPos[0]);
hwnd = childHwnd;
//System.out.println(getPos[0] + "," + getPos[1] + " int: " + x + ", " + y);
//System.out.println("child: " + GetHandleAsString(childHwnd) + " " + POINT_X(getPos[0]) +", " + POINT_Y(getPos[0]));
return hwnd;
}
public static HWND GetHiddenChildWindowFromPoint(HWND inHwnd, long point)
{
//int x = POINT_X(point);int y = POINT_Y(point);
long[] getPos = new long [1];
getPos[0] = point;
//if (!User32.instance.ClientToScreen(inHwnd, getPos)) return lHWND;
//x = POINT_X(getPos[0]);y = POINT_Y(getPos[0]);
//System.out.println("ClientToScreen " + GetHandleAsString(inHwnd) + ", " + x + ", " + y);
if (!User32.instance.ScreenToClient(inHwnd, getPos)) return inHwnd; // if point is not correct use original hwnd.
//x = POINT_X(getPos[0]);y = POINT_Y(getPos[0]);
//System.out.println("ScreenToClient " + GetHandleAsString(inHwnd) + ", " + x + ", " + y);
HWND childHwnd = User32.instance.ChildWindowFromPointEx(inHwnd, getPos[0], CWP_ALL);
//System.out.println("ChildWindowFromPointEx2 " + GetHandleAsString(inHwnd) + ", " + x + ", " + y + " = " + GetHandleAsString(childHwnd));
if (childHwnd == null) // if childHwnd is not correct use original hwnd.
return inHwnd;
return childHwnd;
}
public HWND findWindowByTitle(String title) {
HWND handle = user32.FindWindow(null, title);
return handle;
}
public boolean activateWindow(HWND handle) {
boolean result = user32.SetForegroundWindow(handle);
user32.SetFocus(handle);
return result;
}
public void SetDialogFocus(HWND hdlg, HWND hwndControl) {
WPARAM wp = new WPARAM(hwndControl.getPointer().getLong(0));
LPARAM lp = new LPARAM(1);
user32.SendMessage(hdlg, WM_NEXTDLGCTL, wp, lp);
}
public boolean showWindow(HWND handle) {
return user32.ShowWindow(handle, WinUser.SW_SHOW);
}
public boolean hideWindow(HWND handle) {
return user32.ShowWindow(handle, WinUser.SW_HIDE);
}
public boolean minimizeWindow(HWND handle) {
return user32.ShowWindow(handle, WinUser.SW_MINIMIZE);
}
public boolean maximizeWindow(HWND handle) {
return user32.ShowWindow(handle, WinUser.SW_MAXIMIZE);
}
public boolean restoreWindow(HWND handle) {
return user32.ShowWindow(handle, WinUser.SW_RESTORE);
}
public boolean closeWindow(HWND handle) {
//return user32.DestroyWindow(handle);
user32.SendMessage(handle, WM_CLOSE , null, null);
//user32.SendMessage(handle, WM_NCDESTROY , null, null);
return true;
}
public void switchToThisWindow(HWND handle, boolean fAltTab) {
user32.SwitchToThisWindow(handle, fAltTab);
}
public String sendWmGetText(HWND handle) {
int bufSize = 8192;
byte[] lParamStr = new byte[bufSize];
user32.SendMessageA(handle, WM_GETTEXT, bufSize, lParamStr);
return (Native.toString(lParamStr));
}
public void sendWmSetText(HWND handle, String text) {
user32.SendMessageA(handle, WM_SETTEXT, 0, Native.toByteArray(text));
}
public void sendClick(HWND handle) {
user32.SendMessageA(handle, WM_LBUTTONDOWN, 0, null);
user32.SendMessageA(handle, WM_LBUTTONUP, 0, null);
}
public void sendDoubleClick(HWND handle) {
user32.SendMessageA(handle, WM_LBUTTONDBLCLK, 0, null);
//user32.SendMessageA(handle, WM_LBUTTONUP, 0, null);
}
public void sendRightClick(HWND handle) {
user32.SendMessageA(handle, WM_RBUTTONDOWN, 0, null);
user32.SendMessageA(handle, WM_RBUTTONUP, 0, null);
}
public void sendKeyDown(HWND handle, int keyCode) {
user32.SendMessageA(handle, WM_KEYDOWN, keyCode, null);
//user32.SendMessageA(handle, WM_KEYUP, keyCode, null);
}
public void sendKeyUp(HWND handle, int keyCode) {
//user32.SendMessageA(handle, WM_KEYDOWN, keyCode, null);
user32.SendMessageA(handle, WM_KEYUP, keyCode, null);
}
public int getDiskUsedPercentage() {
return getDiskUsedPercentage(null);
}
public int getDiskUsedPercentage(String target) {
LARGE_INTEGER.ByReference lpFreeBytesAvailable = new LARGE_INTEGER.ByReference();
LARGE_INTEGER.ByReference lpTotalNumberOfBytes = new LARGE_INTEGER.ByReference();
LARGE_INTEGER.ByReference lpTotalNumberOfFreeBytes = new LARGE_INTEGER.ByReference();
Kernel32.instance.GetDiskFreeSpaceEx(target, lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes);
double freeBytes = lpTotalNumberOfFreeBytes.getValue();
double totalBytes = lpTotalNumberOfBytes.getValue();
//System.out.println("freespace " + humanReadableByteCount(freeBytes) + "/ totalspace " + humanReadableByteCount(totalBytes));
return (int)(((totalBytes-freeBytes)/totalBytes) * 100.0);
}
public static String humanReadableByteCount(double bytes) {
boolean si = true;
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
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){
//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.
HANDLE prevPen = Gdi32.instance.SelectObject(dc, rectPen);
// Select a transparent brush into the DC and backup the previous brush.
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);
// Reinsert the previous pen and brush into the found window's DC.
Gdi32.instance.SelectObject(dc, prevPen);
Gdi32.instance.SelectObject(dc, prevBrush);
// Finally release the DC.
User32.instance.ReleaseDC(hwnd, dc);
}
}
public static void refreshWindow(HWND hwnd) {
User32.instance.InvalidateRect(hwnd, 0, true);
User32.instance.UpdateWindow(hwnd);
User32.instance.RedrawWindow(hwnd, 0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JMenu;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
@SuppressWarnings("serial")
public class CommandPopupMenu extends JPopupMenu {
public static interface menuEvents {
void menuItemClicked(String command, int paramCount, boolean useXpath, ActionEvent e);
}
public menuEvents events = new menuEvents() {
public void menuItemClicked(String command, int paramCount, boolean useXpath, ActionEvent e) {
JOptionPane.showMessageDialog(null, command);
}
};
public CommandPopupMenu() {
JMenu mnKeyboard = new JMenu("Keyboard");
add(mnKeyboard);
CommandMenuItem mntmSendkeys = new CommandMenuItem("sendKeys", 2, false);
mnKeyboard.add(mntmSendkeys);
CommandMenuItem mntmKeydown = new CommandMenuItem("keyDown", 2, false);
mnKeyboard.add(mntmKeydown);
CommandMenuItem mntmKeyup = new CommandMenuItem("keyUp", 2, false);
mnKeyboard.add(mntmKeyup);
CommandMenuItem mntmKeycopy = new CommandMenuItem("keyCopy", 1);
mnKeyboard.add(mntmKeycopy);
CommandMenuItem mntmKeypaste = new CommandMenuItem("keyPaste", 1);
mnKeyboard.add(mntmKeypaste);
CommandMenuItem mntmKeyEsc = new CommandMenuItem("keyEscape", 1);
mnKeyboard.add(mntmKeyEsc);
CommandMenuItem mntmKeyFunc = new CommandMenuItem("keyFunctionX", 2, false);
mnKeyboard.add(mntmKeyFunc);
JMenu mnMouse = new JMenu("Mouse");
add(mnMouse);
CommandMenuItem mntmClick = new CommandMenuItem("click", 1, false);
mnMouse.add(mntmClick);
CommandMenuItem mntmDoubleclick = new CommandMenuItem("doubleClick", 1, false);
mnMouse.add(mntmDoubleclick);
CommandMenuItem mntmRightclick = new CommandMenuItem("rightClick", 1, false);
mnMouse.add(mntmRightclick);
CommandMenuItem mntmwinClick = new CommandMenuItem("winClick", 2);
mnMouse.add(mntmwinClick);
CommandMenuItem mntmwinDoubleClick = new CommandMenuItem("winDoubleClick", 2);
mnMouse.add(mntmwinDoubleClick);
CommandMenuItem mntmwinRightClick = new CommandMenuItem("winRightClick", 2);
mnMouse.add(mntmwinRightClick);
CommandMenuItem mntmDraganddrop = new CommandMenuItem("dragAndDrop", 3);
mnMouse.add(mntmDraganddrop);
CommandMenuItem mntmMousedown = new CommandMenuItem("mouseDown", 1, false);
mnMouse.add(mntmMousedown);
CommandMenuItem mntmMouseup = new CommandMenuItem("mouseUp", 1, false);
mnMouse.add(mntmMouseup);
CommandMenuItem mntmMousedownright = new CommandMenuItem("mouseDownRight", 1, false);
mnMouse.add(mntmMousedownright);
CommandMenuItem mntmMouseupright = new CommandMenuItem("mouseUpRight", 1, false);
mnMouse.add(mntmMouseupright);
CommandMenuItem mntmMousemove = new CommandMenuItem("mouseMove", 3, false);
mnMouse.add(mntmMousemove);
JMenu mnWinMessages = new JMenu("Win Messages");
add(mnWinMessages);
CommandMenuItem mntmWindowfocus = new CommandMenuItem("windowFocus", 2);
mnWinMessages.add(mntmWindowfocus);
CommandMenuItem mntmWindowSwitchToThis = new CommandMenuItem("windowSwitchToThis", 2);
mnWinMessages.add(mntmWindowSwitchToThis);
CommandMenuItem mntmSetcursorposition = new CommandMenuItem("setCursorPosition", 3);
mnWinMessages.add(mntmSetcursorposition);
CommandMenuItem mntmWindowminimize = new CommandMenuItem("windowMinimize", 2);
mnWinMessages.add(mntmWindowminimize);
CommandMenuItem mntmWindowmaximize = new CommandMenuItem("windowMaximize", 2);
mnWinMessages.add(mntmWindowmaximize);
CommandMenuItem mntmWindowrestore = new CommandMenuItem("windowRestore", 2);
mnWinMessages.add(mntmWindowrestore);
CommandMenuItem mntmWindowhide = new CommandMenuItem("windowHide", 2);
mnWinMessages.add(mntmWindowhide);
CommandMenuItem mntmWindowshow = new CommandMenuItem("windowShow", 2);
mnWinMessages.add(mntmWindowshow);
CommandMenuItem mntmWindowclose = new CommandMenuItem("windowClose", 2);
mnWinMessages.add(mntmWindowclose);
CommandMenuItem mntmSetwindowtext = new CommandMenuItem("setWindowText", 3);
mnWinMessages.add(mntmSetwindowtext);
CommandMenuItem mntmGetwindowtext = new CommandMenuItem("getWindowText", 2);
mnWinMessages.add(mntmGetwindowtext);
CommandMenuItem mntmGetwindowclass = new CommandMenuItem("getWindowClass", 2);
mnWinMessages.add(mntmGetwindowclass);
CommandMenuItem mntmPause = new CommandMenuItem("pause", 2, false);
add(mntmPause);
CommandMenuItem mntmWaitfortitle = new CommandMenuItem("waitForTitle", 2, false);
add(mntmWaitfortitle);
CommandMenuItem mntmWaitfortext = new CommandMenuItem("waitForText", 2, false);
add(mntmWaitfortext);
CommandMenuItem mntmWaitforclass = new CommandMenuItem("waitForClass", 2, false);
add(mntmWaitforclass);
CommandMenuItem mntmWaitforvisible = new CommandMenuItem("waitForVisible", 2);
add(mntmWaitforvisible);
CommandMenuItem mntmSettimeout = new CommandMenuItem("setTimeout", 2, false);
add(mntmSettimeout);
CommandMenuItem mntmSetspeed = new CommandMenuItem("setSpeed", 2, false);
add(mntmSetspeed);
}
class CommandMenuItem extends JMenuItem {
public String commandText = "";
public int paramCount = 2;
public boolean useXpath = true;
public CommandMenuItem(String arg0, int paramCount) {
super(arg0);
init(arg0, paramCount, true);
}
public CommandMenuItem(String arg0, int paramCount, boolean useXpath) {
super(arg0);
init(arg0, paramCount, useXpath);
}
public void init(String arg0, int paramCount, boolean useXpath) {
this.commandText = arg0;
this.paramCount = paramCount;
this.useXpath = useXpath;
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
events.menuItemClicked(commandText, CommandMenuItem.this.paramCount, CommandMenuItem.this.useXpath, e);
}
});
}
}
public static String buildSkeletonCommand(String command, int paramCount, String xpathStr, boolean useXpath) {
String xpathItem = xpathStr;
if (!useXpath)
xpathItem = "";
String actionStr = "| do | " + command + " | ";
if (paramCount > 1)
actionStr += "on | " + xpathItem + " | ";
if (paramCount > 2)
actionStr += "with | |";
return actionStr;
}
}

View File

@@ -0,0 +1,611 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JOptionPane;
import com.sun.jna.platform.win32.WinDef.HWND;
public class CommandProcessor implements Runnable{
private static String WIN_XML = "";
public static long LAST_UPDATED_XML = 0;
public static long SPEED = 1000; // ms
public static double XML_UPDATE_THRESHOLD = 5.0; // seconds
public static long WAIT_TIMEOUT_THRESHOLD = 30000; //ms
public static AtomicBoolean STOP_PROCESSOR = new AtomicBoolean(false);
public String lastError = "";
public String scriptStr = "";
private Api api = new Api();
private int executeErrorCount = 0;
private String currentCommandText = "";
public static interface Events {
void statusChanged(String status);
void executionCompleted();
}
public Events events = new Events() {
public void statusChanged(String status){
System.out.println(status);
}
public void executionCompleted(){
}
};
public CommandProcessor () {
}
public CommandProcessor (String scriptStr, Events customEvents) { //multithreading support
this.scriptStr = scriptStr;
this.events = customEvents;
}
@Override
public void run() { //multithreading support
executeAllScriptCommands(scriptStr);
}
public static void executeThreaded(String scriptStr, Events customEvents) { //multithreading support
Thread t = new Thread(new CommandProcessor(scriptStr, customEvents));
t.start();
}
public void executeAllScriptCommands(String scriptStr) {
events.statusChanged("Executing Test Script...");
//CommandProcessor cmdProcessor = new CommandProcessor();
int errors = 0;
long startTime = System.nanoTime();
String[] lines = scriptStr.split("\n");
for (String line : lines) {
if (!line.trim().startsWith("|"))
continue; //skip if it doesn't start with bar
String[] parsed = line.split("\\|");
//System.out.println("line: " + line);
//System.out.println("parsed len = " + parsed.length);
//System.out.println("parsed 2 = " + parsed[2]);
//System.out.println("parsed 4 = " + parsed[4]);
events.statusChanged("Executing line: " + line);
if (parsed.length == 4 || parsed.length == 3)
execute(parsed[2].trim(), new String[] {});
if (parsed.length == 6)
execute(parsed[2].trim(), new String[] {parsed[4].trim()});
if (parsed.length == 7)
execute(parsed[2].trim(), new String[] {parsed[4].trim(), parsed[6].trim()});
if (executeErrorCount > 0) //check if any errors occurred
++errors;
if (STOP_PROCESSOR.get())
break;
}
double seconds = ((double)(System.nanoTime() - startTime) / 1000000000);
String forcedStr = "Completed";
if (STOP_PROCESSOR.get())
forcedStr = "Stopped";
events.statusChanged("Script Execution " + forcedStr + " with " + errors + " error(s) in " + new DecimalFormat("#.###").format(seconds) + " seconds");
events.executionCompleted();
if (errors > 0)
JOptionPane.showMessageDialog(null, lastError);
}
public Object execute(String command, String[] args) {
executeErrorCount = 0;
currentCommandText = command;
String joinedArgs = "";
for (String arg : args)
joinedArgs += arg + " | ";
if (joinedArgs.endsWith("| "))
joinedArgs = joinedArgs.substring(0, joinedArgs.length()-2);
StatusWindow sw = new StatusWindow(command + " " + joinedArgs, -1);
Object result = executeCommandSwitch(command, args);
if (SPEED > 0)
try { Thread.sleep(SPEED); } catch (Exception e) {e.printStackTrace();}
sw.dispose();
return result;
}
private Object executeCommandSwitch(String command, String[] args) {
try {
//Key commands
if (command.equals("sendKeys"))
return cmdSendKeys(args);
if (command.equals("keyDown"))
return cmdKeyDown(args);
if (command.equals("keyUp"))
return cmdKeyUp(args);
if (command.equals("keyCopy"))
return cmdKeyCopy(args);
if (command.equals("keyPaste"))
return cmdKeyPaste(args);
if (command.equals("keyEscape"))
return cmdKeyEscape(args);
if (command.equals("keyFunctionX"))
return cmdKeyFunc(args);
//Mouse commands
if (command.equals("click"))
return cmdClick(args);
if (command.equals("doubleClick"))
return cmdDoubleClick(args);
if (command.equals("rightClick"))
return cmdRightClick(args);
if (command.equals("winClick"))
return cmdWinClick(args);
if (command.equals("winDoubleClick"))
return cmdWinDoubleClick(args);
if (command.equals("winRightClick"))
return cmdWinRightClick(args);
if (command.equals("dragAndDrop"))
return cmdRightClick(args);
if (command.equals("mouseDown"))
return cmdMouseDown(args);
if (command.equals("mouseUp"))
return cmdMouseUp(args);
if (command.equals("mouseDownRight"))
return cmdMouseDownRight(args);
if (command.equals("mouseUpRight"))
return cmdMouseUpRight(args);
if (command.equals("mouseMove"))
return cmdMouseMove(args);
//Windows Api Commands
if (command.equals("windowFocus"))
return cmdWindowFocus(args);
if (command.equals("windowMinimize"))
return cmdWindowMinimize(args);
if (command.equals("windowMaximize"))
return cmdWindowMaximize(args);
if (command.equals("windowRestore"))
return cmdWindowRestore(args);
if (command.equals("windowShow"))
return cmdWindowShow(args);
if (command.equals("windowHide"))
return cmdWindowHide(args);
if (command.equals("windowSwitchToThis"))
return cmdWindowSwitchToThis(args);
if (command.equals("windowClose"))
return cmdWindowClose(args);
if (command.equals("setWindowText"))
return cmdSetText(args);
if (command.equals("getWindowText"))
return cmdGetText(args);
// Misc Commands
if (command.equals("delay") || command.equals("pause")) {
Thread.sleep(Long.parseLong(args[0]));
return true;
}
if (command.equals("setSpeed"))
return cmdSetSpeed(args);
if (command.equals("setTimeout"))
return cmdSetTimeout(args);
if (command.equals("waitForTitle"))
return cmdWaitForTitle(args);
if (command.equals("waitForText"))
return cmdWaitForText(args);
if (command.equals("waitForClass"))
return cmdWaitForClass(args);
if (command.equals("waitForVisible"))
return cmdWaitForVisible(args);
}
catch (Exception e) {
appendError(e);
return false;
}
appendError("Error: Command '" + command + "' not found.");
return false;
}
private void appendError(Exception e) {
++executeErrorCount;
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
lastError += new Timestamp((new Date()).getTime()) + " - " + sw.toString() + "\n";
try {
sw.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void appendError(String msg) {
++executeErrorCount;
lastError += new Timestamp((new Date()).getTime()) + " - " + msg + "\n";
}
private boolean checkArgumentLength(String[] args, int expectedLength) {
if (args.length < expectedLength) {
appendError("Error: expected at least " + expectedLength + " arguments (" + currentCommandText + "[" + args.length + "])");
return false;
}
return true;
}
private boolean whenFalseAppendError(boolean cmdResult) {
if (!cmdResult)
appendError("Error: command '" + currentCommandText + "' failed");
return cmdResult;
}
private HWND findHandleWithXpath(String xpath) {
return findHandleWithXpath(xpath, false);
}
private HWND findHandleWithXpath(String xpath, boolean ignoreFailedFind) {
HWND result = null;
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
if (secondsFromLastUpdate > 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("hwnd=")) {
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hwnd");
resultStr = hwndList.get(0);
}
else
resultStr = item;
break;
}
result = Api.GetHandleFromString(resultStr);
if (result == null && !ignoreFailedFind)
appendError("Error: Failed to find window handle matching: " + xpath);
return result;
}
private boolean cmdSendKeys(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
return whenFalseAppendError(RobotMacro.sendKeys(args[0]));
}
private boolean cmdKeyDown(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
if (args[0].length() < 1){
appendError("Error: command '" + currentCommandText + "' failed, expected first argument length > 0");
return false;
}
char keyChar = args[0].charAt(0);
return RobotMacro.keyDown(keyChar);
}
private boolean cmdKeyUp(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
if (args[0].length() < 1){
appendError("Error: command '" + currentCommandText + "' failed, expected first argument length > 0");
return false;
}
char keyChar = args[0].charAt(0);
return RobotMacro.keyUp(keyChar);
}
private boolean cmdKeyCopy(String[] args) {
RobotMacro.copyKey();
return true;
}
private boolean cmdKeyPaste(String[] args) {
RobotMacro.pasteKey();
return true;
}
private boolean cmdKeyEscape(String[] args) {
RobotMacro.escapeKey();
return true;
}
private boolean cmdKeyFunc(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
if (args[0].length() < 1){
appendError("Error: command '" + currentCommandText + "' failed, expected first argument length > 0");
return false;
}
int fNum = Integer.parseInt(args[0]);
RobotMacro.functionKey(fNum);
return true;
}
private boolean cmdClick(String[] args) {
RobotMacro.leftClickMouse();
return true;
}
private boolean cmdDoubleClick(String[] args) {
RobotMacro.doubleClickMouse();
return true;
}
private boolean cmdRightClick(String[] args) {
RobotMacro.rightClickMouse();
return true;
}
private boolean cmdMouseDown(String[] args) {
RobotMacro.leftMouseDown();
return true;
}
private boolean cmdMouseUp(String[] args) {
RobotMacro.leftMouseUp();
return true;
}
private boolean cmdMouseDownRight(String[] args) {
RobotMacro.rightMouseDown();
return true;
}
private boolean cmdMouseUpRight(String[] args) {
RobotMacro.rightMouseUp();
return true;
}
private boolean cmdMouseMove(String[] args) {
if (!checkArgumentLength(args, 2))
return false;
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
RobotMacro.mouseMove(x, y);
return true;
}
private boolean cmdWinClick(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.sendClick(handle);
return true;
}
private boolean cmdWinDoubleClick(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.sendDoubleClick(handle);
return true;
}
private boolean cmdWinRightClick(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.sendRightClick(handle);
return true;
}
private boolean cmdWindowFocus(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.activateWindow(handle);
//api.showWindow(handle);
return true;
}
private boolean cmdWindowMinimize(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.minimizeWindow(handle);
return true;
}
private boolean cmdWindowMaximize(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.maximizeWindow(handle);
return true;
}
private boolean cmdWindowRestore(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.restoreWindow(handle);
return true;
}
private boolean cmdWindowHide(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.hideWindow(handle);
return true;
}
private boolean cmdWindowShow(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.showWindow(handle);
return true;
}
private boolean cmdWindowSwitchToThis(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.switchToThisWindow(handle, true);
return true;
}
private boolean cmdWindowClose(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.closeWindow(handle);
return true;
}
private boolean cmdSetText(String[] args) {
if (!checkArgumentLength(args, 2))
return false;
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return false;
api.sendWmSetText(handle, args[1]);
return true;
}
private String cmdGetText(String[] args) {
if (!checkArgumentLength(args, 1))
return "";
HWND handle = findHandleWithXpath(args[0]);
if (handle == null)
return "";
return api.sendWmGetText(handle);
}
private boolean cmdSetSpeed(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
long speed = Long.parseLong(args[0]);
SPEED = speed;
return true;
}
private boolean cmdSetTimeout(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
long timeout = Long.parseLong(args[0]);
WAIT_TIMEOUT_THRESHOLD = timeout;
return true;
}
private boolean cmdWaitForTitle(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0;
String xpath = "/EnumeratedWindows/win[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
HWND handle = findHandleWithXpath(xpath, true);
if (handle != null)// first test without a timeout
return true;
while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(xpath, true);
if (handle != null)
break;
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount;
if (STOP_PROCESSOR.get())
break;
}
return handle != null;
}
private boolean cmdWaitForText(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0;
String xpath = "//[@TEXT='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
HWND handle = findHandleWithXpath(xpath, true);
if (handle != null)// first test without a timeout
return true;
while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(xpath, true);
if (handle != null)
break;
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount;
if (STOP_PROCESSOR.get())
break;
}
return handle != null;
}
private boolean cmdWaitForClass(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0;
String xpath = "//win[@CLASS='" + WindowsEnumeratedXml.escapeXmlAttributeValue(args[0].toUpperCase()) + "']";
HWND handle = findHandleWithXpath(xpath, true);
if (handle != null)// first test without a timeout
return true;
while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(xpath, true);
if (handle != null)
break;
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount;
if (STOP_PROCESSOR.get())
break;
}
return handle != null;
}
private boolean cmdWaitForVisible(String[] args) {
if (!checkArgumentLength(args, 1))
return false;
long totalAttempts = (long) (WAIT_TIMEOUT_THRESHOLD / (XML_UPDATE_THRESHOLD * 1000));
long attemptCount = 0;
HWND handle = findHandleWithXpath(args[0], true);
if (handle != null)// first test without a timeout
return true;
while (attemptCount < totalAttempts) {
handle = findHandleWithXpath(args[0], true);
if (handle != null)
break;
try {Thread.sleep((long)(XML_UPDATE_THRESHOLD * 1000));} catch (Exception e) {e.printStackTrace();}
++attemptCount;
if (STOP_PROCESSOR.get())
break;
}
return handle != null;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
public class Config extends PropertiesSerializer {
public static String DEFAULT_PROP_FILENAME = "synthuse.properties";
public String urlList = "";
public String xpathList = "";
public String xpathHightlight = ".*process=\"([^\"]*)\".*";
public Config() //needed for cloning
{
}
public Config(String propertyFilename)
{
super(propertyFilename);
load(propertyFilename);
}
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceAdapter;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceMotionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.TransferHandler;
public class DragTarget extends JLabel {
public static String CUSTOM_ICON_RESOURCE = "/org/synthuse/img/bullseye-logo-th32x32.png";
private static final long serialVersionUID = 1L;
public static interface dragEvents {
void dragStarted(JComponent c);
void dragMouseMoved(int x, int y);
void dropped(JComponent c);
}
public dragEvents events = new dragEvents() {
public void dragStarted(JComponent c) {
}
public void dragMouseMoved(int x, int y) {
}
public void dropped(JComponent c) {
}
};
public DragTarget() {
this.setTransferHandler(new CustomTransferHandler());
this.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e)
{
JComponent comp = (JComponent)e.getSource();
TransferHandler handler = comp.getTransferHandler();
//c.setOpaque(true);
handler.exportAsDrag(comp, e, TransferHandler.MOVE);
}
});
}
@SuppressWarnings("serial")
class CustomTransferHandler extends TransferHandler {
//private final JWindow window = new JWindow();
private final DataFlavor localObjectFlavor;
private final JLabel label = new JLabel();
//public Cursor blankCursor = null;
public Cursor customCursor = null;
public CustomTransferHandler () {
//System.out.println("CustomTransferHandler");
localObjectFlavor = new ActivationDataFlavor(DragTarget.class, DataFlavor.javaJVMLocalObjectMimeType, "JLabel");
//label = DragTarget.this;
//window.add(label);
//window.setAlwaysOnTop(true);
//window.setBackground(new Color(0,true));
// Create a new blank cursor.
//BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
//blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0), "blank cursor");
try {
BufferedImage image = ImageIO.read(SynthuseDlg.class.getResourceAsStream(CUSTOM_ICON_RESOURCE));
customCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(15, 16), "custom cursor");
} catch (Exception e1) {
e1.printStackTrace();
}
DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
@Override
public void dragMouseMoved(DragSourceDragEvent e) {
events.dragMouseMoved(e.getLocation().x, e.getLocation().y);
//Point pt = e.getLocation();
//pt.translate(-9, -9); // offset
//window.setLocation(pt);
//e.getDragSourceContext().setCursor(customCursor);//DragSource.DefaultLinkDrop
}
});
DragSource.getDefaultDragSource().addDragSourceListener(new DragSourceAdapter() {
@Override
public void dragEnter(DragSourceDragEvent e) {
e.getDragSourceContext().setCursor(customCursor);//DragSource.DefaultLinkDrop
//System.out.println("dragEnter");
}
});
}
@Override
protected Transferable createTransferable(JComponent c) {
//System.out.println("createTransferable");
//JLabel l = (JLabel)c;
//String text = l.getText();
final DataHandler dh = new DataHandler(c, localObjectFlavor.getMimeType());
return dh;
//return new StringSelection("");
}
@Override
public boolean canImport(TransferSupport support) {
return true;
}
@Override
public boolean importData(TransferSupport support) {
System.out.println("importData");
return true;
}
@Override
public int getSourceActions(JComponent c) {
//System.out.println("getSourceActions");
events.dragStarted(c);
JLabel p = (JLabel)c;
label.setIcon(p.getIcon());
//label.setText(p.draggingLabel.getText());
//window.pack();
//Point pt = p.getLocation();
//SwingUtilities.convertPointToScreen(pt, p);
//window.setLocation(pt);
//window.setVisible(true);
return MOVE;
}
@Override
protected void exportDone(JComponent c, Transferable data, int action) {
//System.out.println("exportDone");
events.dropped(c);
JLabel src = (JLabel)c;
if(action == TransferHandler.MOVE) {
src.remove(src);
src.revalidate();
src.repaint();
}
src = null;
//window.setVisible(false);
//window.dispose();
}
}
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.io.*;
import java.util.Properties;
import java.lang.reflect.Field;
/*
// example class for PropertiesSerializer
public class Configuration extends PropertiesSerializer{
public static final String DEFAULT_PROP_FILENAME = "./ctf.properties";
// General Settings
public String tests_dir = "./tests";
public String logs_dir = "./logs";
public int statusTimer = 2000;
public Configuration() //needed for cloning
{
}
public Configuration(String propertyFilename)
{
super(propertyFilename);
load(propertyFilename);
}
}
*/
public class PropertiesSerializer {
protected Properties prop = new Properties();
protected String propertyFilename = null;
public PropertiesSerializer()
{
}
public PropertiesSerializer(String propertyFilename)
{
this.propertyFilename = propertyFilename;
}
public void load(String propertyFilename)
{
try
{
prop.load(new FileInputStream(propertyFilename));
}
catch (Exception e)
{
e.printStackTrace();
}
Field[] fields = this.getClass().getFields();
for (int i = 0 ; i < fields.length; i++)
{
//fields[i].get(this);
String pName = fields[i].getName();
String pType = "String";
try
{
pType = fields[i].get(this).getClass().getSimpleName();
}
catch (Exception e)
{
//e.printStackTrace();
}
try
{
if (pType.equalsIgnoreCase("integer"))
fields[i].set(this, Integer.parseInt(prop.get(pName) + ""));
if (pType.equalsIgnoreCase("boolean"))
fields[i].set(this, Boolean.parseBoolean(prop.get(pName) + ""));
else
fields[i].set(this, prop.get(pName));
}
catch (Exception e)
{
//e.printStackTrace();
}
}
}
public void save()
{
Field[] fields = this.getClass().getFields();
for (int i = 0 ; i < fields.length; i++)
{
//fields[i].get(this);
try {
String pName = fields[i].getName();
//String pType = fields[i].get(this).getClass().getSimpleName();
if (fields[i].get(this) == null)
prop.setProperty(pName, "");
else
prop.setProperty(pName, fields[i].get(this) + "");
} catch (Exception e) {
//e.printStackTrace();
}
}
try
{
FileOutputStream fos = new FileOutputStream(propertyFilename);
prop.store(fos, "");
fos.flush();
fos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
public Object clone()
{
Object newObject = null;
try {
newObject = (Object)this.getClass().newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
Field[] fields = this.getClass().getFields();
for (int i = 0 ; i < fields.length; i++)
{
try {
//fields[i].get(this);
//String pName = fields[i].getName();
fields[i].set(newObject, fields[i].get(this));
}
catch (Exception e)
{
//e.printStackTrace();
}
}
return newObject;
}
public boolean hasChanged()
{
boolean changes = false;
Field[] fields = this.getClass().getFields();
for (int i = 0 ; i < fields.length; i++)
{
//fields[i].get(this);
try {
String pName = fields[i].getName();
//String pType = fields[i].get(this).getClass().getSimpleName();
if (prop.getProperty(pName).compareTo(fields[i].get(this)+"") != 0)
changes = true;
} catch (Exception e) {
//e.printStackTrace();
}
}
return changes;
}
public String getPropertyFilename()
{
return this.propertyFilename;
}
public void setPropertyFilename(String filename)
{
this.propertyFilename = filename;
}
public String readValue(String propertyName)
{
String val = "";
val = prop.getProperty(propertyName);
return val;
}
public void writeValue(String propertyName, String propertValue)
{
prop.setProperty(propertyName, propertValue);
try {
prop.store(new FileOutputStream(propertyFilename), null);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,371 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.*;
import java.awt.event.*;
public class RobotMacro {
public static Exception lastException = null;
public static boolean executeCommand(String cmd) {
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(cmd);
} catch (Exception e) {
lastException = e;
return false;
}
return true;
}
public static void delay(int time) {
try {
Robot robot = new Robot();
robot.delay(time);
} catch (Exception e) {
lastException = e;
}
}
public static void moveMouse(int x, int y) {
try {
Robot robot = new Robot();
robot.mouseMove(x, y);
} catch (Exception e) {
lastException = e;
}
}
public static void leftClickMouse() {
try {
Robot robot = new Robot();
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
lastException = e;
}
}
public static void doubleClickMouse() {
try {
Robot robot = new Robot();
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(100);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
lastException = e;
}
}
public static void rightClickMouse() {
try {
System.out.println("rightClickMouse");
Robot robot = new Robot();
//robot.mouseMove(200, 200);
//robot.delay(1000);
robot.mousePress(InputEvent.BUTTON3_MASK);
robot.mouseRelease(InputEvent.BUTTON3_MASK);
//System.out.println("rightClickMouse good");
} catch (Exception e) {
lastException = e;
e.printStackTrace();
}
}
public static void leftMouseDown() {
try {
Robot robot = new Robot();
robot.mousePress(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
lastException = e;
}
}
public static void leftMouseUp() {
try {
Robot robot = new Robot();
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
lastException = e;
}
}
public static void rightMouseDown() {
try {
Robot robot = new Robot();
robot.mousePress(InputEvent.BUTTON3_MASK);
} catch (Exception e) {
lastException = e;
}
}
public static void rightMouseUp() {
try {
Robot robot = new Robot();
robot.mouseRelease(InputEvent.BUTTON3_MASK);
} catch (Exception e) {
lastException = e;
e.printStackTrace();
}
}
public static void mouseMove(int x, int y) {
try {
Robot robot = new Robot();
robot.mouseMove(x, y);
} catch (Exception e) {
lastException = e;
e.printStackTrace();
}
}
public static void copyKey() {
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_CONTROL);
} catch (Exception e) {
lastException = e;
}
}
public static void pasteKey() {
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
} catch (Exception e) {
lastException = e;
}
}
public static void escapeKey() {
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ESCAPE);
robot.keyRelease(KeyEvent.VK_ESCAPE);
} catch (Exception e) {
lastException = e;
}
}
public static void functionKey(int functionNum) {
try {
Robot robot = new Robot();
int keyCode = 0;
switch (functionNum) {
case 1: keyCode = KeyEvent.VK_F1; break;
case 2: keyCode = KeyEvent.VK_F2; break;
case 3: keyCode = KeyEvent.VK_F3; break;
case 4: keyCode = KeyEvent.VK_F4; break;
case 5: keyCode = KeyEvent.VK_F5; break;
case 6: keyCode = KeyEvent.VK_F6; break;
case 7: keyCode = KeyEvent.VK_F7; break;
case 8: keyCode = KeyEvent.VK_F8; break;
case 9: keyCode = KeyEvent.VK_F9; break;
case 10: keyCode = KeyEvent.VK_F10; break;
case 11: keyCode = KeyEvent.VK_F11; break;
case 12: keyCode = KeyEvent.VK_F12; break;
}
robot.keyPress(keyCode);
robot.keyRelease(keyCode);
} catch (Exception e) {
lastException = e;
}
}
public static void tildeKey() {
try {
Robot robot = new Robot();
pressKeyCodes(robot, new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_QUOTE});
} catch (Exception e) {
lastException = e;
}
}
public static boolean sendKeys(String keyCommands) {
try {
Robot robot = new Robot();
for (int i = 0; i < keyCommands.length(); i++) {
char key = keyCommands.charAt(i);
int[] keyCode = getKeyCode(key);
pressKeyCodes(robot, keyCode);
}
} catch (Exception e) {
lastException = e;
return false;
}
return true;
}
public static boolean pressKey(char key) {
try {
Robot robot = new Robot();
int[] keyCode = getKeyCode(key);
pressKeyCodes(robot, keyCode);
} catch (Exception e) {
lastException = e;
return false;
}
return true;
}
public static boolean keyDown(char key) {
try {
Robot robot = new Robot();
int[] keyCodes = getKeyCode(key);
for (int i = 0; i < keyCodes.length; i++) {
robot.keyPress(keyCodes[i]);
//System.out.println("pressed: " + keyCodes[i]);
}
} catch (Exception e) {
lastException = e;
return false;
}
return true;
}
public static boolean keyUp(char key) {
try {
Robot robot = new Robot();
int[] keyCodes = getKeyCode(key);
for (int i = keyCodes.length - 1; i >= 0; i--) {
robot.keyRelease(keyCodes[i]);
//System.out.println("released: " + keyCodes[i]);
}
} catch (Exception e) {
lastException = e;
return false;
}
return true;
}
public static void pressKeyCodes(Robot robot, int[] keyCodes) {
for (int i = 0; i < keyCodes.length; i++) {
robot.keyPress(keyCodes[i]);
//System.out.println("pressed: " + keyCodes[i]);
}
//robot.delay(50);
for (int i = keyCodes.length - 1; i >= 0; i--) {
robot.keyRelease(keyCodes[i]);
//System.out.println("released: " + keyCodes[i]);
}
}
public static int[] getKeyCode(char key) {
switch (key) {
case 'a': return(new int[]{KeyEvent.VK_A});
case 'b': return(new int[]{KeyEvent.VK_B});
case 'c': return(new int[]{KeyEvent.VK_C});
case 'd': return(new int[]{KeyEvent.VK_D});
case 'e': return(new int[]{KeyEvent.VK_E});
case 'f': return(new int[]{KeyEvent.VK_F});
case 'g': return(new int[]{KeyEvent.VK_G});
case 'h': return(new int[]{KeyEvent.VK_H});
case 'i': return(new int[]{KeyEvent.VK_I});
case 'j': return(new int[]{KeyEvent.VK_J});
case 'k': return(new int[]{KeyEvent.VK_K});
case 'l': return(new int[]{KeyEvent.VK_L});
case 'm': return(new int[]{KeyEvent.VK_M});
case 'n': return(new int[]{KeyEvent.VK_N});
case 'o': return(new int[]{KeyEvent.VK_O});
case 'p': return(new int[]{KeyEvent.VK_P});
case 'q': return(new int[]{KeyEvent.VK_Q});
case 'r': return(new int[]{KeyEvent.VK_R});
case 's': return(new int[]{KeyEvent.VK_S});
case 't': return(new int[]{KeyEvent.VK_T});
case 'u': return(new int[]{KeyEvent.VK_U});
case 'v': return(new int[]{KeyEvent.VK_V});
case 'w': return(new int[]{KeyEvent.VK_W});
case 'x': return(new int[]{KeyEvent.VK_X});
case 'y': return(new int[]{KeyEvent.VK_Y});
case 'z': return(new int[]{KeyEvent.VK_Z});
case 'A': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_A});
case 'B': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_B});
case 'C': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_C});
case 'D': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_D});
case 'E': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_E});
case 'F': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_F});
case 'G': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_G});
case 'H': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_H});
case 'I': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_I});
case 'J': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_J});
case 'K': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_K});
case 'L': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_L});
case 'M': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_M});
case 'N': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_N});
case 'O': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_O});
case 'P': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_P});
case 'Q': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_Q});
case 'R': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_R});
case 'S': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_S});
case 'T': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_T});
case 'U': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_U});
case 'V': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_V});
case 'W': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_W});
case 'X': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_X});
case 'Y': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_Y});
case 'Z': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_Z});
case '`': return(new int[]{KeyEvent.VK_BACK_QUOTE});
case '0': return(new int[]{KeyEvent.VK_0});
case '1': return(new int[]{KeyEvent.VK_1});
case '2': return(new int[]{KeyEvent.VK_2});
case '3': return(new int[]{KeyEvent.VK_3});
case '4': return(new int[]{KeyEvent.VK_4});
case '5': return(new int[]{KeyEvent.VK_5});
case '6': return(new int[]{KeyEvent.VK_6});
case '7': return(new int[]{KeyEvent.VK_7});
case '8': return(new int[]{KeyEvent.VK_8});
case '9': return(new int[]{KeyEvent.VK_9});
case '-': return(new int[]{KeyEvent.VK_MINUS});
case '=': return(new int[]{KeyEvent.VK_EQUALS});
case '~': return(new int[]{KeyEvent.VK_ENTER});//return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_QUOTE});
case '!': return(new int[]{KeyEvent.VK_EXCLAMATION_MARK});
case '@': return(new int[]{KeyEvent.VK_AT});
case '#': return(new int[]{KeyEvent.VK_NUMBER_SIGN});
case '$': return(new int[]{KeyEvent.VK_DOLLAR});
case '%': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_5});
case '^': return(new int[]{KeyEvent.VK_CIRCUMFLEX});
case '&': return(new int[]{KeyEvent.VK_AMPERSAND});
case '*': return(new int[]{KeyEvent.VK_ASTERISK});
case '(': return(new int[]{KeyEvent.VK_LEFT_PARENTHESIS});
case ')': return(new int[]{KeyEvent.VK_RIGHT_PARENTHESIS});
case '_': return(new int[]{KeyEvent.VK_UNDERSCORE});
case '+': return(new int[]{KeyEvent.VK_PLUS});
case '\t': return(new int[]{KeyEvent.VK_TAB});
case '\n': return(new int[]{KeyEvent.VK_ENTER});
case '[': return(new int[]{KeyEvent.VK_OPEN_BRACKET});
case ']': return(new int[]{KeyEvent.VK_CLOSE_BRACKET});
case '\\': return(new int[]{KeyEvent.VK_BACK_SLASH});
case '{': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_OPEN_BRACKET});
case '}': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CLOSE_BRACKET});
case '|': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH});
case ';': return(new int[]{KeyEvent.VK_SEMICOLON});
case ':': return(new int[]{KeyEvent.VK_COLON});
case '\'': return(new int[]{KeyEvent.VK_QUOTE});
case '"': return(new int[]{KeyEvent.VK_QUOTEDBL});
case ',': return(new int[]{KeyEvent.VK_COMMA});
case '<': return(new int[]{KeyEvent.VK_LESS});
case '.': return(new int[]{KeyEvent.VK_PERIOD});
case '>': return(new int[]{KeyEvent.VK_GREATER});
case '/': return(new int[]{KeyEvent.VK_SLASH});
case '?': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_SLASH}); // needs Shift
case ' ': return(new int[]{KeyEvent.VK_SPACE});
default:
throw new IllegalArgumentException("Cannot find Key Code for character " + key);
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JLabel;
import javax.swing.JWindow;
public class StatusWindow extends JWindow {
private static final long serialVersionUID = 1L;
public static int FONT_SIZE = 14;
public static int FONT_BOLD = Font.BOLD; //Font.PLAIN
public static int Y_BOTTOM_OFFSET = -100;
public static Color BACKGROUND_COLOR = Color.yellow;
public static Color FOREGROUND_COLOR = Color.black;
//private int displayTime = -1;
//private String displayText = "";
public StatusWindow(String lblText, int displayTime) {
super();
//this.displayTime = displayTime;
//this.displayText = lblText;
//this.setLayout(new FlowLayout());
JLabel lbl = new JLabel(lblText);
lbl.setFont(new Font(lbl.getName(), FONT_BOLD, FONT_SIZE));
lbl.setOpaque(true); //background isn't painted without this
lbl.setBackground(BACKGROUND_COLOR);
lbl.setForeground(FOREGROUND_COLOR);
this.getContentPane().setLayout(new FlowLayout());
this.getContentPane().add(lbl);
this.pack();
this.setVisible(true);
//
if (displayTime > 0) {
Timer timer = new Timer(true);
timer.schedule(new TimerTask() {
@Override
public void run() {
StatusWindow.this.dispose();
}
}, displayTime);
}
}
@Override
public void setVisible(final boolean visible) {
super.setVisible(visible);
// ...and bring window to the front.. in a strange and weird way
if (visible) {
super.setAlwaysOnTop(true);
super.toFront();
super.requestFocus();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
//this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
this.setLocation(dim.width/2-this.getSize().width/2, dim.height + Y_BOTTOM_OFFSET );
}
}
}

View File

@@ -0,0 +1,438 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
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.WindowConstants;
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;
import com.jgoodies.forms.layout.RowSpec;
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;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
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;
//public class SynthuseDlg extends JDialog {
public class SynthuseDlg extends JFrame {
/**
*
*/
public static String VERSION_STR = "1.0.5";
public static String RES_STR_MAIN_ICON = "/org/synthuse/img/gnome-robots.png";
public static String RES_STR_REFRESH_IMG = "/org/synthuse/img/rapidsvn.png";
public static String RES_STR_TESTIDE_IMG = "/org/synthuse/img/applications-education.png";
public static String RES_STR_HELP_IMG = "/org/synthuse/img/help-3.png";
public static String RES_STR_TARGET_IMG = "/org/synthuse/img/bullseye-logo-th18x18.png";
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 List<String> actionListQueue = new ArrayList<String>();
private static final long serialVersionUID = 1L;
private XpathManager.Events xpathEvents = null;
private JPanel contentPane;
private JLabel lblStatus;
private JButton btnRefresh;
private JTextPane textPane;
private JButton btnSetAction;
private JButton btnCancel;
private JButton btnFind;
public static Config config = new Config(Config.DEFAULT_PROP_FILENAME);
private String dialogResult = "";
private String lastDragHwnd = "";
private JComboBox<String> cmbXpath;
private JButton btnTestIde;
private TestIdeFrame testIde = null;
private int targetX;
private int targetY;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SynthuseDlg frame = new SynthuseDlg();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public SynthuseDlg() {
setIconImage(Toolkit.getDefaultToolkit().getImage(SynthuseDlg.class.getResource(RES_STR_MAIN_ICON)));
//setModal(true);
setTitle("Synthuse");
setBounds(100, 100, 827, 420);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JToolBar toolBar = new JToolBar();
contentPane.add(toolBar, BorderLayout.NORTH);
JRadioButton rdbtnWindows = new JRadioButton("Windows Enumerated Xml");
rdbtnWindows.setSelected(true);
toolBar.add(rdbtnWindows);
Component horizontalStrut = Box.createHorizontalStrut(20);
toolBar.add(horizontalStrut);
JRadioButton rdbtnUrl = new JRadioButton("Url: ");
rdbtnUrl.setEnabled(false);
toolBar.add(rdbtnUrl);
// Group the radio buttons.
ButtonGroup group = new ButtonGroup();
group.add(rdbtnWindows);
group.add(rdbtnUrl);
JComboBox<String> cmbUrl = new JComboBox<String>();
cmbUrl.setEnabled(false);
cmbUrl.setEditable(true);
toolBar.add(cmbUrl);
Component horizontalStrut_1 = Box.createHorizontalStrut(20);
toolBar.add(horizontalStrut_1);
btnRefresh = new JButton(" Refresh ");
btnRefresh.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//lblStatus.setText("Loading Windows Enumerated Xml...");
WindowsEnumeratedXml.getXmlThreaded(textPane, lblStatus);
//appendToPane(WindowsEnumeratedXml.getXml());
//lblStatus.setText("Windows Enumerated Xml loaded");
}
});
btnRefresh.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_REFRESH_IMG)));
toolBar.add(btnRefresh);
Component horizontalStrut_3 = Box.createHorizontalStrut(20);
toolBar.add(horizontalStrut_3);
btnTestIde = new JButton("Test IDE");
btnTestIde.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (testIde == null) {
testIde = new TestIdeFrame();
if (SynthuseDlg.actionListQueue.size() > 0) { // if stuff is already in the queue add it to the test ide
for (String action : SynthuseDlg.actionListQueue) {
testIde.txtTest.append(action + "\n");
}
}
}
testIde.setVisible(true);
}
});
btnTestIde.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_TESTIDE_IMG)));
toolBar.add(btnTestIde);
Component horizontalStrut_2 = Box.createHorizontalStrut(20);
toolBar.add(horizontalStrut_2);
JButton helpBtn = new JButton("Help");
helpBtn.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_HELP_IMG)));
helpBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, "Version " + VERSION_STR + " create by Edward Jakubowski ejakubowski7@gmail.com", "About", JOptionPane.QUESTION_MESSAGE);
}
});
toolBar.add(helpBtn);
JSplitPane splitPane = new JSplitPane();
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
contentPane.add(splitPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
panel.setMinimumSize(new Dimension(20, 35));
splitPane.setLeftComponent(panel);
/*
panel.setLayout(new FormLayout(new ColumnSpec[] {
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("left:max(11dlu;default)"),
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("left:default"),
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,},
new RowSpec[] {
FormFactory.RELATED_GAP_ROWSPEC,
RowSpec.decode("default:grow"),}));
*/
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridwidth = 1;
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(3,3,3,3); // add padding around objects
DragTarget lblTarget = new DragTarget();
lblTarget.setHorizontalAlignment(SwingConstants.CENTER);
lblTarget.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_TARGET_IMG)));
panel.add(lblTarget, c);
btnFind = new JButton("Find");
btnFind.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String xpathItem = cmbXpath.getSelectedItem().toString();
int matches = XpathManager.nextXpathMatch(xpathItem, textPane, lblStatus, false);
if (matches < 0) //check for an error
return; //don't save bad xpath to combobox
if (config.xpathList == null)
config.xpathList = "";
if (!config.xpathList.contains(xpathItem + "<EFBFBD>")){
config.xpathList += xpathItem + "<EFBFBD>";
refreshDatabinding();
cmbXpath.setSelectedItem(xpathItem);
}
}
});
cmbXpath = new JComboBox<String>();
cmbXpath.setPreferredSize(new Dimension(440, 20));//fix the width of the combobox
cmbXpath.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");//fix the width of the combobox
cmbXpath.setEditable(true);
cmbXpath.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ENTER) {
btnFind.doClick();
}
}
});
c.gridwidth = 3;
c.gridx = 1;
panel.add(cmbXpath, c);
btnFind.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_FIND_IMG)));
c.gridwidth = 1;
c.gridx = 4;
panel.add(btnFind, c);
btnSetAction = new JButton("Set Action");
btnSetAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CommandPopupMenu menu = new CommandPopupMenu();
final String xpathItem = cmbXpath.getSelectedItem().toString();
menu.events = new CommandPopupMenu.menuEvents() {
@Override
public void menuItemClicked(String command, int paramCount, boolean useXpath, ActionEvent e) {
String actionStr = CommandPopupMenu.buildSkeletonCommand(command, paramCount, xpathItem, useXpath);
SynthuseDlg.actionListQueue.add(actionStr);
lblStatus.setText("Setting Action: " + actionStr);
if (testIde != null)
testIde.txtTest.append(actionStr + "\n");
}
};
Component c = (Component) e.getSource();
menu.show(c, -1, c.getHeight());
}
});
btnSetAction.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_SETACTION_IMG)));
c.gridwidth = 1;
c.gridx = 5;
panel.add(btnSetAction, c);
btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dialogResult = "";
SynthuseDlg.this.dispose();
}
});
btnCancel.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_CANCEL_IMG)));
c.gridwidth = 1;
c.gridx = 6;
panel.add(btnCancel, c);
JScrollPane scrollPane = new JScrollPane();
splitPane.setRightComponent(scrollPane);
textPane = new JTextPane();
textPane.setEditable(false);
textPane.setEditorKitForContentType("text/xml", new XmlEditorKit());
textPane.setContentType("text/xml");
scrollPane.setViewportView(textPane);
JPanel panel_1 = new JPanel();
FlowLayout flowLayout = (FlowLayout) panel_1.getLayout();
flowLayout.setAlignment(FlowLayout.LEFT);
panel_1.setMinimumSize(new Dimension(20, 20));
contentPane.add(panel_1, BorderLayout.SOUTH);
lblStatus = new JLabel("Status:");
lblStatus.setHorizontalAlignment(SwingConstants.LEFT);
lblStatus.setVerticalAlignment(SwingConstants.TOP);
panel_1.add(lblStatus);
xpathEvents = new XpathManager.Events() {
@Override
public void statusChanged(String status) {
lblStatus.setText(status);
}
@Override
public void executionCompleted(Object input, String results) { //buildXpathStatementThreaded finished, with results being the xpath statement
if (input instanceof HWND) { // in case thread takes long time to process
lastDragHwnd = Api.GetHandleAsString((HWND)input);
}
XpathManager.nextXpathMatch(results, textPane, lblStatus, true);
cmbXpath.setSelectedItem(results);
}
};
lblTarget.events = new dragEvents() {
public void dragStarted(JComponent c) {
//might be nice to minimize this window, if we weren't displaying realtime information about each window
}
public void dragMouseMoved(int x, int y) {
targetX = x;
targetY = y;
targetDragged();
}
public void dropped(JComponent c) {
lastDragHwnd = ""; //sometimes with multithreaded the order becomes incorrect, so we may want to refresh this on dropped.
targetDragged();
}
};
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
config.save();
SynthuseDlg.this.dispose(); // force app to close
}
});
btnRefresh.doClick();
refreshDatabinding();
}
/*
@Override
public void setVisible(final boolean visible) {
// make sure that frame is marked as not disposed if it is asked to be visible
if (visible) {
//setDisposed(false);
}
// let's handle visibility...
if (!visible || !isVisible()) { // have to check this condition simply because super.setVisible(true) invokes toFront if frame was already visible
super.setVisible(visible);
}
// ...and bring frame to the front.. in a strange and weird way
if (visible) {
int state = super.getExtendedState();
state &= ~JFrame.ICONIFIED;
super.setExtendedState(state);
super.setAlwaysOnTop(true);
super.toFront();
super.requestFocus();
super.setAlwaysOnTop(false);
}
}
*/
public String showDialog() {
//this.setModal(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
this.setVisible(true);
return dialogResult;
}
public void refreshDatabinding() {
if (config.xpathList != null)
cmbXpath.setModel(new DefaultComboBoxModel<String>(config.xpathList.split("<EFBFBD>")));
if (config.xpathHightlight != null)
XmlEditorKit.TAG_HIGHLIGHTED = config.xpathHightlight;
}
public void targetDragged() {
HWND hwnd = Api.GetWindowFromPoint(new Point(targetX,targetY));
String handleStr = Api.GetHandleAsString(hwnd);
String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd));
String parentStr = Api.GetHandleAsString(User32.instance.GetParent(hwnd));
lblStatus.setText("class: " + classStr + " hWnd: " + handleStr + " parent: " + parentStr + " X,Y: " + targetX + ", " + targetY);
if (!lastDragHwnd.equals(handleStr)) {
if (!lastDragHwnd.isEmpty()) {
Api.refreshWindow(Api.GetHandleFromString(lastDragHwnd));
}
lastDragHwnd = handleStr;
//lastDragHwnd = (hwnd + "");
Api.highlightWindow(hwnd);
XpathManager.buildXpathStatementThreaded(hwnd, textPane, xpathEvents);
}
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.ImageIcon;
import javax.swing.JToolBar;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Toolkit;
import javax.swing.JLabel;
public class TestIdeFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public JTextArea txtTest;
private JButton btnRun;
private JButton btnClear;
private JButton btnCopy;
private JLabel lblStatus;
/**
* Create the frame.
*/
public TestIdeFrame() {
setTitle("Test IDE - Synthuse");
setIconImage(Toolkit.getDefaultToolkit().getImage(TestIdeFrame.class.getResource("/org/qedsys/synthuse/applications-education.png")));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 700, 367);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JToolBar toolBar = new JToolBar();
contentPane.add(toolBar, BorderLayout.NORTH);
btnRun = new JButton("Run");
btnRun.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (btnRun.getText().equals("Run")) {
btnRun.setText("Stop");
btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/dialog-close.png")));
CommandProcessor.STOP_PROCESSOR.set(false);
CommandProcessor.executeThreaded(txtTest.getText(), new CommandProcessor.Events() {
@Override
public void statusChanged(String status) {
lblStatus.setText(status);
}
@Override
public void executionCompleted() {
btnRun.setText("Run");
btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/arrow-right-3.png")));
}
});
}
else {
CommandProcessor.STOP_PROCESSOR.set(true);
//btnRun.setText("Run");
//btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/arrow-right-3.png")));
}
}
});
btnRun.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/arrow-right-3.png")));
toolBar.add(btnRun);
btnClear = new JButton("Clear");
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
txtTest.setText("");
}
});
btnClear.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/user-trash-2.png")));
toolBar.add(btnClear);
btnCopy = new JButton("Copy Script");
btnCopy.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
StringSelection stringSelection = new StringSelection(txtTest.getText());
Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard();
clpbrd.setContents(stringSelection, null);
//StatusWindow sw = new StatusWindow("this is a test BLAH really long string goes here to test status of stuff yaya!!!!123123 123 123", 4000);
}
});
btnCopy.setIcon(new ImageIcon(SynthuseDlg.class.getResource("/org/qedsys/synthuse/edit-copy-7.png")));
toolBar.add(btnCopy);
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
txtTest = new JTextArea();
txtTest.setText("Click the Run button above to test the script below...\r\n\r\n");
scrollPane.setViewportView(txtTest);
lblStatus = new JLabel(" ");
contentPane.add(lblStatus, BorderLayout.SOUTH);
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
//TestIdeFrame.this.setVisible(false);
TestIdeFrame.this.dispose();
}
});
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import org.synthuse.Api.*;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.ptr.PointerByReference;
public class WindowInfo {
public HWND hwnd;
public String hwndStr = "";
public HWND parent = null;
public String parentStr = "";
public RECT rect;
public String text;
public String className = "";
public boolean isChild = false;
public String processName = "";
public long pid = 0;
public Object xmlObj = null;
public WindowInfo(HWND hWnd, boolean isChild) {
byte[] buffer = new byte[1024];
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
text = Native.toString(buffer);
if (text.isEmpty())
text = new Api().sendWmGetText(hWnd);
char[] buffer2 = new char[1026];
User32.instance.GetClassName(hWnd, buffer2, 1026);
className = Native.toString(buffer2);
rect = new RECT();
User32.instance.GetWindowRect(hWnd, rect);
this.isChild = isChild;
if (isChild) {
parent = User32.instance.GetParent(hWnd);
parentStr = Api.GetHandleAsString(parent);
}
else {
//User32.instance.GetWindowModuleFileName(hWnd, path, 512);
PointerByReference pointer = new PointerByReference();
User32.instance.GetWindowThreadProcessId(hWnd, pointer);
Pointer p = pointer.getPointer();
pid = p.getLong(0);
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);
//processName = Native.toString(path);
}
this.hwnd = hWnd;
hwndStr = Api.GetHandleAsString(hWnd);
}
public String toString() {
return String.format("(%d,%d)-(%d,%d) : \"%s\" [%s] {%s}", rect.left,rect.top,rect.right,rect.bottom,text,className,hwnd.toString());
}
}

View File

@@ -0,0 +1,253 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JLabel;
import javax.swing.JTextPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.HWND;
public class WindowsEnumeratedXml implements Runnable{
public static Exception lastException = null;
public JTextPane outputPane = null;
public JLabel lblStatus = null;
public WindowsEnumeratedXml() {
}
public WindowsEnumeratedXml(JTextPane outputPane, JLabel lblStatus) {
this.outputPane = outputPane;
this.lblStatus = lblStatus;
}
@Override
public void run() {
lblStatus.setText("Loading Windows Enumerated Xml...");
long startTime = System.nanoTime();
outputPane.setText(getXml());
outputPane.setCaretPosition(0);
double seconds = ((double)(System.nanoTime() - startTime) / 1000000000);
lblStatus.setText("Windows Enumerated Xml loaded in " + new DecimalFormat("#.###").format(seconds) + " seconds");
}
public static void getXmlThreaded(JTextPane outputPane, JLabel lblStatus) {
Thread t = new Thread(new WindowsEnumeratedXml(outputPane, lblStatus));
t.start();
}
public static String getXml() {
final Map<String, WindowInfo> infoList = new LinkedHashMap<String, WindowInfo>();
final Map<String, String> processList = new LinkedHashMap<String, String>();
class ChildWindowCallback implements WinUser.WNDENUMPROC {
@Override
public boolean callback(HWND hWnd, Pointer lParam) {
infoList.put(Api.GetHandleAsString(hWnd), new WindowInfo(hWnd, true));
return true;
}
}
class ParentWindowCallback implements WinUser.WNDENUMPROC {
@Override
public boolean callback(HWND hWnd, Pointer lParam) {
infoList.put(Api.GetHandleAsString(hWnd), new WindowInfo(hWnd, false));
Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0));
return true;
}
}
Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0);
// convert window info list to xml dom
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("EnumeratedWindows");
doc.appendChild(rootElement);
long parentCount = 0;
long childCount = 0;
for (String handle : infoList.keySet()) {
WindowInfo w = infoList.get(handle);
//System.out.println(w);
// create new win xml element
Element win = doc.createElement("win");
win.setAttribute("hwnd", w.hwndStr);
win.setAttribute("text", w.text);
win.setAttribute("TEXT", w.text.toUpperCase());
win.setAttribute("class", w.className);
win.setAttribute("CLASS", w.className.toUpperCase());
if (!w.isChild) {
parentCount++;
if (w.processName != null && !w.processName.isEmpty()) {
if (!processList.containsKey(w.pid+""))
processList.put(w.pid+"", w.hwndStr);
win.setAttribute("process", w.processName);
win.setAttribute("PROCESS", w.processName.toUpperCase());
win.setAttribute("pid", w.pid+"");
}
}
//else
//win.setAttribute("parent", w.parent + ""); // not really needed since child node is append to parent node
if (w.isChild && infoList.containsKey(w.parentStr)) {
childCount++;
WindowInfo parentWi = infoList.get(w.parentStr);
if (parentWi.xmlObj != null)
((Element)parentWi.xmlObj).appendChild(win);
else
rootElement.appendChild(win);
}
else
rootElement.appendChild(win);
w.xmlObj = win;
}
// calculate totals on various windows.
Element totals = doc.createElement("totals");
totals.setAttribute("parentCount", parentCount+"");
totals.setAttribute("childCount", childCount+"");
totals.setAttribute("windowCount", infoList.size()+"");
totals.setAttribute("processCount", processList.size()+"");
totals.setAttribute("updatedLast", new Timestamp((new Date()).getTime()) + "");
rootElement.appendChild(totals);
String output = nodeToString(rootElement);
//System.out.println("count - " + infoList.size() + "\r\n");
return output;
} catch (Exception e) {
e.printStackTrace();
lastException = e;
}
return "";
}
public static String escapeXmlAttributeValue(String unescapedStr) {
String result = "";
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("temp");
doc.appendChild(rootElement);
Attr attribute = doc.createAttribute("attrib");
attribute.setNodeValue(unescapedStr);
rootElement.setAttributeNode(attribute);
result = nodeToString(rootElement);
result = result.replaceAll("[^\"]*\"([^\"]*)\"[^\"]*", "$1"); // keep the string within quotes.
} catch (Exception e) {
e.printStackTrace();
//lastException = e;
}
return result;
}
private static String nodeToString(Node node) {
StringWriter sw = new StringWriter();
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
t.transform(new DOMSource(node), new StreamResult(sw));
} catch (Exception e) {
e.printStackTrace();
lastException = e;
}
return sw.toString();
}
public static String queryWindowInfoXml(String xpathExpr) {
String nl = System.getProperty("line.separator");
String result = "<result>" + nl;
String xml = getXml();
List<String> resultList = evaluateXpathGetValues(xml, xpathExpr);
for(String item: resultList) {
result += " " + item;
}
result += "</result>" + nl;
return result;
}
public static HWND queryHandleWindowInfoXml(String xpathExpr) {
String xml = getXml();
String result = "";
List<String> resultList = evaluateXpathGetValues(xml, xpathExpr);
for(String item: resultList) {
if (item.contains("hwnd")) {
List<String> hwndList = evaluateXpathGetValues(item, "//@hwnd");
result = hwndList.get(0);
}
else
result = item;
break;
}
return Api.GetHandleFromString(result);
}
public static List<String> evaluateXpathGetValues(String xml, String xpathExpr) {
List<String> resultLst = new ArrayList<String>();
try {
InputSource inSource = new InputSource(new StringReader(xml));
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile(xpathExpr);
Object result = expr.evaluate(inSource, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
String val = nodes.item(i).getNodeValue();
if (val == null) // if we can't get a string value try to transform the xml node to a string
val = nodeToString(nodes.item(i));
else
val += System.getProperty("line.separator");
resultLst.add(val);
//System.out.println("match " + i + ": " + val);
}
} catch(Exception e) {
e.printStackTrace();
lastException = e;
}
return resultLst;
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.Color;
import java.awt.Graphics;
import java.util.*;
import java.util.regex.*;
import javax.swing.text.*;
/* Example:
// Set editor kit
jtextpane.setEditorKitForContentType("text/xml", new XmlEditorKit());
jtextpane.setContentType("text/xml");
*/
public class XmlEditorKit extends StyledEditorKit {
private static final long serialVersionUID = 2969169649596107757L;
private ViewFactory xmlViewFactory;
private static HashMap<Pattern, Color> patternColors;
private static String TAG_PATTERN = "(</?[a-z]*)\\s?>?";
private static String TAG_END_PATTERN = "(/>)";
private static String TAG_ATTRIBUTE_PATTERN = "\\s([a-zA-Z0-9]*)\\s*?\\=\\s*?\\\"";
private static String TAG_ATTRIBUTE_VALUE = "[a-zA-Z0-9]*\\=(\"[^\"]*\")";
private static String TAG_COMMENT = "(<!--.*-->)";
private static String TAG_CDATA_START = "(\\<!\\[CDATA\\[).*";
private static String TAG_CDATA_END = ".*(]]>)";
//public static String TAG_HIGHLIGHTED = ".*hwnd=\"([^\"]*)\".*";
public static String TAG_HIGHLIGHTED = "";
public static Color TAG_HIGHLIGHTED_COLOR = new Color(170, 255, 48);
public static int HIGHLIGHTED_START = 0;
public static int HIGHLIGHTED_END = 0;
public static Color HIGHLIGHTED_COLOR = new Color(240, 255, 112);
static {
// NOTE: the order is important!
patternColors = new HashMap<Pattern, Color>();
patternColors.put(Pattern.compile(TAG_CDATA_START), new Color(128, 128, 128));
patternColors.put(Pattern.compile(TAG_CDATA_END), new Color(128, 128, 128));
patternColors.put(Pattern.compile(TAG_PATTERN), new Color(63, 127, 127));
patternColors.put(Pattern.compile(TAG_ATTRIBUTE_PATTERN), new Color(127, 0, 127));
patternColors.put(Pattern.compile(TAG_END_PATTERN), new Color(63, 127, 127));
patternColors.put(Pattern.compile(TAG_ATTRIBUTE_VALUE), new Color(42, 0, 255));
patternColors.put(Pattern.compile(TAG_COMMENT), new Color(63, 95, 191));
}
class XmlView extends PlainView {
public XmlView(Element element) {
super(element);
// Set tabsize to 4 (instead of the default 8)
getDocument().putProperty(PlainDocument.tabSizeAttribute, 4);
}
@Override
protected int drawUnselectedText(Graphics graphics, int x, int y, int p0, int p1) throws BadLocationException {
try {
Document doc = getDocument();
String text = doc.getText(p0, p1 - p0);
Segment segment = getLineBuffer();
int initialXpos = x;
SortedMap<Integer, Integer> startMap = new TreeMap<Integer, Integer>();
SortedMap<Integer, Color> colorMap = new TreeMap<Integer, Color>();
// Match all regexes on this snippet, store positions
for (Map.Entry<Pattern, Color> entry : patternColors.entrySet()) {
Matcher matcher = entry.getKey().matcher(text);
while (matcher.find()) {
startMap.put(matcher.start(1), matcher.end(1));
colorMap.put(matcher.start(1), entry.getValue());
}
}
// TODO: check the map for overlapping parts
int i = 0;
//add tag highlighted background colors
if (!TAG_HIGHLIGHTED.isEmpty()) {
Matcher highlightMatcher = Pattern.compile(TAG_HIGHLIGHTED).matcher(text);
while(highlightMatcher.find()) {
int start = highlightMatcher.start(1);
int end = highlightMatcher.end(1);
if (i < start) {
graphics.setColor(Color.black);
doc.getText(p0 + i, start - i, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
}
graphics.setColor(TAG_HIGHLIGHTED_COLOR);
i = end;
doc.getText(p0 + start, i - start, segment);
int width = Utilities.getTabbedTextWidth(segment, graphics.getFontMetrics(), x, this, p0 + start);
//graphics.drawLine(x, y, width, y);graphics.getFontMetrics()
graphics.fillRect(x, y - graphics.getFontMetrics().getHeight() + 2, width, graphics.getFontMetrics().getHeight());
graphics.setColor(Color.black);
doc.getText(p0 + start, i - start, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
}
}
x = initialXpos;
i=0;
//add highlighted background colors based on position
//String textx = doc.getText(p0, p1 - p0);
if ((HIGHLIGHTED_START < p1 && HIGHLIGHTED_START >= p0) || (HIGHLIGHTED_END <= p1 && HIGHLIGHTED_END > p0) || ( HIGHLIGHTED_START < p1 && HIGHLIGHTED_END > p0)) {
//select whole line
int start = 0;
int end = text.length();
// test to see if only partial line is needed.
if (HIGHLIGHTED_START > p0)
start = HIGHLIGHTED_START - p0;
if (HIGHLIGHTED_END < p1)
end -= p1 - HIGHLIGHTED_END;
if (i < start) { // fill in normal color if start highlight isn't at the beginning
graphics.setColor(Color.black);
doc.getText(p0 + i, start - i, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
}
graphics.setColor(HIGHLIGHTED_COLOR);// fill in the highlight color
i = end;
if (i - start > 0) {
doc.getText(p0 + start, i - start, segment);
int width = Utilities.getTabbedTextWidth(segment, graphics.getFontMetrics(), x, this, p0 + start);
//graphics.drawLine(x, y, width, y);graphics.getFontMetrics()
graphics.fillRect(x, y - graphics.getFontMetrics().getHeight() + 2, width, graphics.getFontMetrics().getHeight());
graphics.setColor(Color.black);
doc.getText(p0 + start, i - start, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
}
//else
// System.out.println("invalid highlighting " + (i - start) + " is <= 0 (" + p0 + "-" + p1 + "=" + (p1 - p0) +") " + start + ", " + end + " len=" + text.length());
}
x = initialXpos;
i=0;
// Color the parts of xml foreground font
for (Map.Entry<Integer, Integer> entry : startMap.entrySet()) {
int start = entry.getKey();
int end = entry.getValue();
if (i < start) {
graphics.setColor(Color.black);
doc.getText(p0 + i, start - i, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
}
graphics.setColor(colorMap.get(start));
i = end;
doc.getText(p0 + start, i - start, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
}
// Paint possible remaining text black
if (i < text.length()) {
graphics.setColor(Color.black);
doc.getText(p0 + i, text.length() - i, segment);
x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
}
} catch (Exception e) {
e.printStackTrace();
}
return x;
}
}
class XmlViewFactory extends Object implements ViewFactory {
/**
* @see javax.swing.text.ViewFactory#create(javax.swing.text.Element)
*/
public View create(Element element) {
return new XmlView(element);
}
}
public XmlEditorKit() {
xmlViewFactory = new XmlViewFactory();
}
@Override
public ViewFactory getViewFactory() {
return xmlViewFactory;
}
@Override
public String getContentType() {
return "text/xml";
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse;
import java.awt.EventQueue;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import org.synthuse.Api.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
public class XpathManager implements Runnable{
private HWND hwnd = null;
private JTextPane windowsXmlTextPane = null;
public static interface Events {
void statusChanged(String status);
void executionCompleted(Object input, String results);
}
public Events events = new Events() {
public void statusChanged(String status){
System.out.println(status);
}
public void executionCompleted(Object input, String results){
}
};
public XpathManager(HWND hwnd, JTextPane windowsXmlTextPane, Events events) {
this.events = events;
this.hwnd = hwnd;
this.windowsXmlTextPane = windowsXmlTextPane;
}
@Override
public void run() {
String results = buildXpathStatement();
events.executionCompleted(hwnd, results);
}
public static void buildXpathStatementThreaded(HWND hwnd, JTextPane windowsXmlTextPane, Events events) {
Thread t = new Thread(new XpathManager(hwnd, windowsXmlTextPane, events));
t.start();
}
public String buildXpathStatement() {
String builtXpath = "";
try {
String classStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(hwnd));
String handleStr = Api.GetHandleAsString(hwnd);
String txtOrig = Api.GetWindowText(hwnd);
String txtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(txtOrig);
String xml = this.windowsXmlTextPane.getText();
builtXpath = "//win[@class='" + classStr + "']";
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
//int matches = nextXpathMatch(builtXpath, textPane, true);
if (resultList.size() > 1) { // if there are multiple results with the simple xpath then include parent class and text with the xpath statement.
HWND parent = User32.instance.GetParent(hwnd);
String parentClassStr = WindowsEnumeratedXml.escapeXmlAttributeValue(Api.GetWindowClassName(parent));
String parentTxtOrig = Api.GetWindowText(parent);
String parentTxtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(parentTxtOrig);
if (!parentTxtStr.isEmpty()) {
if (parentTxtOrig.length() > 20) {// if the parent text is too long only test the first 20 characters
parentTxtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(parentTxtOrig.substring(0, 20));
parentTxtStr = " and starts-with(@text,'" + parentTxtStr + "')";
}
else
parentTxtStr = " and @text='" + parentTxtStr + "'";
}
if (!parentClassStr.isEmpty())
builtXpath = "//win[@class='" + parentClassStr + "'" + parentTxtStr + "]/win[@class='" + classStr + "']";
resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, builtXpath);
if (resultList.size() > 1) { // if there are still multiple results add position to the xpath
int position = 1;
for (String result : resultList) {
if (result.contains(handleStr)) {
builtXpath += "[" + position + "]";
break;
}
++position;
}
}
if (resultList.size() == 0) { //some reason a window might have a parent window that is not associated with it's child (orphans!!)
if (!txtStr.isEmpty()) {
if (parentTxtOrig.length() > 30) {// if the text is too long only test the first 20 characters
txtStr = WindowsEnumeratedXml.escapeXmlAttributeValue(txtStr.substring(0, 30));
txtStr = " and starts-with(@text,'" + txtStr + "')";
}
else
txtStr = " and @text='" + txtStr + "'";
}
builtXpath = "//win[@class='" + classStr + "'" + txtStr + "]";
}
}
} catch (Exception e) {
e.printStackTrace();
}
return builtXpath;
}
public static int nextXpathMatch(String xpathExpr, JTextPane targetText, JLabel lblStatus, boolean alwaysFromTop) {
int results = 0;
try {
if (xpathExpr.length() == 0)
return results;
if (targetText instanceof JTextPane) {
final JTextPane target = (JTextPane)targetText;
target.requestFocus();
int cPos = target.getCaretPosition();
if (alwaysFromTop)
cPos = 0;
int len = target.getStyledDocument().getLength();
String xml = target.getText(0, len);
WindowsEnumeratedXml.lastException = null;
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(xml, xpathExpr);
if (resultList.size() == 0 && WindowsEnumeratedXml.lastException != null) {
String errMsg = WindowsEnumeratedXml.lastException.getCause().getMessage();
JOptionPane.showMessageDialog(null, "Exception: " + errMsg, "Error", JOptionPane.ERROR_MESSAGE);
return -1;
}
results = resultList.size();
String txt = "";
String targetStr = target.getText(cPos, (len - cPos));
int matches = 0;
int mPos = 0;
target.select(cPos, cPos); //clear selection
for (int i = 0; i < resultList.size(); i++) {
txt = resultList.get(i).trim();
if (txt.length() == 0)
continue;
//if (txt.endsWith("\r\n"))
// txt = txt.substring(0, txt.length() - 2).trim();
txt = txt.replaceAll("\r\n", "\n").trim();
while ((mPos = targetStr.indexOf(txt)) != -1) {
if (matches == 0){
if (!alwaysFromTop)
flashMatchingWindow(txt);
//target.setCaretPosition(cPos + mPos);
//target.select(cPos + mPos, cPos + mPos + txt.length());
XmlEditorKit.HIGHLIGHTED_START = cPos + mPos;
XmlEditorKit.HIGHLIGHTED_END = cPos + mPos + txt.length();
//System.out.println("HIGHLIGHTED_START = " + (cPos + mPos));
//System.out.println("HIGHLIGHTED_END = " + (cPos + mPos + txt.length()));
final int cpos = cPos + mPos +2;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
target.updateUI();
target.setCaretPosition(cpos);
}
});
}
targetStr = targetStr.substring(mPos + txt.length());
++matches;
}
}
lblStatus.setText(results + " matches");
if (cPos > 0 && matches == 0 && !alwaysFromTop) { //ask if user wants to search from top
int result = JOptionPane.showConfirmDialog(null, "No more matches found. Do you want to search from the top of the document?", "Find", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
target.setCaretPosition(0);
nextXpathMatch(xpathExpr, targetText, lblStatus, alwaysFromTop);
}
}
}
} catch (Exception e) {
XmlEditorKit.HIGHLIGHTED_START = 0;
XmlEditorKit.HIGHLIGHTED_END = 0;
e.printStackTrace();
}
return results;
}
public static void flashMatchingWindow(String txtXml) {
if (txtXml.contains("hwnd")) {
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(txtXml, "//@hwnd");
if (hwndList.size() > 0) {
String hwndStr = hwndList.get(0);
HWND tHwnd = Api.GetHandleFromString(hwndStr);
Api.highlightWindow(tHwnd);
try { Thread.sleep(100); } catch (Exception e) {e.printStackTrace();}
Api.refreshWindow(tHwnd);
try { Thread.sleep(100); } catch (Exception e) {e.printStackTrace();}
Api.highlightWindow(tHwnd);
try { Thread.sleep(100); } catch (Exception e) {e.printStackTrace();}
Api.refreshWindow(tHwnd);
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB