在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客户端开发的利器。
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
相关专题
- Java基础知识:初学者必须理解的六大问题 (76次浏览)
- 九个非常值得一看的MySpace程序 (72次浏览)
- struts验证框架开发详解 (48次浏览)
- 关于提高自己水平的十大技术 (47次浏览)
- Flex测试工具RIATest Beta版发布 (45次浏览)
- 100行Java代码构建一个线程池。 (40次浏览)
- JAVA基础知识:JAVA变量类型之间的相互转换 (33次浏览)
- 什么是面向接口编程 (29次浏览)
- 动态java代码的使用方法 (28次浏览)
- 程序员必读:对JAVA语言的十个常见误解 (26次浏览)



