SWT中调用Automation的方式 这篇文章中我们介绍了SWT中通过Automation访问IE的方式,但是只是简单的URL导航,没有自动填表单、自动提交等功能。我们对其进行了升级,采用了新的操作方式,充分利用了SWT对OLE的支持,裁减掉大量代码。现在可以实现自动填表单、自动提交等功能。不过暂时还无法响应IE的事件。
核心代码如下:
package test;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.internal.ole.win32.COM;
import org.eclipse.swt.internal.ole.win32.GUID;
import org.eclipse.swt.internal.ole.win32.IUnknown;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.widgets.Composite;
/**
*
* @author 杨中科
*
*/
public class AutomationClientSite extends OleClientSite
{
public AutomationClientSite(Composite parent, int style, String progId)
{
super(parent, style);
try
{
appClsid = getClassID(progId);
if (appClsid == null)
OLE.error(OLE.ERROR_INVALID_CLASSID);
//使用CoCreateInstance创建一个进程外Automation服务器
int[] address = new int[1];
int result = COM.CoCreateInstance(getClassID(progId), 0,
COM.CLSCTX_INPROC_SERVER | COM.CLSCTX_LOCAL_SERVER,
COM.IIDIUnknown, address);
if (result != COM.S_OK)
OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
objIUnknown = new IUnknown(address[0]);
} catch (SWTException e)
{
dispose();
disposeCOMInterfaces();
throw e;
}
}
protected GUID getClassID(String progId)
{
GUID guid = new GUID();
// create a null terminated array of char
char[] buffer = null;
if (progId != null)
{
int count = progId.length();
buffer = new char[count + 1];
progId.getChars(0, count, buffer, 0);
}
if (COM.CLSIDFromProgID(buffer, guid) != COM.S_OK)
{
int result = COM.CLSIDFromString(buffer, guid);
if (result != COM.S_OK)
OLE.error(result);
}
return guid;
}
}
public class OleUtils
{
public static int getIdOfName(OleAutomation auto, String name)
{
int[] ret = auto.getIDsOfNames(new String[]{name});
return ret[0];
}
public static void setProperty(OleAutomation auto, String name,Variant value)
{
int id = getIdOfName(auto, name);
auto.setProperty(id, new Variant[]{value});
}
public static Variant getProperty(OleAutomation auto, String name)
{
int id = getIdOfName(auto, name);
return auto.getProperty(id);
}
public static Variant invoke(OleAutomation auto, String name)
{
return invoke(auto,name,new Variant[0]);
}
public static Variant invoke(OleAutomation auto, String name,Variant... params)
{
int id = getIdOfName(auto, name);
return auto.invoke(id,params);
}
}
package test;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.Variant;
/**
*
* @author 杨中科
*
*/
public class HtmlElement
{
private OleAutomation auto;
public HtmlElement(OleAutomation auto)
{
this.auto = auto;
}
protected OleAutomation getOleAutomation()
{
return auto;
}
public void setProperty(String name, Variant value)
{
OleUtils.setProperty(auto, name, value);
}
public Variant getPropertyAsVariant(String name)
{
Variant value = OleUtils.getProperty(auto, name);
return value;
}
public void setProperty(String name, int value)
{
OleUtils.setProperty(auto, name, new Variant(value));
}
public int getPropertyAsInt(String name)
{
Variant value = OleUtils.getProperty(auto, name);
return value.getInt();
}
public void setProperty(String name, boolean value)
{
OleUtils.setProperty(auto, name, new Variant(value));
}
public boolean getPropertyAsBool(String name)
{
Variant value = OleUtils.getProperty(auto, name);
return value.getBoolean();
}
public void setProperty(String name, String value)
{
OleUtils.setProperty(auto, name, new Variant(value));
}
public String getPropertyAsString(String name)
{
Variant value = OleUtils.getProperty(auto, name);
return value.getString();
}
public HtmlElement getPropertyAsHtmlElement(String name)
{
Variant value = OleUtils.getProperty(auto, name);
return new HtmlElement(value.getAutomation());
}
public Variant invoke(String name,Variant... params)
{
return OleUtils.invoke(auto, name,params);
}
public int invoke_Int(String name,Variant... params)
{
return invoke(name,params).getInt();
}
public boolean invoke_Bool(String name,Variant... params)
{
return invoke(name,params).getBoolean();
}
public String invoke_String(String name,Variant... params)
{
return invoke(name,params).getString();
}
public HtmlElement invoke_HtmlElement(String name,Variant... params)
{
return new HtmlElement(invoke(name,params).getAutomation());
}
}
package test;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.Variant;
/**
* 更多方法参考MSDN“InternetExplorer Object”文档
*
* @author 杨中科
*
*/
public class IEAutomation extends HtmlElement
{
public IEAutomation(OleClientSite clientSite)
{
super(new OleAutomation(clientSite));
}
public void setVisible(boolean value)
{
setProperty("Visible", value);
}
public boolean isVisible()
{
return getPropertyAsBool("Visible");
}
public void setMenuBar(boolean value)
{
setProperty("MenuBar", value);
}
public boolean isMenuBar()
{
return getPropertyAsBool("MenuBar");
}
public void setStatusBar(boolean value)
{
setProperty("StatusBar", value);
}
public boolean isStatusBar()
{
return getPropertyAsBool("StatusBar");
}
public void setToolBar(boolean value)
{
setProperty("ToolBar", value);
}
public boolean isToolBar()
{
return getPropertyAsBool("ToolBar");
}
public int getHWND()
{
return getPropertyAsInt("HWND");
}
public String getReadyState()
{
return getPropertyAsString("ReadyState");
}
public String getLocationURL()
{
return getPropertyAsString("LocationURL");
}
public boolean getBusy()
{
return getPropertyAsBool("Busy");
}
public void navigate(String url)
{
invoke("Navigate", new Variant(url));
}
public HtmlElement getDocument()
{
return getPropertyAsHtmlElement("Document");
}
public String getInnerHtml()
{
HtmlElement document = getPropertyAsHtmlElement("Document");
HtmlElement body = document.getPropertyAsHtmlElement("body");
return body.getPropertyAsString("innerHtml");
}
public HtmlElement getElementById(String id)
{
HtmlElement document = getDocument();
return document.invoke_HtmlElement("getElementById", new Variant(id));
}
public void quit()
{
invoke("Quit");
}
}
使用范例:
protected void 自动填表()
{
//"kw"为关键字输入框
HtmlElement txtKW = ie.getElementById("kw");
//自动填表
txtKW.setProperty("value", "杨中科");
HtmlElement btnSB = ie.getElementById("sb");
//自动点击【百度一下】按钮自动提交查询
btnSB.invoke("click");
}
private void automation() throws Exception
{
OleFrame frame = new OleFrame(composite, SWT.NONE);
AutomationClientSite client =
new AutomationClientSite(frame,SWT.NONE,"InternetExplorer.Application");
ie = new IEAutomation(client);
ie.setVisible(true);
ie.setMenuBar(false);
ie.setToolBar(false);
ie.setStatusBar(false);
int hwnd = ie.getHWND();
OS.SetParent(hwnd, composite.handle);
// 窗口最大化
OS.SendMessage(hwnd, OS.WM_SYSCOMMAND, OS.SC_MAXIMIZE, 0);
OS.SendMessage(hwnd, OS.WM_ACTIVATE, 0, 0);
ie.navigate("http://www.baidu.com");
//等待加载完毕,正确的方式应该是在网页onComplete的时候继续执行,但是没弄明白OLE 的EventSink机制怎么搞到SWT中来
//所以先凑合着Sleep循环检测getBusy()的值,当不busy的时候再进行后续处理
while(ie.getBusy())
{
Thread.sleep(10);
}
msgBox(ie.getInnerHtml());
//"sb"为【百度一下】这个按钮的id
HtmlElement btnSB = ie.getElementById("sb");
//取value属性
String txt = btnSB.getPropertyAsString("value");
msgBox("按钮上的文字:"+txt);
msgBox("网址:"+ie.getLocationURL());
composite.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e)
{
//必须手动指定退出,否则会报异常
ie.quit();
}
});
}