import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.ole.win32.COM;
import org.eclipse.swt.internal.ole.win32.DISPPARAMS;
import org.eclipse.swt.internal.ole.win32.EXCEPINFO;
import org.eclipse.swt.internal.ole.win32.GUID;
import org.eclipse.swt.internal.ole.win32.IDispatch;
import org.eclipse.swt.internal.ole.win32.ITypeInfo;
import org.eclipse.swt.internal.ole.win32.IUnknown;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.Variant;
/*
* Created on 2006-7-11
*
*
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author hcw
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
public class CComObject {
private GUID guid = new GUID();
//private GUID IID = new GUID();
private IDispatch Autoface = null;
private ITypeInfo TypeInfo = null;
private String FMachineName = null;
private void CreateComObject() throws Exception{
dispose();
int[] ppv = new int[1];
int ret = COM.CoCreateInstance(guid, 0,
COM.CLSCTX_INPROC_SERVER | COM.CLSCTX_LOCAL_SERVER,
COM.IIDIUnknown, ppv);
if(ret!=COM.S_OK)
OLE.error(ret);
//throw new Exception("對象創建失?。?);
IUnknown objIUnknown = new IUnknown(ppv[0]);
ppv = new int[1];
ret = objIUnknown.QueryInterface(COM.IIDIDispatch, ppv);
objIUnknown.Release();
if(ret!=COM.S_OK)
OLE.error(ret);
//throw new Exception("對象不支持Dispatch!");
Autoface = new IDispatch(ppv[0]);
ppv = new int[1];
ret = Autoface.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, ppv);
if (ret == OLE.S_OK) {
TypeInfo = new ITypeInfo(ppv[0]);
TypeInfo.AddRef();
}
}
private int getIDsOfNames(String name){
int[] rgdispid = new int[1];
String[] names = new String[]{name};
int ret = Autoface.GetIDsOfNames(guid, names, names.length, COM.LOCALE_USER_DEFAULT, rgdispid);
if (ret != COM.S_OK) return -1;
return rgdispid[0];
}
private void getVariantData(Variant aVar, int pData){
if (pData == 0) OLE.error(OLE.ERROR_OUT_OF_MEMORY);
COM.VariantInit(pData);
if ((aVar.getType() & COM.VT_BYREF) == COM.VT_BYREF) {
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new int[]{aVar.getByRef()}, 4);
return;
}
switch (aVar.getType()) {
case COM.VT_EMPTY :
break;
case COM.VT_BOOL :
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new int[]{(aVar.getBoolean()) ? COM.VARIANT_TRUE : COM.VARIANT_FALSE}, 2);
break;
case COM.VT_R4 :
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new float[]{aVar.getFloat()}, 4);
break;
case COM.VT_I4 :
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new int[]{aVar.getInt()}, 4);
break;
case COM.VT_DISPATCH :
aVar.getDispatch().AddRef();
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new int[]{aVar.getDispatch().getAddress()}, 4);
break;
case COM.VT_UNKNOWN :
aVar.getUnknown().AddRef();
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new int[]{aVar.getUnknown().getAddress()}, 4);
break;
case COM.VT_I2 :
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
COM.MoveMemory(pData + 8, new short[]{aVar.getShort()}, 2);
break;
case COM.VT_BSTR :
COM.MoveMemory(pData, new short[] {aVar.getType()}, 2);
char[] data = (aVar.getString()+"\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pData + 8, new int[] {ptr}, 4);
break;
default :
OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
}
}
private Variant setVariantData(int pData){
if (pData == 0) OLE.error(OLE.ERROR_INVALID_ARGUMENT);
Variant ret = null;
short[] dataType = new short[1];
COM.MoveMemory(dataType, pData, 2);
int type = dataType[0];
if ((type & COM.VT_BYREF) == COM.VT_BYREF) {
int[] newByRefPtr = new int[1];
OS.MoveMemory(newByRefPtr, pData + 8, 4);
return new Variant(newByRefPtr[0], COM.VT_BYREF);
}
switch (type) {
case COM.VT_EMPTY :
break;
case COM.VT_BOOL :
short[] newBooleanData = new short[1];
COM.MoveMemory(newBooleanData, pData + 8, 2);
ret = new Variant(newBooleanData[0]!=0);
break;
case COM.VT_R4 :
float[] newFloatData = new float[1];
COM.MoveMemory(newFloatData, pData + 8, 4);
ret = new Variant(newFloatData[0]);
break;
case COM.VT_I4 :
int[] newIntData = new int[1];
OS.MoveMemory(newIntData, pData + 8, 4);
ret = new Variant(newIntData[0]);
break;
case COM.VT_DISPATCH : {
int[] ppvObject = new int[1];
OS.MoveMemory(ppvObject, pData + 8, 4);
if (ppvObject[0] == 0) {
type = COM.VT_EMPTY;
break;
}
ret = new Variant(new IDispatch(ppvObject[0]));
break;
}
case COM.VT_UNKNOWN : {
int[] ppvObject = new int[1];
OS.MoveMemory(ppvObject, pData + 8, 4);
if (ppvObject[0] == 0) {
type = COM.VT_EMPTY;
break;
}
ret = new Variant(new IUnknown(ppvObject[0]));
break;
}
case COM.VT_I2 :
short[] newShortData = new short[1];
COM.MoveMemory(newShortData, pData + 8, 2);
ret = new Variant(newShortData[0]);
break;
case COM.VT_BSTR :
// get the address of the memory in which the string resides
int[] hMem = new int[1];
OS.MoveMemory(hMem, pData + 8, 4);
if (hMem[0] == 0) {
type = COM.VT_EMPTY;
break;
}
int size = COM.SysStringByteLen(hMem[0]);
if (size > 0){
char[] buffer = new char[(size + 1) /2]; // add one to avoid rounding errors
COM.MoveMemory(buffer, hMem[0], size);
ret = new Variant(new String(buffer));
} else {
ret = new Variant(""); //$NON-NLS-1$
}
break;
default :
int newPData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof);
if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_R4) == COM.S_OK) {
ret = setVariantData(newPData);
} else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_I4) == COM.S_OK) {
setVariantData(newPData);
} else if (COM.VariantChangeType(newPData, pData, (short) 0, COM.VT_BSTR) == COM.S_OK) {
ret = setVariantData(newPData);
}
COM.VariantClear(newPData);
OS.GlobalFree(newPData);
break;
}
return ret;
}
private int invoke(int dispIdMember, int wFlags, Variant[] rgvarg, int[] rgdispidNamedArgs, Variant[] pVarResult) {
if (Autoface == null) return COM.E_FAIL;
DISPPARAMS pDispParams = new DISPPARAMS();
if (rgvarg != null && rgvarg.length > 0) {
pDispParams.cArgs = rgvarg.length;
pDispParams.rgvarg = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, Variant.sizeof * rgvarg.length);
int offset = 0;
for (int i = rgvarg.length - 1; i >= 0 ; i--) {
getVariantData(rgvarg[i], pDispParams.rgvarg + offset);
offset += Variant.sizeof;
}
}
if (rgdispidNamedArgs != null && rgdispidNamedArgs.length > 0) {
pDispParams.cNamedArgs = rgdispidNamedArgs.length;
pDispParams.rgdispidNamedArgs = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, 4 * rgdispidNamedArgs.length);
int offset = 0;
for (int i = rgdispidNamedArgs.length; i > 0; i--) {
COM.MoveMemory(pDispParams.rgdispidNamedArgs + offset, new int[] {rgdispidNamedArgs[i-1]}, 4);
offset += 4;
}
}
EXCEPINFO excepInfo = new EXCEPINFO();
int[] pArgErr = new int[1];
int pVarResultAddress = 0;
if (pVarResult != null)
pVarResultAddress = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof);
int ret = Autoface.Invoke(dispIdMember, new GUID(), COM.LOCALE_USER_DEFAULT, wFlags, pDispParams, pVarResultAddress, excepInfo, pArgErr);
if(ret!=COM.S_OK)
return ret;
if (pVarResultAddress != 0){
pVarResult[0] = setVariantData(pVarResultAddress);
COM.VariantClear(pVarResultAddress);
OS.GlobalFree(pVarResultAddress);
}
if (pDispParams.rgdispidNamedArgs != 0){
OS.GlobalFree(pDispParams.rgdispidNamedArgs);
}
if (pDispParams.rgvarg != 0) {
int offset = 0;
for (int i = 0, length = rgvarg.length; i < length; i++){
COM.VariantClear(pDispParams.rgvarg + offset);
offset += Variant.sizeof;
}
OS.GlobalFree(pDispParams.rgvarg);
}
return ret;
}
/**
* 創建空對象在使用需調用CreateComObject或CreateComObjectProgID創建COM對象。
*
*/
public CComObject(){
}
/**
* 使用CLSID創建COM對象,建構后可以調用COM對象方法或屬性。
* @param sCLSID COM對象CLSID
* @throws Exception
*/
public CComObject(String sCLSID) throws Exception{
COM.IIDFromString(sCLSID.toCharArray(), guid);
CreateComObject();
}
/**
* 使用現有自動化對象接口創建COM對象。
* @param prgDispatch
*/
public CComObject(IDispatch prgDispatch){
Autoface = prgDispatch;
Autoface.AddRef();
}
/**
* 使用CLSID創建COM對象??捎糜趧摻ㄐ碌膶ο螅ㄔ袑ο髮⑨尫牛?br />
* @param sCLSID
* @return
* @throws Exception
*/
public IDispatch CreateComObject(String sCLSID) throws Exception{
COM.IIDFromString(sCLSID.toCharArray(), guid);
CreateComObject();
return Autoface;
}
/**
* 創建遠程COM對象(未實現)。
* @param MachineName
* @param sCLSID
* @return
*/
public IDispatch CreateRemoteComObject(String MachineName, String sCLSID){
COM.IIDFromString(sCLSID.toCharArray(), guid);
return Autoface;
}
/**
* 使用ProgID創建COM對象。
* @param ProgID
* @return
* @throws Exception
*/
public IDispatch CreateComObjectProgID(String ProgID) throws Exception{
COM.CLSIDFromProgID(ProgID.toCharArray(), guid);
CreateComObject();
return Autoface;
}
/**
* 調用COM對象方法,有返回值(可變參數暫不支持)。
* @param FunctionName
* @param rgvarg
* @return
* @throws Exception
*/
public Variant CallFunction(String FunctionName, Variant[] rgvarg) throws Exception{
if(Autoface==null)
throw new Exception("對象為空");
int rgdispid = getIDsOfNames(FunctionName);
if(rgdispid==-1)
throw new Exception("方法不支持!");
Variant[] pVarResult = new Variant[1];
int ret = invoke(rgdispid, COM.DISPATCH_METHOD, rgvarg, null, pVarResult);
if(ret!=COM.S_OK)
OLE.error(ret);
//throw new Exception("方法調用失??!");
return pVarResult[0];
}
/**
* 調用COM對象方法,無參數和返回值。
* @param FunctionName
* @throws Exception
*/
public void CallFunction(String FunctionName) throws Exception{
CallFunction(FunctionName, new Variant[]{});
}
/**
* 獲取COM對象屬性值。
* @param PropertyName
* @param rgvarg
* @return
* @throws Exception
*/
public Variant getProperty(String PropertyName, Variant[] rgvarg) throws Exception{
if(Autoface==null)
throw new Exception("對象為空");
int rgdispid = getIDsOfNames(PropertyName);
if(rgdispid==-1)
throw new Exception("屬性不支持!");
Variant[] pVarResult = new Variant[1];
int ret = invoke(rgdispid, COM.DISPATCH_PROPERTYGET, rgvarg, null, pVarResult);
if(ret!=COM.S_OK)
OLE.error(ret);
//throw new Exception("屬性獲取失敗");
return pVarResult[0];
}
/**
* 給COM對象屬性賦值。
* @param PropertyName
* @param rgvarg
* @throws Exception
*/
public void setProperty(String PropertyName, Variant[] rgvarg) throws Exception{
if(Autoface==null)
throw new Exception("對象為空");
int rgdispid = getIDsOfNames(PropertyName);
if(rgdispid==-1)
throw new Exception("屬性不支持!");
int[] rgdispidNamedArgs = new int[] {COM.DISPID_PROPERTYPUT};
int dwFlags = COM.DISPATCH_PROPERTYPUT;
for (int i = 0; i < rgvarg.length; i++) {
if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF)
dwFlags = COM.DISPATCH_PROPERTYPUTREF;
}
Variant[] pVarResult = new Variant[1];
int ret = invoke(rgdispid, dwFlags, rgvarg, rgdispidNamedArgs, pVarResult);
if(ret != COM.S_OK)
OLE.error(ret);
//throw new Exception("屬性設置失??!");
}
/**
* 釋放COM對象的連接。在對象不用的時候需調用此函數,以便及時釋放對象。
*
*/
public void dispose(){
if(Autoface!=null)
Autoface.Release();
Autoface = null;
if(TypeInfo!=null)
TypeInfo.Release();
TypeInfo = null;
}
}
產品中要用到在Rcp程序中操作Excel。在網上goole了一下,發現一篇文章還不錯,測試了一下通過。
Integrate Eclipse RCP with Microsoft Applications - Tutorial
Lars Vogel
<webmaster@vogella.de>
Version 0.5
Copyright © 2007 Lars Vogel
01.11.2007
Abstract
The Eclipse Rich Client Platform (RCP) is using the SWT GUI framework. SWT does allow to integrated Microsoft application via OLE (Object Linking and Embedding). This article will demonstrate how SWT can be used within an Eclipse RCP application to integrate / use Microsoft applications. Microsoft Outlook and Microsoft Excel are used as examples
This article assumes that you are already familiar with using the Eclipse IDE and with developing simple Eclipse RCP applications.
--------------------------------------------------------------------------------
Table of Contents
1. Microsoft Object Linking and Embedding
1.1. Overview
2. Microsoft Integration - Sending an email via outlook
2.1. Create Project
2.2. Add action
2.3. Program the action
3. Microsoft Integration - Use Excel in your application.
3.1. Create Project
3.2. Change View code
4. Links and Literature
1. Microsoft Object Linking and Embedding
1.1. Overview
Windows applications use OLE (Object Linking and Embedding) to allow applications to control other application objects. The following will show how to do this using a few examples.
2. Microsoft Integration - Sending an email via outlook
This example assumes you running an MS operating system and that you have a version of Outlook installed.
2.1. Create Project
Create a new project "OutlookTest" (see here how to create a new RCP project). Use the "Hello RCP " as a template.
2.2. Add action
Using extensions add action "sendEmail" (see here how to add an action). The class of this action should be "outlooktest.SendEmail". Run the application. The result should look like the following.
2.3. Program the action
Lets program the action. The following coding will create and open the email for the user. It also assumes that you have a file c:\temp\test.txt which will be attached to the email.
package outlooktest;
import java.io.File;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
public class SendEmail implements IWorkbenchWindowActionDelegate {
private Shell shell;
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public void init(IWorkbenchWindow window) {
shell = window.getShell();
}
@Override
public void run(IAction action) {
Display display = Display.getCurrent();
Shell shell = new Shell(display);
OleFrame frame = new OleFrame(shell, SWT.NONE);
// This should start outlook if it is not running yet
OleClientSite site = new OleClientSite(frame, SWT.NONE, "OVCtl.OVCtl");
site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
// Now get the outlook application
OleClientSite site2 = new OleClientSite(frame, SWT.NONE,
"Outlook.Application");
OleAutomation outlook = new OleAutomation(site2);
//
OleAutomation mail = invoke(outlook, "CreateItem", 0 /* Mail item */)
.getAutomation();
setProperty(mail, "To", "test@gmail.com"); /* Empty but could also be predefined */
setProperty(mail, "Bcc", "test@gmail.com"); /* Empty but could also be predefined */
setProperty(mail, "BodyFormat", 2 /* HTML */);
setProperty(mail, "Subject", "Top News for you");
setProperty(mail, "HtmlBody",
"<html>Hello<p>, please find some infos here.</html>");
File file = new File("c:/temp/test.txt");
if (file.exists()) {
OleAutomation attachments = getProperty(mail, "Attachments");
invoke(attachments, "Add", "c:/temp/test.txt");
} else {
MessageDialog
.openInformation(shell, "Info",
"Attachment File c:/temp/test.txt not found; will send email with attachment");
}
invoke(mail, "Display" /* or "Send" */);
}
private static OleAutomation getProperty(OleAutomation auto, String name) {
Variant varResult = auto.getProperty(property(auto, name));
if (varResult != null && varResult.getType() != OLE.VT_EMPTY) {
OleAutomation result = varResult.getAutomation();
varResult.dispose();
return result;
}
return null;
}
private static Variant invoke(OleAutomation auto, String command,
String value) {
return auto.invoke(property(auto, command),
new Variant[] { new Variant(value) });
}
@Override
public void selectionChanged(IAction action, ISelection selection) {
// TODO Auto-generated method stub
}
private static Variant invoke(OleAutomation auto, String command) {
return auto.invoke(property(auto, command));
}
private static Variant invoke(OleAutomation auto, String command, int value) {
return auto.invoke(property(auto, command),
new Variant[] { new Variant(value) });
}
private static boolean setProperty(OleAutomation auto, String name,
String value) {
return auto.setProperty(property(auto, name), new Variant(value));
}
private static boolean setProperty(OleAutomation auto, String name,
int value) {
return auto.setProperty(property(auto, name), new Variant(value));
}
private static int property(OleAutomation auto, String name) {
return auto.getIDsOfNames(new String[] { name })[0];
}
}
If you now start the application and press the button an email should be prepared and shown to the user.
3. Microsoft Integration - Use Excel in your application.
This example assume that you running on Microsoft and that you have a version of Microsoft Excel installed.
3.1. Create Project
Create a new project "ExcelTest" (see here how to create a new RCP project). Use the "RCP with a view" as a template. Run it and see that is working.
3.2. Change View code
Select View.java and replace the coding with the following.
package exceltest;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
public class View extends ViewPart {
public static final String ID = "ExcelTest.view";
private OleClientSite site;
public View() {
}
@Override
public void createPartControl(Composite parent) {
try {
OleFrame frame = new OleFrame(parent, SWT.NONE);
site = new OleClientSite(frame, SWT.NONE, "Excel.Sheet");
} catch (SWTError e) {
System.out.println("Unable to open activeX control");
return;
}
}
@Override
public void setFocus() {
// Have to set the focus see https://bugs.eclipse.org/bugs/show_bug.cgi?id=207688
site.setFocus();
}
}
Start your application and excel should be displayed.
4. Links and Literature
http://www.eclipse.org/ Eclipse Website
http://www.vogella.de/articles/Eclipse/article.html Using Eclipse as IDE - Tutorial
http://www.vogella.de/articles/RichClientPlatform/article.html Eclipse Rich Client Platform - Tutorial
http://www.vogella.de/articles/EclipseCodeAccess/article.html A guide to access the Eclipse Sources