native-window-host
demonstrates Proof of Concept how can native windows (e.g win32 window on Windows) might be embedded/hosted (hosted) in Java and C# GUI elements.
Java concept uses Java Native Access
and C# uses HwndHost
from the WPF framework.
See java for Java implementation and C# for C# implementation with WPF.
Currently, only Windows concept is implemented.
Java implementation uses the JNA and Canvas
component from the AWT. Canvas
is used because it's a heavy-weight component (it has its own handle, e.g. HWND
on Windows) and thus has ability to become a parent of native system window.
The basic idea is that when this inherited Canvas
component (i.e. NativeWindowHost
) become parent window (SetParent(...)
call in Windows), all system messages that are sent to the Canvas
are also sent to the child (the native window). Because of this parent-child relationship, the GUI-related things like moving, resizing, work (more or less) out of the box.
Demo is located at java/windows/source/com/github/karel-burda/native-window-host/demo/Main.java.
The concept is using the HwndHost
component on Windows from WPF that effectively works well without much code needed.
The only catch is to use set the correct window style to the native window (WS_CHILD
).
Currently not implemented.
C# and Java uses helper app that creates and shows dummy window with specified class name, this resides in common/windows/win32-demo-helper-app.
Build process is meant to be performed like this:
cmake -Bbuild -H.
cmake --build build
Java project is built using CMake: CMakeLists.txt.
Projects is divided into separate targets that are built (and also run) using CMake:
native-window-host-java.jar
-- makes the core functionality, depends on the JNAnative-window-host-java-demo.jar
-- demonstration example
The build itself is being executed using:
cmake -Bbuild -H. -DJNA_PATH:PATH=<absolute-path-to-jna> -DJDK_VERSION:STRING=<version>
cmake --build build
where <absolute-path-to-jna>
is absolute path to the directory where jna.jar
and jna-platform.jar
reside.
<version>
is an optional parameter of the JDK used, e.g. 1.8
.
Demo might be run using (after the generation step is done, you can skip the cmake --build build
):
cmake --build build --target run-demo
Core class providing functionality is NativeWindowHost.java
To be done.
For full use cases, see Main.java.
import com.github.karelburda.nativewindowhost.NativeWindowHost;
public class Main {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setSize(1200, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// using variant of constructor where window class name is known (the other one is with HWND)
final NativeWindowHost host = new NativeWindowHost("win32-demo-helper-app");
host.setSize(frame.getWidth(), frame.getHeight());
host.setVisible(true);
frame.add(host, BorderLayout.CENTER);
// upon closing, we may want to "release" the native handle from the embedder
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(final WindowEvent event) {
host.release();
System.exit(0);
}
});
}
}
Currently no automatic tests, because of difficult testing in headless (mode without window managers from the OS) environment on the CI.
To perform manual integration test, you can run the demo. Steps are:
- Run the
win32-demo-helper-app
- Run the demo (e.g. using CMake to execute the JAR)
Continuous Integration is now being run on Linux on Travis: https://travis-ci.org/karel-burda/native-window-host.
The project is using these jobs:
win32-demo-helper-app -- windows, release, msvc, 32-bit
native-window-host, example -- linux, jdk 1.8, 64-bit
Build of the project, core and demo, is performed, see .travis.yml.