大家知道,Java调用DLL有个特别的地方,就是DLL的输出函数需要特别的名字:
JNIEXPORT void JNICALL Java_类名_函数名
(JNIEnv *, jclass, 其他参数)
{
}
总是要求DLL函数有 Java_ 开头,调用USER32.DLL中的 GetWindowText 那要怎么做呢?直接调用是不可能的了,下面介绍通过桥接器,实现Java调用任何API,或者类似API的任何DLL的方法。
先看运行效果:
这是把 JFrame 通过 API 中的 SetWindowRgn 函数改变成圆角窗口。
这个桥接器的准备工作可以参考VC写的源代码。这里主要介绍的是Java部分的代码:
1 API 部分
public
class
MyAPI{
public
static
dobject4j os_api
=
new
dobject4j(
"
OSAPI
"
);
public
static
dValue GetWindowText(dValue hWnd){
dobject4j param
=
new
dobject4j(
"
ApiParams
"
);
param.invoke(
"
AppendHandlePointer
"
,hWnd);
param.invoke(
"
AllocAsciiStringBuffer
"
,
new
dValue(
260
));
param.invoke(
"
AppendUnsignedLong
"
,
new
dValue(
260
));
os_api.invoke(
"
CallOSAPI
"
,
new
dValue(
"
USER32.DLL
"
),
new
dValue(
"
GetWindowTextA
"
),
new
dValue(param));
return
param.invoke(
"
ReadAsciiString
"
,
new
dValue(
4
));
}
public
static
dValue SetWindowRgn(dValue hWnd,dValue hRgn,dValue bRedraw){
dobject4j param=
new
dobject4j("ApiParams");
param.invoke("AppendHandlePointer",hWnd);
param.invoke("AppendHandlePointer",hRgn);
param.invoke("AppendUnsignedLong",bRedraw);
dValue ret=os_api.invoke("CallOSAPI",
new
dValue("USER32.DLL"),
new
dValue("SetWindowRgn"),
new
dValue(param));
param=null;
return
ret;
}
//其他API的代码可以下载后看看。下载的.dwidget文件是zip格式的,改名.zip解压后即可。
}
2 应用实现部分
public
void
StartupMe(){
frame
=
new
JFrame(
"
Swing Application
"
);
................
createComponents(frame);
frame.setLocation(
300
,
220
);
frame.setSize(
300
,
130
);
String title
=
"
round JFrame
"
;
frame.setTitle(title);
frame.setVisible(
true
);
................
dValue desktop
=
MyAPI.GetDesktopWindow();
dValue h
=
MyAPI.FindWindowEx(desktop,
null
,
new
dValue(
"
javax.swing.JFrame
"
),
new
dValue(title));
dValue hParentRgn
=
MyAPI.CreateRoundRectRgn(
new
dValue(
13
),
new
dValue(
3
),
new
dValue(
290
),
new
dValue(
120
),
new
dValue(
15
),
new
dValue(
15
));
MyAPI.SetWindowRgn(h,hParentRgn,
new
dValue(
true
));
MyAPI.DeleteObject(hParentRgn);
}
桥接器的2个重要的类分别是 OSAPI 和 ApiParams。OSAPI 负责API的调用实现,ApiParams 负责参数组织。OSAPI 的 CallOSAPI 方法 第一个参数是DLL文件名,像上述的USER32.DLL,第二个参数是方法的名字,要注意的是,Windows API 很多是区分 ANSI 和 Unicode ,就像我们熟悉的GetWindowText() 就分别有GetWindowTextA() 和GetWindowTextW() 两个对应于 ANSI 和 Unicode ,第三个参数是API的参数。ApiParams 的方法有很多,都是支持各种类型参数用的,例如 AppendUnsignedLong() 方法支持 DWORD 类型,AppendHandlePointer() 支持各种句柄。ApiParams还可以嵌套,用 AppendStructurePointer() 方法支持嵌套结构体指针,用 AppendStructure() 方法支持嵌套结构体,等等。
点击这里仅下载本例代码,下载后的.dwidget改名.zip文件解压即可
点击这里下载整个运行程序
点击这里下载这个IE内核浏览器源代码(不含msscript.ocx调用机制部分源代码,这部分是DLL形式提供的)