Making Native Windows API calls from
within a Java Application
One of the main points of Java is to be completely platform independent.
However, sometimes it will occur that the developer of an application will
know that his or her application is only going to be run on a specific
platform, for example, Win32.
NOTE: This example assumes that you are using JDK 1.2 or
later.
Below are the steps for writing a Java application that makes a Win32
API call. The application generates a Swing Jframe and makes it system
modal, or gives it the Always On Top functionality, similar to that of
the Windows NT Task Manager.
-----
Steps to follow:
1. Write the Java code for the application
2. Run javah.exe on your .class file to generate a
C header file
3. write the implementation of your native methods
4. create the shared library
5. run the application
-----
1. Write the Java code for the application
import java.awt.*;
import sun.awt.*;
import sun.awt.windows.*;
import javax.swing.*;
import java.awt.event.*;
public class Frame1 extends
JFrame {
int windowHWND =
0;
JButton jButton1
= new JButton();
public Frame1()
{
//windowHWND
= this.getHwnd();
try
{
jbInit();
}
catch(Exception
e) {
e.printStackTrace();
}
}
public int getHwnd()
{
DrawingSurfaceInfo
w = (DrawingSurfaceInfo) ((DrawingSurface) getPeer()).getDrawingSurfaceInfo();
w.lock();
WDrawingSurfaceInfo
win32 = (WDrawingSurfaceInfo) w;
int hwnd = win32.getHWnd();
w.unlock();
return hwnd;
}
static
{
System.loadLibrary("windowOnTop");
}
public static native
void WindowAlwaysOnTop(int hwnd, boolean flag);
public static void
main(String[] args) {
Frame1
frame11 = new Frame1();
frame11.setSize(400,400);
frame11.setVisible(true);
}
private void jbInit()
throws Exception {
jButton1.setText("jButton1");
this.addWindowListener(new
java.awt.event.WindowAdapter() {
public void windowOpened(WindowEvent e) {
this_windowOpened(e);
}
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
this.getContentPane().add(jButton1,
BorderLayout.NORTH);
}
void this_windowOpened(WindowEvent
e) {
windowHWND = this.getHwnd();
System.out.println("the value is: " + this.getHwnd());
this.WindowAlwaysOnTop(windowHWND, true);
}
void this_windowClosing(WindowEvent
e) {
System.exit(0);
}
}
Once the code is written, compile it with Jbuilder or the command
line javac.exe tool which will result in a generated .class file.
You will use this .class file in the next step.
-----
2. Run javah.exe on your .class file to generate a C header file
The following line represents the basic syntax for running javah.exe:
javah Frame1
where Frame1 is the name of the argument class.
When you run javah.exe, it will generate a header file by the same name
as your implementation but with a .h file extension. For this example
the .h file that was generated from the above Java code will be emitted
being that it is quite large.
NOTE: Make sure that when you run javah.exe, it is the javah.exe
that came with the same JDK that you will be compiling with as there may
be some issues with using a version of javah.exe that is different from
that of the JDK you are using to compile.
-----
3. write the implementation of your native methods
Now that you have your Java source and your C header file, it is time
to write the implementation of your native methods.
Following is the C code that corresponds to the native methods declared
in the Java code listed in step 1:
#include "jni.h"
#include "Frame1.h"
#include <stdio.h>
#include<windows.h>
JNIEXPORT void JNICALL
Java_Frame1_WindowAlwaysOnTop(JNIEnv *env, jclass obj, jint hwnd, jboolean
flag)
{
if (flag)
SetWindowPos((HWND)
hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
else
SetWindowPos((HWND)
hwnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
return;
}
You will notice several things: one is that the function signature has
Java_Frame1_ preceeding the name of the function. If there was
a package statement in the Java source, it would appear after Frame1_
in the function signature.
Second, you will notice the #include jni.h. Normally this would
be #include<jni.h>, depending on how you have your libraries set up
within your C compiler.
-----
4. create the shared library
Now you are ready to create the shared library. Using your C compiler,
create a .dll file with the code from the C implementation file.
Refer to the doccumentation of the C compiler for details on creating a
.dll file.
---------------------------------------------------------------------
For those interested in using Borland C++ Builder:
If you have got it installed, you could use Borland C++ Builder 3 or
C++ Builder 4 to create your DLL file. If this is the case, you would
use File | New... | DLL C++ Builder will then generate some
code for you, and you will just need to add your implementation code to
the code which was generated.
---------------------------------------------------------------------
Remember in the Java code in step one there is a line:
static {
System.loadLibrary("windowOnTop");
}
windowOnTop is the name of the .dll file. You can name it whatever
you want, just make sure that you specify the appropriate name when loading
the library.
-----
5. run the application
Finally you are ready to run the application. From the command
line use java.exe and as the argument specify the name of the class that
you compiled in step one. Once the system loads your DLL, the window
that the VM creates should mimic the Always On Top functionality.
-----
|