Skip to main content

How to display a Java2D lightweight component on top of a heavy weight window that has been reparented?

4 replies [Last post]
Anonymous

Hi,

I'm trying to overlay a transparent JPanel on top of a native Window
that has been reparented using the approach below: I'm using Overlayout
to layer to panels on top of eachother. The native Window (DirectX)
always displays above the lightweight component. I had thought that JDK
7 allowed this, but I must not be doing something right. Has anybody
successfully done this type of thing? (I know it can be done since JOGL
windows can be mixed with lightweight components now.)

Thanks!

Rob

void attachRenderHwnd() {
//hide GE main window
try {
User32.ShowWindow(getMainHwnd(), 0); //hide GE main window
} catch (COMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

resizeGERenderHwnd();

//attach GE render window to the GUI
try {
FuncPtr setParent = new FuncPtr("USER32.DLL", "SetParent");
setParent.invoke_I(getRenderHwnd(), this.getGUIHwnd(),
ReturnFlags.CHECK_FALSE);
} catch (COMException e) {
e.printStackTrace();
}
}

private void resizeGERenderHwnd() {
try {
FuncPtr moveWindow = new FuncPtr("USER32.DLL", "MoveWindow");
// create a NakedByteStream for the serialization of Java
variables
NakedByteStream nbs = new NakedByteStream();
// wrap it in a LittleEndianOutputStream
LittleEndianOutputStream leos = new
LittleEndianOutputStream(nbs);
// and then write the Java arguments
leos.writeInt(getRenderHwnd()); //Handle to the window

Point myCorner = new Point(this.getX(),this.getY());
JFrame frame =
(JFrame)SwingUtilities.getAncestorOfClass(JFrame.class, this);
Point corner = SwingUtilities.convertPoint(this,myCorner,
frame.getContentPane());

leos.writeInt(corner.x); //Specifies the new position of the
left side of the window
leos.writeInt(corner.y); //Specifies the new position of the
top of the window
leos.writeInt((int) this.getWidth()); // Specifies
the new width of the window
leos.writeInt((int) this.getHeight()); // Specifies
the new height of the window
leos.writeBoolean(false); //Specifies whether the
window is to be repainted //
moveWindow.invoke("IIIII:I:", 24, nbs, null,
ReturnFlags.CHECK_FALSE);
} catch (IOException e) {
e.printStackTrace();
} catch (COMException e) {
e.printStackTrace();
}
}

public final static Field getDeclaredField(Class clazz, String
fieldName) throws NoSuchFieldException {
Class c = clazz;
while (c != null && c != Object.class) {
try {
return c.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
}
c = c.getSuperclass();
}
throw new NoSuchFieldException(fieldName);
}

private int getGUIHwnd() {
int hwnd = 0;
System.loadLibrary("jawt");

sun.awt.windows.WToolkit tk = (sun.awt.windows.WToolkit)
this.getToolkit();
System.out.println("tk" + tk);

Window w = SwingUtilities.getWindowAncestor(this);

Object peer = tk.targetToPeer(w);
System.out.println("peer\n" + peer);

try {

Class c = peer.getClass();
System.out.println("class\n" + c);

this.f = this.getDeclaredField(c,"hwnd");
System.out.println("Field\n" + f);

f.setAccessible(true);
Object result = f.get(peer);
//return

hwnd = ((Long) result).intValue();

} catch (Throwable t) {

throw new RuntimeException(t.toString());

}
return hwnd;
}

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Chris Campbell

Hi Rob,

It's not possible to draw on top of heavyweight components (like your
embedded Google Earth panel) using Java 2D. The problem with
heavyweight components is that they are, by nature, in control of
their own rendering process: their rendering "blows through" directly
to the screen, and we can't get in the way. I don't think you'll be
able to get around this restriction other than using screenshot
tricks like you suggested (in another thread). Another option would
be to use NASA's WorldWind component, which has the benefit of being
written in Java/JOGL and provides more embedding options (e.g. using
the lightweight GLJPanel, which would allow for the overlayed
rendering you're seeking).

Chris

On Dec 5, 2007, at 12:50 PM, Rob Ratcliff wrote:
> Hi,
>
> I'm trying to overlay a transparent JPanel on top of a native Window
> that has been reparented using the approach below: I'm using
> Overlayout
> to layer to panels on top of eachother. The native Window (DirectX)
> always displays above the lightweight component. I had thought that
> JDK
> 7 allowed this, but I must not be doing something right. Has anybody
> successfully done this type of thing? (I know it can be done since
> JOGL
> windows can be mixed with lightweight components now.)
>
> Thanks!
>
> Rob
>
>
> void attachRenderHwnd() {
> //hide GE main window
> try {
> User32.ShowWindow(getMainHwnd(), 0); //hide GE main window
> } catch (COMException e) {
> e.printStackTrace();
> } catch (IOException e) {
> e.printStackTrace();
> }
>
> resizeGERenderHwnd();
>
> //attach GE render window to the GUI
> try {
> FuncPtr setParent = new FuncPtr("USER32.DLL",
> "SetParent");
> setParent.invoke_I(getRenderHwnd(), this.getGUIHwnd(),
> ReturnFlags.CHECK_FALSE);
> } catch (COMException e) {
> e.printStackTrace();
> }
> }
>
> private void resizeGERenderHwnd() {
> try {
> FuncPtr moveWindow = new FuncPtr("USER32.DLL",
> "MoveWindow");
> // create a NakedByteStream for the serialization of Java
> variables
> NakedByteStream nbs = new NakedByteStream();
> // wrap it in a LittleEndianOutputStream
> LittleEndianOutputStream leos = new
> LittleEndianOutputStream(nbs);
> // and then write the Java arguments
> leos.writeInt(getRenderHwnd()); //Handle to the window
>
> Point myCorner = new Point(this.getX(),this.getY());
> JFrame frame =
> (JFrame)SwingUtilities.getAncestorOfClass(JFrame.class, this);
> Point corner = SwingUtilities.convertPoint(this,myCorner,
> frame.getContentPane());
>
> leos.writeInt(corner.x); //Specifies the new position
> of the
> left side of the window
> leos.writeInt(corner.y); //Specifies the new position
> of the
> top of the window
> leos.writeInt((int) this.getWidth()); // Specifies
> the new width of the window
> leos.writeInt((int) this.getHeight()); // Specifies
> the new height of the window
> leos.writeBoolean(false); //Specifies whether the
> window is to be repainted //
> moveWindow.invoke("IIIII:I:", 24, nbs, null,
> ReturnFlags.CHECK_FALSE);
> } catch (IOException e) {
> e.printStackTrace();
> } catch (COMException e) {
> e.printStackTrace();
> }
> }
>
> public final static Field getDeclaredField(Class clazz, String
> fieldName) throws NoSuchFieldException {
> Class c = clazz;
> while (c != null && c != Object.class) {
> try {
> return c.getDeclaredField(fieldName);
> } catch (NoSuchFieldException e) {
> }
> c = c.getSuperclass();
> }
> throw new NoSuchFieldException(fieldName);
> }
>
> private int getGUIHwnd() {
> int hwnd = 0;
> System.loadLibrary("jawt");
>
> sun.awt.windows.WToolkit tk = (sun.awt.windows.WToolkit)
> this.getToolkit();
> System.out.println("tk" + tk);
>
> Window w = SwingUtilities.getWindowAncestor(this);
>
> Object peer = tk.targetToPeer(w);
> System.out.println("peer\n" + peer);
>
> try {
>
> Class c = peer.getClass();
> System.out.println("class\n" + c);
>
> this.f = this.getDeclaredField(c,"hwnd");
> System.out.println("Field\n" + f);
>
> f.setAccessible(true);
> Object result = f.get(peer);
> //return
>
> hwnd = ((Long) result).intValue();
>
> } catch (Throwable t) {
>
> throw new RuntimeException(t.toString());
>
> }
> return hwnd;
> }
>
> ======================================================================
> =====
> To unsubscribe, send email to listserv@java.sun.com and include in
> the body
> of the message "signoff JAVA2D-INTEREST". For general help, send
> email to
> listserv@java.sun.com and include in the body of the message "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Rob Ratcliff

Thanks Chris for the response and the info.

I wonder what would happened if GE got reparented into a GLJPanel? (If
that is even possible.)
One thing that I was thought was odd was that even if I overlayed an AWT
panel on top of the reparented GE panel that GE still came through on
top. I would've thought that would've worked. (I'm looking at the
Windows API to see about moving the z-order of the windows.)

I have looked at Nasa's WW and may prototype something with that in the
future depending on various things, but I need to get my current
approach working first despite the limitations.

Thanks!

Rob

Chris Campbell wrote:
> Hi Rob,
>
> It's not possible to draw on top of heavyweight components (like your
> embedded Google Earth panel) using Java 2D. The problem with
> heavyweight components is that they are, by nature, in control of
> their own rendering process: their rendering "blows through" directly
> to the screen, and we can't get in the way. I don't think you'll be
> able to get around this restriction other than using screenshot tricks
> like you suggested (in another thread). Another option would be to
> use NASA's WorldWind component, which has the benefit of being written
> in Java/JOGL and provides more embedding options (e.g. using the
> lightweight GLJPanel, which would allow for the overlayed rendering
> you're seeking).
>
> Chris
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

jb489
Offline
Joined: 2008-03-13

Hey Robert,

any news on this thread. I am doing the same thing, need to put the google earth render inside one of my applications, though I am having problems fitting it exactly into a JPanel or any other container other than a JFrame, which by the way still does not centre properly.

James

Rob Ratcliff

Hi James,

I was able to get it to fit into a JPanel and resize correctly (for most
instances.) I resorted to doing the drawing on the screenshot hack to
deal with the lightweight component overlaying a heavyweight window
(create screen shot of window, hide 3D window, draw polygon for
instance, send polygon KML to Google Earth, show 3D window.) I'd be
happy to send you my source if you're interested.

Of course, NASA's World Wind using the new JOGL has solved the
heavyweight/lightweight mixing problem, which is very cool, so I'd
recommend using WW if you want a 3D map.
(I think the mixing works best on nVidia graphics cards though.)

BTW, I read on the WW message board, that somebody wrote a plug-in that
can access GE server data, which I believe would be legal if you bought
your own GE map server and populated it with data from the NGA for
instance. (The only reason I was trying to embed GE into a Java
application was that Google has a richer dataset that streams faster
than the default WW servers.)

java2d@JAVADESKTOP.ORG wrote:
> Hey Robert,
>
> any news on this thread. I am doing the same thing, need to put the google earth render inside one of my applications, though I am having problems fitting it exactly into a JPanel or any other container other than a JFrame, which by the way still does not centre properly.
>
> James
> [Message sent by forum member 'jb489' (jb489)]
>
> http://forums.java.net/jive/thread.jspa?messageID=263893
>
> ===========================================================================
> To unsubscribe, send email to listserv@java.sun.com and include in the body
> of the message "signoff JAVA2D-INTEREST". For general help, send email to
> listserv@java.sun.com and include in the body of the message "help".
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".