#java #jna
#java #jna
Вопрос:
Я написал некоторый Java-код.
как запустить Chrome с помощью JNA в Windows (32bit).
тогда я хотел бы разобраться в этом.
Как вы знаете, FindWindow — это простое решение, но если chrome не запущен, это не сработает.
возможен приведенный ниже подобный код?
HWND hwnd = User32.CreateProcess(...);
приведенный ниже код открывает chrome.
но настройка размера, maxmizing не работает.
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);
}
}
Ответ №1:
Если Chrome не запущен, вы, конечно, не сможете получить дескриптор его окна, потому что такого окна не существует. Возможно, вы захотите запустить Chrome, используя что-то вроде ProcessBuilder, а затем вызвать что-то вроде этого:
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" ) amp;amp; !windowClass.toLowerCase().equals( "progman" ) amp;amp; !windowTitle.equals( "" ) amp;amp; !windowClass.toLowerCase().equals( "shell_traywnd" ) )
{
listOfWindows.put( hWnd, getWindowParentRectangle( hWnd ) );
}
// }
}
return true;
}
else
{
return false;
}
}
}, 0 );
Конечно, это уже рабочий код, в котором есть некоторые условия, специфичные для моего приложения. Но основная идея заключается в
вызовите EnumWindows с помощью WndEnumProc(), который поместит все найденные окна в коллекцию (в моем случае в HashMap ). Затем, после возврата EnumWindows, у вас будет коллекция окон в вашей переменной listOfWindows, и вы сможете получить hwnd Chrome, если он был запущен во время вызова EnumWindows.
Вы должны определить EnumWindows в вашем экземпляре user32 следующим образом:
/**
* 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 );
Вы также должны определить свою структуру WndEnumProc в классе (мой был назван Structures) примерно так:
public static interface WndEnumProc extends StdCallLibrary.StdCallCallback
{
boolean callback ( int hWnd, int lParam );
}
Надеюсь, это поможет. Пожалуйста, обратите внимание, что Chrome должен быть запущен, пока вы творите все это волшебство. Запустить его, как я отметил в начале, должно быть относительно просто с помощью ProcessBuilder или, если вы не хотите сильно заморачиваться и Chrome находится на вашем пути, вы можете использовать
System.getRuntime().exec("chrome.exe")
чтобы запустить Chrome.