Saturday, November 12, 2011

Customized User32 JNA Interface for controlling Windows programs



This is the customized User32 interface for controlling calculator.
Method added for calculator is:

public WinDef.HWND FindWindowEx(WinDef.HWND hwndParent, WinDef.HWND hwndChildAfter, String lpszClass, String lpszWindow);

/**
* Customized User32 Interface for controlling Windows programs from Java.
*/

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public abstract interface User32 extends StdCallLibrary
{
public static final User32 INSTANCE = (User32)Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);

public abstract WinDef.HDC GetDC(WinDef.HWND paramHWND);

public abstract int ReleaseDC(WinDef.HWND paramHWND, WinDef.HDC paramHDC);

public abstract WinDef.HWND FindWindow(String paramString1, String paramString2);

public abstract int GetClassName(WinDef.HWND paramHWND, char[] paramArrayOfChar, int paramInt);

public abstract boolean GetGUIThreadInfo(int paramInt, WinUser.GUITHREADINFO paramGUITHREADINFO);

public abstract boolean GetWindowInfo(WinDef.HWND paramHWND, WinUser.WINDOWINFO paramWINDOWINFO);

public abstract boolean GetWindowRect(WinDef.HWND paramHWND, WinDef.RECT paramRECT);

public abstract int GetWindowText(WinDef.HWND paramHWND, char[] paramArrayOfChar, int paramInt);

public abstract int GetWindowTextLength(WinDef.HWND paramHWND);

public abstract int GetWindowModuleFileName(WinDef.HWND paramHWND, char[] paramArrayOfChar, int paramInt);

public abstract int GetWindowThreadProcessId(WinDef.HWND paramHWND, IntByReference paramIntByReference);

public abstract boolean EnumWindows(WinUser.WNDENUMPROC paramWNDENUMPROC, Pointer paramPointer);

public abstract boolean EnumChildWindows(WinDef.HWND paramHWND, WinUser.WNDENUMPROC paramWNDENUMPROC, Pointer paramPointer);

public abstract boolean EnumThreadWindows(int paramInt, WinUser.WNDENUMPROC paramWNDENUMPROC, Pointer paramPointer);

public abstract boolean FlashWindowEx(WinUser.FLASHWINFO paramFLASHWINFO);

public abstract WinDef.HICON LoadIcon(WinDef.HINSTANCE paramHINSTANCE, String paramString);

public abstract WinNT.HANDLE LoadImage(WinDef.HINSTANCE paramHINSTANCE, String paramString, int paramInt1, int paramInt2, int paramInt3, int paramInt4);

public abstract boolean DestroyIcon(WinDef.HICON paramHICON);

public abstract int GetWindowLong(WinDef.HWND paramHWND, int paramInt);

public abstract int SetWindowLong(WinDef.HWND paramHWND, int paramInt1, int paramInt2);

public abstract Pointer SetWindowLong(WinDef.HWND paramHWND, int paramInt, Pointer paramPointer);

public abstract BaseTSD.LONG_PTR GetWindowLongPtr(WinDef.HWND paramHWND, int paramInt);

public abstract BaseTSD.LONG_PTR SetWindowLongPtr(WinDef.HWND paramHWND, int paramInt, BaseTSD.LONG_PTR paramLONG_PTR);

public abstract Pointer SetWindowLongPtr(WinDef.HWND paramHWND, int paramInt, Pointer paramPointer);

public abstract boolean SetLayeredWindowAttributes(WinDef.HWND paramHWND, int paramInt1, byte paramByte, int paramInt2);

public abstract boolean GetLayeredWindowAttributes(WinDef.HWND paramHWND, IntByReference paramIntByReference1, ByteByReference paramByteByReference, IntByReference paramIntByReference2);

public abstract boolean UpdateLayeredWindow(WinDef.HWND paramHWND, WinDef.HDC paramHDC1, WinUser.POINT paramPOINT1, WinUser.SIZE paramSIZE, WinDef.HDC paramHDC2, WinUser.POINT paramPOINT2, int paramInt1, WinUser.BLENDFUNCTION paramBLENDFUNCTION, int paramInt2);

public abstract int SetWindowRgn(WinDef.HWND paramHWND, WinDef.HRGN paramHRGN, boolean paramBoolean);

public abstract boolean GetKeyboardState(byte[] paramArrayOfByte);

public abstract short GetAsyncKeyState(int paramInt);

public abstract WinUser.HHOOK SetWindowsHookEx(int paramInt1, WinUser.HOOKPROC paramHOOKPROC, WinDef.HINSTANCE paramHINSTANCE, int paramInt2);

public abstract WinDef.LRESULT CallNextHookEx(WinUser.HHOOK paramHHOOK, int paramInt, WinDef.WPARAM paramWPARAM, WinDef.LPARAM paramLPARAM);

public abstract WinDef.LRESULT CallNextHookEx(WinUser.HHOOK paramHHOOK, int paramInt, WinDef.WPARAM paramWPARAM, Pointer paramPointer);

public abstract boolean UnhookWindowsHookEx(WinUser.HHOOK paramHHOOK);

public abstract int GetMessage(WinUser.MSG paramMSG, WinDef.HWND paramHWND, int paramInt1, int paramInt2);

public abstract boolean PeekMessage(WinUser.MSG paramMSG, WinDef.HWND paramHWND, int paramInt1, int paramInt2, int paramInt3);

public abstract boolean TranslateMessage(WinUser.MSG paramMSG);

public abstract WinDef.LRESULT DispatchMessage(WinUser.MSG paramMSG);

public abstract void PostMessage(WinDef.HWND paramHWND, int paramInt, WinDef.WPARAM paramWPARAM, WinDef.LPARAM paramLPARAM);

public abstract void PostQuitMessage(int paramInt);

public abstract int GetSystemMetrics(int paramInt);

public WinDef.HWND FindWindowEx(WinDef.HWND hwndParent, WinDef.HWND hwndChildAfter, String lpszClass, String lpszWindow);
         
public boolean LockWorkStation();

public void mouse_event(int dwFlags, int dx, int dy, int dwData,int dwExtraInfo);
}

Controlling CALCULATOR from Java Program

Winamp is controlled. Now let us control Windows calculator program using Java code and JNA.

This is similar to controlling Winamp. Same concept is used here. For more details about the concept CLICK.


import java.io.IOException;

import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import controlled.impl.utils.User32;  ==> This interface is defined below in the article: CLICK

/**
 * This class controls the Windows Calculator.
 * @author Santosh Pai
 */
public class CalculatorControl {

private HWND calcWindowHandle;

/**
* User32 DLL instance
*/
       public User32 USER32INST;


    /**
     * When a number / operator is recognized the value is sent to this method, which takes
     * care of performing the whole operation and shows the result.
     * @param command Operator / Operand
     */
  public  void sendCommandToCalculator(String buttonName){

HWND hwndChild = USER32INST.FindWindowEx((HWND)calcWindowHandle,null,"Button",buttonName);

                    WinDef.WPARAM wParamValue = new WinDef.WPARAM(Long.parseLong("0"));
 
   WinDef.LPARAM lParamValue = new WinDef.LPARAM(Long.parseLong("0"));

     USER32INST.PostMessage(hwndChild,245, wParamValue, lParamValue);

}

public void init() {

USER32INST = User32.INSTANCE;

calcWindowHandle = USER32INST.FindWindow(null,"Calculator");

if(calcWindowHandle != null){
  System.out.println("CALCULATOR is running.");
  return;
}
else{
System.out.println("CALCULATOR is not running.");
System.out.println("Strating the CALCULATOR.");

try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
System.out.println("Internal Error. CALCULATOR cannot be started.");
e.printStackTrace();
return;
}

calcWindowHandle = USER32INST.FindWindow(null,"Calculator");

return;
}

}

}

Wednesday, November 9, 2011

Controlling WINAMP from Java Program

Yes. It is possible to control Winamp media player from a Java program. This is very simple. Before we discuss the code let me show you a simple diagram for understanding the logic.

Java Navite Access is a project which provides access to Windows APIs using Java code. Writing programs using JNA is very very simple. Read More about JNA....

Using JNA we get the Java representation of the Winamp Window. Then send different message codes (one per operaion) to the window handle.

The Java code is self explainable:



import java.util.HashMap;
import java.util.Map;

import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.User32;

/**
 * This class controls the Winamp Media Player.
 * @author Santosh Pai
 */
public class WinampControl {

/**
* This is a map which stores the command values per operation.
*/
private static Map<String,String[]> h ;
static{
h = new HashMap<String,String[]>();
h.put("play", new String[]{"40045","0"});
h.put("stop", new String[]{"40047","0"});
h.put("pause", new String[]{"40046","0"});
h.put("next", new String[]{"40048","0"});
h.put("previous", new String[]{"40044","0"});
}

/**
* User32 DLL instance
*/
    public static User32 USER32INST;

  /**
* This method checks if the Winamp Window is currently present. i.e, Winamp is running.
* @param windowClass Name of the window class
* @param windowName Name of the window
* @return Return window handle in case winamp is running, else retun NULL.
*/
public static HWND isWinampRunning(){

HWND windowHandle = USER32INST.FindWindow("Winamp v1.x",null);

if(windowHandle != null)
  return windowHandle;
else{
System.out.println("WINAMP is not running.");
  return null;
}

}

/**
     * This method is used to send the control commands to Winamp. Before sending any command,
     * the method checks if the Winamp is open or not. If winamp is running the command
     * is sent using Windows User32 DLL sendMessage function.
     * @param windowClassName The name is used as Winamp v1.x
     * @param command Command to control the Winamp
     */
public static void sendCommandToWinamp(String command){
USER32INST = User32.INSTANCE;
//Check if the winamp is running
HWND winampHandle = isWinampRunning();

if(null != winampHandle){

   String[] values = h.get(command);
 
   WinDef.WPARAM wParamValue = new WinDef.WPARAM(Long.parseLong(values[0]));
 
   WinDef.LPARAM lParamValue = new WinDef.LPARAM(Long.parseLong(values[1]));

   //Send the command to the Winamp Window and control it
   USER32INST.PostMessage(winampHandle,273, wParamValue, lParamValue);

}

}

}

So now the Winamp is CONTROLLED :-) ...

I will post more code in future. I am working on a project "CONTROLLED".