Dear users,
I have a program that starts up a notepad, and I want it to be contained inside a java application.
Like: Code to Host a Third Party Application in our Process Window (e.g. Google Chrome, Internet Explorer 8) - CodeProject
Everything runs fine, but finally the SetParent does not work at all, but it return a pointer (showing me that it is success)
The SetParent() does not set the parent, but everything seems to be fine.
The windows supports the following functions to handle windows:
Content not found...
The following is done:
CreateProcessA() called to start notepad (and I used it because java does not allow me to retrieve process id).
WaitForInputIdle() used to wait for the window to become visible, and to retrieve its handle.
GetTopWindow(null), GetWindowThreadProcessId(w, pid), GetWindow(w, 2); is used to find the window of the given process id. (If I close the notepad before these are executed the system does not find a window for that process id, so it works as well)
Finally the SetParent() is used to set the parent
From the microsoft msdn:
"If the function succeeds, the return value is a handle to the previous parent window."
And it does return a pointer!
Result:
The notepad window does not hosted
Here are the files I use:
--- APPLICATION -------------------
---------------------------------------------------package com.smith; import java.awt.BorderLayout; import java.awt.Canvas; import java.awt.Component; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingUtilities; import com.smith.Kernel32.ProcessInformation; import com.smith.Kernel32.StartupInfoA; import com.sun.jna.Native; import com.sun.jna.Platform; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; public class Main implements Runnable { public static void main(String[] args) { Main main = new Main(); SwingUtilities.invokeLater(main); } public Pointer getWindowOf(int pid) { Pointer w = User32.INSTANCE.GetTopWindow(null); IntByReference iptr = new IntByReference(); while (w != null) { User32.INSTANCE.GetWindowThreadProcessId(w, iptr); if (iptr.getValue() == pid) { return w; } w = User32.INSTANCE.GetWindow(w, 2); } return null; } private String host(String prog, Component heavy) { ProcessInformation pi = this.runAndWait(prog); heavy.setPreferredSize(new Dimension(600, 500)); Pointer handle = Native.getComponentPointer(heavy); Pointer procWnd = this.getWindowOf(pi.dwProcessId); Pointer last = User32.INSTANCE.SetParent(procWnd, handle); if (last == null) { throw new IllegalArgumentException("Can not set parent: " + Kernel32.INSTANCE.GetLastError()); } return "Started: " + pi.dwProcessId + " (window: " + procWnd + ") -> Java parent: " + handle; } @Override public void run() { JFrame frame = new JFrame("Hosting Window"); frame.setPreferredSize(new Dimension(500, 600)); JLabel label = new JLabel("Alma"); frame.setLayout(new BorderLayout()); frame.add(label, BorderLayout.NORTH); Component heavy = new Canvas(); frame.add(heavy, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); try { String ret = this.host("c:\\Windows\\notepad.exe", heavy); label.setText(ret); } catch (IllegalArgumentException ia) { label.setText(ia.getMessage()); } } private ProcessInformation runAndWait(String program) { ProcessInformation processInformation = new ProcessInformation(); StartupInfoA startupInfo = new StartupInfoA(); startupInfo.cb = Platform.is64Bit() ? 104 : 68; boolean ok = Kernel32.INSTANCE.CreateProcessA(program, null, null, null, true, 0x00000020, null, null, startupInfo, processInformation); if (ok) { User32.INSTANCE.WaitForInputIdle(processInformation.hProcess, -1); } else { throw new IllegalArgumentException("Executing '" + program + "' failed: " + Kernel32.INSTANCE.GetLastError()); } return processInformation; } }
----------------------------------------------------package com.smith; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.Structure; public interface Kernel32 extends Library { public class ProcessInformation extends Structure { public Pointer hProcess; public Pointer hThread; public int dwProcessId; public int dwThreadId; } public class StartupInfoA extends Structure { public int cb; public String lpReserved; public String lpDesktop; public String 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; } Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class); boolean CreateProcessA(String lpApplicationName, String lpCommandLine, Pointer lpProcessAttributes, Pointer lpThreadAttributes, boolean bInheritHandles, long dwCreationFlags, Pointer lpEnvironment, String lpCurrentDirectory, StartupInfoA lpStartupInfo, ProcessInformation lpProcessInformation); int GetLastError(); }
package com.smith; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; public interface User32 extends Library { User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class); Pointer GetTopWindow(Pointer wnd); Pointer GetWindow(Pointer wnd, int cmd); int GetWindowThreadProcessId(Pointer wnd, IntByReference ptr); Pointer SetParent(Pointer hWndChild, Pointer hWndNewParent); int WaitForInputIdle(Pointer process, int timeout); }