MyPage is a personalized page based on your interests.The page is customized to help you to find content that matters you the most.


I'm not curious

TUTORIAL: Hosting WPF Content in a Java Application

Published on 13 January 13
596
1
0

Hosting WPF Content in a Java Application

TUTORIAL: Hosting WPF Content in a Java Application - Image 1

Background

The main ideas of Java /.NET integration are described in [4]. There I provide a code sample for embedding .NET GUI components into Java GUI. If the reader is not familiar with Object-Oriented JNI for .NET, I recommend reading this article first. For this demo project, I used the same WPF component as [1].

Integrating Java Application with WPF/.Net Component Modules

The main ideas of Java and .NET code integration described in [4] where I showed an example of embedding .NET GUI components into Java interface. For anybody who is not familiar with Object-Oriented JNI for .NET, I recommend reading this article first. Description of Windows Presentation Foundation (WPF) can be found in MSDN, special manuals and is also not discussed in this article. WPF Module used in my example (without sources) was borrowed from [1]. Here I set out only with the task of embedding WMF Component into Java GUI.

Writing Java Code

From Java side, any WPF/.NET component is a piece of native code that should be wrapped with some Java classes. Special interface in Java is dealing with WPF/.NET components. Interface must include methods for:

  • creating of component instances (create)
  • destroying instances when Java code exits (dispose)

In the attached sample code, I embed WPF Clock component [1] into Java GUI. Method updateClock sets new Date/Time. Arbitrary native GUI element can be embedded into Java user interface components withjava.awt.Canvas class as a base Java UI component class. java.awt.Canvas is a Java Component with Windows, i.e. a heavy-weight component, that does not implement the paint method. Class com.oojni.WPFContainerinherits from java.awt.Canvas. Any WPF component is windowless and must be added into a .NET Container, which is bound to window of java.awt.Canvas class.
In the provided sample of Java code, there are placeholders used as interops for .NET components. The interop for WPF Component is com.oojni.WPFContainer class:

package com.oojni; import java.awt.Canvas; /** * The interop for WPF Container * * @author Vitaly Shelest */ public class WPFContainer extends Canvas { static{ System.loadLibrary("oojni.net20"); System.loadLibrary("JavaHostWPF"); } /** * Stores a reference to .NET Container */ int ref = 0; /** * The place to create .NET Container */ public void addNotify() { super.addNotify(); ref = create(this); } /** * Used to dispose .NET Container */ public void removeNotify() { dispose(ref); super.removeNotify(); } /** * Disposes .NET Container */ public void dispose() { if(ref != 0) dispose(ref); ref = 0; } /** * Updates WPF Clock with a new time/date selection */ void updateClock() { updateClock(ref); } /** * Updates WPF Clock * @param ref reference to .NET Container */ native void updateClock(int ref); /** * Creates .NET Container * @param parent Java component as a placeholder for .NET Container * @return reference to .NET Container */ native int create(Object parent); /** * Disposes .NET Container * @param ref reference to .NET Container */ native void dispose(int ref); }


This class overrides two java.awt.Canvas methods:

  • addNotify, called by JVM while creating java.awt.Canvas instance. This is the place where a native WPF/.NET Component container can be created, the native create method returns some integer value (I call it a .NET component reference). In .NET code this value is converted into WPF/.NET Component container instance when a native method is executed.
  • removeNotify, called by JVM on destroy of java.awt.Canvas instance. In this method, WPF/.NET Component container is destroyed with the native method dispose.
  • The same interop was designed for Calendar Container - com.oojni.CalendarContainer. The rest of the code implements the usual SWING GUI of Java application.

.NET JNI Module Design

In .NET JNI code, I implement methods that:

  • Acquire handle of window hWnd from Java component. Handle hWnd is further utilized
  • Create .NET Component Container instance in the native implementation of the create method and addshWnd of this .NET Component Container as a child window of the Java component
  • Fill .NET Component Container instance with .NET GUI components


Here is the implementation of the
com.oojni.WPFContainer native method create:

/// <summary> /// Implements Native Method create that creates Component Container reference /// </summary> /// <param name="parent">com.oojni.CalendarContainer instance</param> /// <returns>WPF Clock Container reference</returns> public override int create(ObjectOrientedJNI.JObject parent) { WPFCreator creator = new WPFCreator(parent); thread = new System.Threading.Thread (new System.Threading.ThreadStart(creator.Create)); thread.SetApartmentState(System.Threading.ApartmentState.STA); thread.Start(); creator.autoEvent.WaitOne(); GlobalReference gref = new GlobalReference(creator.Control, true); return gref.Reference.ToInt32(); }

In STA Thread, I call create method of ObjectOrientedJNIInterop.com.oojni.WPFCreator class instance where .NET WPF Container (class ObjectOrientedJNIInterop.com.oojni.WPFControl) is created. In OnLoadEvent of ObjectOrientedJNIInterop.com.oojni.WPFControl I create WPF Clock component:

private void WPFControl_Load(object sender, EventArgs e) { // Create WPF Clock Component instance here.  // First wrap HWND of Java Placeholder.  ObjectOrientedJNIInterop.java.awt.CanvasJNIProxy canvas = new ObjectOrientedJNIInterop.java.awt.CanvasJNIProxy(parent); // Initialize create parameters  System.Windows.Interop.HwndSourceParameters sourceParams = new System.Windows.Interop.HwndSourceParameters("JavaWPFApp"); // Set Size and Location of WPF Clock  sourceParams.PositionX = 0; sourceParams.PositionY = 0; sourceParams.Height = canvas.getHeight(); sourceParams.Width = canvas.getWidth(); sourceParams.ParentWindow = this.Handle; sourceParams.WindowStyle = WS_VISIBLE | WS_CHILD; // Wrap EmbeddedFrame HWND, this component is embedded into Java Placeholder  hwndSource = new System.Windows.Interop.HwndSource(sourceParams); // Set Date/Time to WPF Clock and put WPF Clock component into HwndSource  DateTime tm = DateTime.Now; clock = new WPFControls.AnimClock(); clock.ChangeDateTime(tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second); System.Windows.FrameworkElement myPage = clock; hwndSource.RootVisual = myPage; }


This piece of .NET code shows how to call a Java native method in STA Thread context.

delegate void UpdateClock(int peer); /// <summary> /// Implementation of native method updateClock /// </summary> /// <param name="peer">WPF Clock Container reference</param> public override void updateClock(int peer) { // Restore the instance of WPF Clock Container  GlobalReference gr = new GlobalReference(peer, true); object o = gr.Object; // Call updateClock in STA Thread Context  if (((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).InvokeRequired) ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).Invoke (new UpdateClock(updateClock), new object[] { peer }); else { // Initialize WPF Clock Component with new values  ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).clock.ChangeDateTime (CalendarCreator.currentDateTime.Year, CalendarCreator.currentDateTime.Month, CalendarCreator.currentDateTime.Day, CalendarCreator.currentDateTime.Hour, CalendarCreator.currentDateTime.Minute, CalendarCreator.currentDateTime.Second); System.Windows.FrameworkElement myPage = ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).clock; ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o). hwndSource.RootVisual = myPage; } }

Prerequisites to Run the Example Attached

Development Tools

  • Microsoft Visual Studio 2005 or above
  • Microsoft .NET Framework 3.0 or above
  • Java SUN/IBM 1.6 and above
  • Java SUN/IBM 1.3 and above to recompile Java sources

Operating Systems

  • Windows Vista
  • Windows XP SP2
  • Windows Server 2003 SP1

References

  1. Choong,K.,2008, Hosting WPF Content in an MFC Application [Online], CodeGuru
  2. Shelest,V.,2007, OOJNI Add-in .NET (C#) for VS2005/2008 [Online], Simtel
  3. Shelest,V.,2006, OOJNI for .NET2.0 (low-level) [Online], Simtel
  4. Shelest,V.,2006, Java/.NET Integration as Simple as Possible [Online], The Code Project
This article is brought to you by Vitaly Shelest, Software Developer (Senior) Javain Ltd. This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL).









Hosting WPF Content in a Java Application

TUTORIAL: Hosting WPF Content in a Java Application - Image 1

Background

The main ideas of Java /.NET integration are described in [4]. There I provide a code sample for embedding .NET GUI components into Java GUI. If the reader is not familiar with Object-Oriented JNI for .NET, I recommend reading this article first. For this demo project, I used the same WPF component as [1].

Integrating Java Application with WPF/.Net Component Modules

The main ideas of Java and .NET code integration described in [4] where I showed an example of embedding .NET GUI components into Java interface. For anybody who is not familiar with Object-Oriented JNI for .NET, I recommend reading this article first. Description of Windows Presentation Foundation (WPF) can be found in MSDN, special manuals and is also not discussed in this article. WPF Module used in my example (without sources) was borrowed from [1]. Here I set out only with the task of embedding WMF Component into Java GUI.

Writing Java Code

From Java side, any WPF/.NET component is a piece of native code that should be wrapped with some Java classes. Special interface in Java is dealing with WPF/.NET components. Interface must include methods for:

  • creating of component instances (create)
  • destroying instances when Java code exits (dispose)
In the attached sample code, I embed WPF Clock component [1] into Java GUI. Method updateClock sets new Date/Time. Arbitrary native GUI element can be embedded into Java user interface components withjava.awt.Canvas class as a base Java UI component class. java.awt.Canvas is a Java Component with Windows, i.e. a heavy-weight component, that does not implement the paint method. Class com.oojni.WPFContainerinherits from java.awt.Canvas. Any WPF component is windowless and must be added into a .NET Container, which is bound to window of java.awt.Canvas class.
In the provided sample of Java code, there are placeholders used as interops for .NET components. The interop for WPF Component is com.oojni.WPFContainer class:

package com.oojni; import java.awt.Canvas; /** * The interop for WPF Container * * @author Vitaly Shelest */ public class WPFContainer extends Canvas { static{ System.loadLibrary("oojni.net20"); System.loadLibrary("JavaHostWPF"); } /** * Stores a reference to .NET Container */ int ref = 0; /** * The place to create .NET Container */ public void addNotify() { super.addNotify(); ref = create(this); } /** * Used to dispose .NET Container */ public void removeNotify() { dispose(ref); super.removeNotify(); } /** * Disposes .NET Container */ public void dispose() { if(ref != 0) dispose(ref); ref = 0; } /** * Updates WPF Clock with a new time/date selection */ void updateClock() { updateClock(ref); } /** * Updates WPF Clock * @param ref reference to .NET Container */ native void updateClock(int ref); /** * Creates .NET Container * @param parent Java component as a placeholder for .NET Container * @return reference to .NET Container */ native int create(Object parent); /** * Disposes .NET Container * @param ref reference to .NET Container */ native void dispose(int ref); }

This class overrides two java.awt.Canvas methods:

  • addNotify, called by JVM while creating java.awt.Canvas instance. This is the place where a native WPF/.NET Component container can be created, the native create method returns some integer value (I call it a .NET component reference). In .NET code this value is converted into WPF/.NET Component container instance when a native method is executed.
  • removeNotify, called by JVM on destroy of java.awt.Canvas instance. In this method, WPF/.NET Component container is destroyed with the native method dispose.
  • The same interop was designed for Calendar Container - com.oojni.CalendarContainer. The rest of the code implements the usual SWING GUI of Java application.
.NET JNI Module Design

In .NET JNI code, I implement methods that:

  • Acquire handle of window hWnd from Java component. Handle hWnd is further utilized
  • Create .NET Component Container instance in the native implementation of the create method and addshWnd of this .NET Component Container as a child window of the Java component
  • Fill .NET Component Container instance with .NET GUI components

Here is the implementation of the com.oojni.WPFContainer native method create:

/// /// Implements Native Method create that creates Component Container reference /// /// com.oojni.CalendarContainer instance /// WPF Clock Container referencepublic override int create(ObjectOrientedJNI.JObject parent) { WPFCreator creator = new WPFCreator(parent); thread = new System.Threading.Thread (new System.Threading.ThreadStart(creator.Create)); thread.SetApartmentState(System.Threading.ApartmentState.STA); thread.Start(); creator.autoEvent.WaitOne(); GlobalReference gref = new GlobalReference(creator.Control, true); return gref.Reference.ToInt32(); }In STA Thread, I call create method of ObjectOrientedJNIInterop.com.oojni.WPFCreator class instance where .NET WPF Container (class ObjectOrientedJNIInterop.com.oojni.WPFControl) is created. In OnLoadEvent of ObjectOrientedJNIInterop.com.oojni.WPFControl I create WPF Clock component:

private void WPFControl_Load(object sender, EventArgs e) { // Create WPF Clock Component instance here. // First wrap HWND of Java Placeholder. ObjectOrientedJNIInterop.java.awt.CanvasJNIProxy canvas = new ObjectOrientedJNIInterop.java.awt.CanvasJNIProxy(parent); // Initialize create parameters System.Windows.Interop.HwndSourceParameters sourceParams = new System.Windows.Interop.HwndSourceParameters("JavaWPFApp"); // Set Size and Location of WPF Clock sourceParams.PositionX = 0; sourceParams.PositionY = 0; sourceParams.Height = canvas.getHeight(); sourceParams.Width = canvas.getWidth(); sourceParams.ParentWindow = this.Handle; sourceParams.WindowStyle = WS_VISIBLE | WS_CHILD; // Wrap EmbeddedFrame HWND, this component is embedded into Java Placeholder hwndSource = new System.Windows.Interop.HwndSource(sourceParams); // Set Date/Time to WPF Clock and put WPF Clock component into HwndSource DateTime tm = DateTime.Now; clock = new WPFControls.AnimClock(); clock.ChangeDateTime(tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second); System.Windows.FrameworkElement myPage = clock; hwndSource.RootVisual = myPage; }

This piece of .NET code shows how to call a Java native method in STA Thread context.

delegate void UpdateClock(int peer); /// /// Implementation of native method updateClock /// /// WPF Clock Container reference public override void updateClock(int peer) { // Restore the instance of WPF Clock Container GlobalReference gr = new GlobalReference(peer, true); object o = gr.Object; // Call updateClock in STA Thread Context if (((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).InvokeRequired) ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).Invoke (new UpdateClock(updateClock), new object[] { peer }); else { // Initialize WPF Clock Component with new values ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).clock.ChangeDateTime (CalendarCreator.currentDateTime.Year, CalendarCreator.currentDateTime.Month, CalendarCreator.currentDateTime.Day, CalendarCreator.currentDateTime.Hour, CalendarCreator.currentDateTime.Minute, CalendarCreator.currentDateTime.Second); System.Windows.FrameworkElement myPage = ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o).clock; ((ObjectOrientedJNIInterop.com.oojni.WPFControl)o). hwndSource.RootVisual = myPage; } }Prerequisites to Run the Example Attached

Development Tools

  • Microsoft Visual Studio 2005 or above
  • Microsoft .NET Framework 3.0 or above
  • Java SUN/IBM 1.6 and above
  • Java SUN/IBM 1.3 and above to recompile Java sources
Operating Systems

  • Windows Vista
  • Windows XP SP2
  • Windows Server 2003 SP1
References

  1. Choong,K.,2008, Hosting WPF Content in an MFC Application [Online], CodeGuru
  2. Shelest,V.,2007, OOJNI Add-in .NET (C#) for VS2005/2008 [Online], Simtel
  3. Shelest,V.,2006, OOJNI for .NET2.0 (low-level) [Online], Simtel
  4. Shelest,V.,2006, Java/.NET Integration as Simple as Possible [Online], The Code Project
This article is brought to you by Vitaly Shelest, Software Developer (Senior) Javain Ltd. This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL).

This blog is listed under Development & Implementations Community

View Comment (1)
Post a Comment

Please notify me the replies via email.

Important:
  • We hope the conversations that take place on MyTechLogy.com will be constructive and thought-provoking.
  • To ensure the quality of the discussion, our moderators may review/edit the comments for clarity and relevance.
  • Comments that are promotional, mean-spirited, or off-topic may be deleted per the moderators' judgment.
  1. 22 September 15
    0

    Hi clev, Very useful detailed information on TUTORIAL: Hosting WPF Content in a Java Application. especially good and to the point code included in this blog. I am searching such [Java questions and answers](http://findnerd.com/askquestion/java) on google, I found your blog. http://findnerd.com/askquestion/java

You may also be interested in
Awards & Accolades for MyTechLogy
Winner of
REDHERRING
Top 100 Asia
Finalist at SiTF Awards 2014 under the category Best Social & Community Product
Finalist at HR Vendor of the Year 2015 Awards under the category Best Learning Management System
Finalist at HR Vendor of the Year 2015 Awards under the category Best Talent Management Software
Hidden Image Url

Back to Top