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

8
.classpath Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="lib" path="lib/jna-3.4.0.jar"/>
<classpathentry kind="lib" path="lib/platform-3.4.0.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Synthuse</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

BIN
lib/jna-3.4.0.jar Normal file

Binary file not shown.

BIN
lib/platform-3.4.0.jar Normal file

Binary file not shown.

30
readme.txt Normal file
View File

@@ -0,0 +1,30 @@
Synthuse
Version 1.0.5 released on 1-30-2014
By Edward Jakubowski ejakubowski7@gmail.com
Description:
Synthuse is a portable java base software testing framework for desktop windows
applications. This framework has a built-in object spy and automation Test IDE.
What makes this different from other frameworks is that it shares similar command
syntax as Selenium. It also utilizes Xpath statements to locate target windows/objects
The familar syntaxes makes it easier to train automation tester in this frameworks.
Configurations:
All configurable settings are stored in the following file: synthuse.properties
Changes to this file will not take affect until you restart the application.
Example synthuse.properties file below:
urlList=
xpathList=//win[@class\='Notepad']\u00BA
xpathHightlight=.*process\="([^"]*)".*
Software Requirements:
- Java 1.6 or greater
Release Notes:
1-30-2014 version 1.0.5
- Base version

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

6
synthuse.properties Normal file
View File

@@ -0,0 +1,6 @@
#
#Sun Feb 16 21:34:31 EST 2014
DEFAULT_PROP_FILENAME=
urlList=
xpathList=
xpathHightlight=.*process\="([^"]*)".*