Reputation: 3970
I wrote some java code.
how to run chrome using JNA in windows(32bit).
then I like to get the hwnd of it.
As you know, FindWindow is simple solution but if chrome doesn't running, it doesn't work.
below like code is possible?
HWND hwnd = User32.CreateProcess(...);
below code open chrome. but sizing, maxmizing doesn't work.
public interface Kernel32 extends StdCallLibrary {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
boolean CreateProcessA(
String lpApplicationName
, String lpCommandLine
, Structure lpProcessAttributes
, Structure lpThreadAttributes
, boolean bInheritHandles
, int dwCreationFlags
, Structure lpEnvironment
, String lpCurrentDirectory
, Structure lpStartupInfo
, Structure lpProcessInformation);
}
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public class ProcessInformation extends Structure {
public Pointer hProcess;
public Pointer hThread;
public int dwProcessId;
public int dwThreadId;
}
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
public class StartupInfoA extends Structure {
public int cb;
public WString lpReserved;
public WString lpDesktop;
public WString lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public Pointer lpReserved2;
public Pointer hStdInput;
public Pointer hStdOutput;
public Pointer hStdError;
}
public class Test {
public static void main(String[] args) {
int STARTF_USEPOSITION = 0x00000004;
int STARTF_USESIZE = 0x00000002;
int STARTF_USESHOWWINDOW = 0x00000001;
ProcessInformation processInformation = new ProcessInformation();
StartupInfoA startupInfo = new StartupInfoA();
startupInfo.dwX = 100;
startupInfo.dwY = 100;
startupInfo.dwXSize = 100;
startupInfo.dwYSize = 100;
startupInfo.wShowWindow = (short) SW_MAXIMIZE;
startupInfo.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;
Kernel32.INSTANCE.CreateProcessA(new String("C:\\Users.....\\Google\\Chrome\\Application\\chrome.exe")
, null
, null
, null
, true
, 0
, null
, null
, startupInfo
, processInformation);
}
}
Upvotes: 2
Views: 1299
Reputation: 10216
If Chrome is not running, you can't get a handle of its window, of course, because such a window does not exist. You might want to run Chrome, using something like ProcessBuilder, then call something like this:
user32.EnumWindows( new WndEnumProc()
{
@SuppressWarnings ( "AssignmentToMethodParameter" )
public boolean callback ( int hWnd, int lParam )
{
if ( user32.IsWindow( hWnd ) )
{
if ( user32.IsWindowVisible( hWnd ) )
{
RECT r = new RECT();
user32.GetWindowRect( hWnd, r );
// if (r.left > -32000) // is not minimized
//{
String windowTitle = getWindowParentName( hWnd );
String windowClass = getWindowParentClassName( hWnd );
hWnd = user32.GetAncestor( hWnd, 3 );
if ( !windowTitle.toLowerCase().equals( "program manager" ) && !windowClass.toLowerCase().equals( "progman" ) && !windowTitle.equals( "" ) && !windowClass.toLowerCase().equals( "shell_traywnd" ) )
{
listOfWindows.put( hWnd, getWindowParentRectangle( hWnd ) );
}
// }
}
return true;
}
else
{
return false;
}
}
}, 0 );
Of course, this is already working code that has some conditions specific to my app. But the main idea is to call EnumWindows with a WndEnumProc() that will put all windows it finds to a collection ( in my case an HashMap ). Then after the EnumWindows returns, you will have a collection of windows in your listOfWindows variable and you will be able to get the hwnd of Chrome if it was running during the time EnumWindows was called.
You should define EnumWindows in your user32 instance like this:
/**
* Enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function.
* @param wndenumproc A pointer to an application-defined callback function.
* @param lParam An application-defined value to be passed to the callback function.
* @return if the function succeeded.
* <a href="http://msdn.microsoft.com/en-us/library/ms633497(v=VS.85).aspx"> <b>Microsoft Reference</b></a><br>
*/
public boolean EnumWindows ( WndEnumProc wndenumproc, int lParam );
You should also define your WndEnumProc structure in a class (mine was named Structures) something like this:
public static interface WndEnumProc extends StdCallLibrary.StdCallCallback
{
boolean callback ( int hWnd, int lParam );
}
Hope that helps. Please note that Chrome must be running while you are doing all that magic. Running it, as I noted in the beginning, should be relatively straightforward using a ProcessBuilder or if you don't want to bother much and Chrome is in your path, you can use
System.getRuntime().exec("chrome.exe")
to start Chrome.
Upvotes: 2