在swt extension中,引入了function这个类。基本上所有的win32 jni库都有这个类,用来直接操纵win32 的部分api。有了这个class,我们不用编写jni,就可以实现某些简单的,甚至是较复杂的win32 api。这里我们就以enumwindows这个api举例,看看怎么java来执行这个win32 api。
private static final string funtion_enumwindows = "enumwindows";
private static final string user32_lib = "user32";
private static list windowslist = new arraylist();
public static int[] enumwindows()
{
windowslist.clear();
callback callback = new callback(windows.class, "enumwindowsproc", 2);
int address = callback.getaddress();
if (address != 0)
{
try
{
function function = new function(user32_lib, funtion_enumwindows);
function.invoke_i(address, 0);
function.close();
} catch (exception e)
{
swt.error(swt.error_invalid_argument);
}
callback.dispose();
}
int[] handles = new int[windowslist.size()];
for (int i = 0; i windowslist.size(); i++)
handles[i] = ((long) windowslist.get(i)).value;
return handles;
}
private static int enumwindowsproc(int hwnd, int lparam)
{
windowslist.add(new long(hwnd));
return 1;
}enumwindows是用来遍历windows窗口的api,它需要传入一个返回boolean值的callback的地址作为参数。实际上在c里面,一个boolean值无非就是是否非0,如果为0,则为false,不为0,则为true。我们只需要new 一个function实例,传入这个api所在的lib和api名字,然后执行invoke方法就ok了,在function里面,可以最多执行含有4个简单类型参数的api。
让我们再来看看findwindowex这个api,它需要传入2个int变量和2个字符串指针,根据swt的设计,我们是可以将java的字符串转换为指针的,因此通过function我们也可以实现这个api:
private static final string funtion_findwindowex = extension.isunicode ? "findwindowexw"
: "findwindowexa";
private static final string user32_lib = "user32";
public static int findwindowex(int parent, int hwndchildafter, string classname,
string windowname)
{
int result = 0;
int lpclassname = 0;
int lpwindowname = 0;
int hheap = extension.getprocessheap();
if (classname != null)
{
tchar buffer = new tchar(0, classname, true);
int bytecount = buffer.length() * tchar.sizeof;
lpclassname = extension.heapalloc(hheap, extension.heap_zero_memory, bytecount);
extension.movememory(lpclassname, buffer, bytecount);
}
if (windowname != null)
{
tchar buffer = new tchar(0, windowname, true);
int bytecount = buffer.length() * tchar.sizeof;
lpwindowname = extension.heapalloc(hheap, extension.heap_zero_memory, bytecount);
extension.movememory(lpwindowname, buffer, bytecount);
}
try
{
function function = new function(user32_lib, funtion_findwindowex);
result = function.invoke_i(parent, hwndchildafter, lpclassname, lpwindowname);
function.close();
} catch (exception e)
{
swt.error(swt.error_invalid_argument);
}
if (lpclassname != 0) extension.heapfree(hheap, 0, lpclassname);
if (lpwindowname != 0) extension.heapfree(hheap, 0, lpwindowname);
return result;
}其实像这种简单参数类型的api,win32 里还有很多,我们完全不必为其专门编写jni,只需使用熟悉的java即可。虽然不是调用全部的api,但大部分常用的api都是没有问题的,关键是如何灵活运用。现在的大型商业rcp应用中,其实多多少少都参和了jni,用于提升对用户的友好性和软件的执行性能,毕竟java天生就是客户端开发的矮子。对于jni,我们既不能一味排斥,也不能滥用,要把握一个平衡点,使之成为java客户端开发的利器。
注:IT公司速查网所有信息来自互联网