sourceforge 1386454 now supporting return values in event handlers. also added visio example of this
This commit is contained in:
@@ -30,6 +30,11 @@
|
|||||||
has been added to the DispatchEvents constructors that lets a user provide
|
has been added to the DispatchEvents constructors that lets a user provide
|
||||||
the location of the OLB or EXE that contains the information required to
|
the location of the OLB or EXE that contains the information required to
|
||||||
retrieve the events.
|
retrieve the events.
|
||||||
|
<li>Event handlers can now return a value to calling MS Windows program.
|
||||||
|
The event handlers must return an objec of type Variant if they wish to return
|
||||||
|
a value. All
|
||||||
|
previous event handlers still work with a void return. (This change should be
|
||||||
|
backwards compatible)
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@@ -53,7 +58,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="100%" colspan="2"><b>Patches</b></td>
|
<td width="100%" colspan="2"><b>Patches</b></td>
|
||||||
</tr>1394001
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="13%">1386454</td>
|
||||||
|
<td width="87%">Return values from event callbacks (pre4)</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="13%">1394001</td>
|
<td width="13%">1394001</td>
|
||||||
<td width="87%">Missing variable initialization (pre3)</td>
|
<td width="87%">Missing variable initialization (pre3)</td>
|
||||||
|
|||||||
@@ -42,9 +42,15 @@ EventProxy::EventProxy(JNIEnv *env,
|
|||||||
env->GetJavaVM(&jvm);
|
env->GetJavaVM(&jvm);
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
AddRef();
|
AddRef();
|
||||||
|
Connect(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventProxy::Connect(JNIEnv *env) {
|
||||||
HRESULT hr = pCP->Advise(this, &dwEventCookie);
|
HRESULT hr = pCP->Advise(this, &dwEventCookie);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
|
connected = 1;
|
||||||
} else {
|
} else {
|
||||||
|
connected = 0;
|
||||||
ThrowComFail(env, "Advise failed", hr);
|
ThrowComFail(env, "Advise failed", hr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,8 +58,8 @@ EventProxy::EventProxy(JNIEnv *env,
|
|||||||
// unhook myself up as a listener and get rid of delegate
|
// unhook myself up as a listener and get rid of delegate
|
||||||
EventProxy::~EventProxy()
|
EventProxy::~EventProxy()
|
||||||
{
|
{
|
||||||
pCP->Unadvise(dwEventCookie);
|
|
||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
|
Disconnect();
|
||||||
// attach to the current running thread
|
// attach to the current running thread
|
||||||
#ifdef JNI_VERSION_1_2
|
#ifdef JNI_VERSION_1_2
|
||||||
printf("using version 1.2 API\n");
|
printf("using version 1.2 API\n");
|
||||||
@@ -74,6 +80,12 @@ EventProxy::~EventProxy()
|
|||||||
jvm->DetachCurrentThread();
|
jvm->DetachCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventProxy::Disconnect() {
|
||||||
|
if (connected) {
|
||||||
|
pCP->Unadvise(dwEventCookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// I only support the eventIID interface which was passed in
|
// I only support the eventIID interface which was passed in
|
||||||
// by the DispatchEvent wrapper who looked it up as the
|
// by the DispatchEvent wrapper who looked it up as the
|
||||||
// source object's default source interface
|
// source object's default source interface
|
||||||
@@ -106,6 +118,7 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
|
|||||||
|
|
||||||
const char *eventMethodName = NULL; //Sourceforge report 1394001
|
const char *eventMethodName = NULL; //Sourceforge report 1394001
|
||||||
JNIEnv *env = NULL;
|
JNIEnv *env = NULL;
|
||||||
|
jobject retObj;
|
||||||
|
|
||||||
// map dispID to jmethodID
|
// map dispID to jmethodID
|
||||||
for(int i=0;i<MethNum;i++)
|
for(int i=0;i<MethNum;i++)
|
||||||
@@ -135,13 +148,12 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
|
|||||||
// find the class of the InvocationHandler
|
// find the class of the InvocationHandler
|
||||||
jclass javaSinkClass = env->GetObjectClass(javaSinkObj);
|
jclass javaSinkClass = env->GetObjectClass(javaSinkObj);
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
jmethodID invokeMethod = env->GetMethodID(javaSinkClass, "invoke",
|
jmethodID invokeMethod;
|
||||||
"(Ljava/lang/String;[Lcom/jacob/com/Variant;)V");
|
invokeMethod = env->GetMethodID(javaSinkClass, "invoke", "(Ljava/lang/String;[Lcom/jacob/com/Variant;)Lcom/jacob/com/Variant;");
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
jstring eventMethodNameAsString = env->NewStringUTF(eventMethodName);
|
jstring eventMethodNameAsString = env->NewStringUTF(eventMethodName);
|
||||||
// now do what we need for the variant
|
// now do what we need for the variant
|
||||||
jmethodID getVariantMethod =
|
jmethodID getVariantMethod = env->GetMethodID(javaSinkClass, "getVariant", "()Lcom/jacob/com/Variant;");
|
||||||
env->GetMethodID(javaSinkClass, "getVariant", "()Lcom/jacob/com/Variant;");
|
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
jobject aVariantObj = env->CallObjectMethod(javaSinkObj, getVariantMethod);
|
jobject aVariantObj = env->CallObjectMethod(javaSinkObj, getVariantMethod);
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
@@ -169,8 +181,14 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
|
|||||||
env->DeleteLocalRef(arg);
|
env->DeleteLocalRef(arg);
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
}
|
}
|
||||||
env->CallVoidMethod(javaSinkObj, invokeMethod,
|
// Set up the return value
|
||||||
eventMethodNameAsString, varr);
|
jobject ret;
|
||||||
|
|
||||||
|
ret = env->CallObjectMethod(javaSinkObj, invokeMethod,
|
||||||
|
eventMethodNameAsString, varr);
|
||||||
|
if (!env->ExceptionOccurred() && ret != NULL) {
|
||||||
|
VariantCopy(pVarResult, extractVariant(env,ret));
|
||||||
|
}
|
||||||
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
|
||||||
// don't need the first variant we created to get the class
|
// don't need the first variant we created to get the class
|
||||||
env->DeleteLocalRef(aVariantObj);
|
env->DeleteLocalRef(aVariantObj);
|
||||||
@@ -182,6 +200,19 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
|
|||||||
jobject arg = env->GetObjectArrayElement(varr, j);
|
jobject arg = env->GetObjectArrayElement(varr, j);
|
||||||
VARIANT *java = extractVariant(env, arg);
|
VARIANT *java = extractVariant(env, arg);
|
||||||
VARIANT *com = &pDispParams->rgvarg[i];
|
VARIANT *com = &pDispParams->rgvarg[i];
|
||||||
|
convertJavaVariant(java, com);
|
||||||
|
zeroVariant(env, arg);
|
||||||
|
env->DeleteLocalRef(arg);
|
||||||
|
}
|
||||||
|
// End code from Jiffie team that copies parameters back from java to COM
|
||||||
|
// detach from thread
|
||||||
|
jvm->DetachCurrentThread();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventProxy::convertJavaVariant(VARIANT *java, VARIANT *com) {
|
||||||
|
|
||||||
switch (com->vt)
|
switch (com->vt)
|
||||||
{
|
{
|
||||||
@@ -795,15 +826,6 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
zeroVariant(env, arg);
|
|
||||||
env->DeleteLocalRef(arg);
|
|
||||||
}
|
}
|
||||||
// End code from Jiffie team that copies parameters back from java to COM
|
|
||||||
|
|
||||||
// detach from thread
|
|
||||||
jvm->DetachCurrentThread();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
class EventProxy : public IDispatch
|
class EventProxy : public IDispatch
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
int connected;
|
||||||
LONG m_cRef; // a reference counter
|
LONG m_cRef; // a reference counter
|
||||||
CComPtr<IConnectionPoint> pCP; // the connection point
|
CComPtr<IConnectionPoint> pCP; // the connection point
|
||||||
DWORD dwEventCookie; // connection point cookie
|
DWORD dwEventCookie; // connection point cookie
|
||||||
@@ -47,6 +48,9 @@ private:
|
|||||||
CComBSTR *MethName; // Array of method names
|
CComBSTR *MethName; // Array of method names
|
||||||
DISPID *MethID; // Array of method ids, used to match invokations to method names
|
DISPID *MethID; // Array of method ids, used to match invokations to method names
|
||||||
JavaVM *jvm; // The java vm we are running
|
JavaVM *jvm; // The java vm we are running
|
||||||
|
void convertJavaVariant(VARIANT *java, VARIANT *com);
|
||||||
|
void Connect(JNIEnv *env);
|
||||||
|
void Disconnect();
|
||||||
public:
|
public:
|
||||||
// constuct with a global JNI ref to a sink object
|
// constuct with a global JNI ref to a sink object
|
||||||
// to which we will delegate event callbacks
|
// to which we will delegate event callbacks
|
||||||
@@ -62,7 +66,8 @@ public:
|
|||||||
// IUnknown methods
|
// IUnknown methods
|
||||||
STDMETHODIMP_(ULONG) AddRef(void)
|
STDMETHODIMP_(ULONG) AddRef(void)
|
||||||
{
|
{
|
||||||
return InterlockedIncrement(&m_cRef);
|
LONG res = InterlockedIncrement(&m_cRef);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) Release(void)
|
STDMETHODIMP_(ULONG) Release(void)
|
||||||
|
|||||||
85
samples/com/jacob/samples/visio/VisioApp.java
Normal file
85
samples/com/jacob/samples/visio/VisioApp.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package com.jacob.samples.visio;
|
||||||
|
|
||||||
|
import com.jacob.com.*;
|
||||||
|
import com.jacob.activeX.*;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
|
||||||
|
* @author miles@rowansoftware.net
|
||||||
|
*
|
||||||
|
* This class represents the visio app itself
|
||||||
|
*/
|
||||||
|
public class VisioApp extends ActiveXComponent {
|
||||||
|
|
||||||
|
|
||||||
|
public VisioApp() throws VisioException {
|
||||||
|
super("Visio.Application");
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates a DispatchEvents boject to register o as a listener
|
||||||
|
* @param o
|
||||||
|
*/
|
||||||
|
public void addEventListener(VisioEventListener o) {
|
||||||
|
DispatchEvents events = new DispatchEvents(this, o);
|
||||||
|
if (events == null){
|
||||||
|
System.out.println("You should never get null back when creating a DispatchEvents object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void open(File f) throws VisioException {
|
||||||
|
try {
|
||||||
|
ActiveXComponent documents = new ActiveXComponent(getProperty("Documents").toDispatch());
|
||||||
|
Variant[] args = new Variant[1];
|
||||||
|
args[0] = new Variant(f.getPath());
|
||||||
|
documents.invoke("Open",args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new VisioException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() throws VisioException {
|
||||||
|
try {
|
||||||
|
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch());
|
||||||
|
document.invoke("Save");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new VisioException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* terminates visio
|
||||||
|
*/
|
||||||
|
public void quit() {
|
||||||
|
System.out.println("Received quit()");
|
||||||
|
// there can't be any open documents for this to work
|
||||||
|
// you'll get a visio error if you don't close them
|
||||||
|
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch());
|
||||||
|
document.invoke("Close");
|
||||||
|
invoke("Quit");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void export(File f) throws VisioException {
|
||||||
|
try {
|
||||||
|
ActiveXComponent document = new ActiveXComponent(getProperty("ActivePage").toDispatch());
|
||||||
|
Variant[] args = new Variant[1];
|
||||||
|
args[0] = new Variant(f.getPath());
|
||||||
|
document.invoke("Export",args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new VisioException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisible(boolean b) throws VisioException {
|
||||||
|
try {
|
||||||
|
setProperty("Visible",new Variant(b));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new VisioException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
samples/com/jacob/samples/visio/VisioAppFacade.java
Normal file
120
samples/com/jacob/samples/visio/VisioAppFacade.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package com.jacob.samples.visio;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
|
||||||
|
* @author miles@rowansoftware.net
|
||||||
|
*
|
||||||
|
* This singleton isolates the demo app from the Visio instance object so that
|
||||||
|
* you can't try and send messages to a dead Visio instance after quit() has been
|
||||||
|
* called. Direct consumption of VisioApp would mean you could quit but would
|
||||||
|
* still have a handle to the no longer connected application proxy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class VisioAppFacade {
|
||||||
|
|
||||||
|
|
||||||
|
private VisioApp app;
|
||||||
|
private static VisioAppFacade instance;
|
||||||
|
|
||||||
|
public static final String IMAGE_EXT = ".jpg";
|
||||||
|
public static final String VISIO_EXT = ".vsd";
|
||||||
|
public static final int BUFFER_SIZE = 2048;
|
||||||
|
|
||||||
|
private VisioAppFacade() throws VisioException {
|
||||||
|
this.app = new VisioApp();
|
||||||
|
app.addEventListener(new VisioEventAdapter(app));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VisioAppFacade getInstance() throws VisioException {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new VisioAppFacade();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] createPreview(byte[] visioData) throws VisioException {
|
||||||
|
byte[] preview;
|
||||||
|
File tmpFile;
|
||||||
|
try {
|
||||||
|
tmpFile = getTempVisioFile();
|
||||||
|
OutputStream out = new FileOutputStream(tmpFile);
|
||||||
|
out.write(visioData);
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new VisioException(ioe);
|
||||||
|
}
|
||||||
|
preview = createPreview(tmpFile);
|
||||||
|
tmpFile.delete();
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] createPreview(File visioFile) throws VisioException {
|
||||||
|
try {
|
||||||
|
File imageFile;
|
||||||
|
imageFile = getTempImageFile();
|
||||||
|
app.open(visioFile);
|
||||||
|
app.export(imageFile);
|
||||||
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
|
FileInputStream fin = new FileInputStream(imageFile);
|
||||||
|
copy(fin, bout);
|
||||||
|
fin.close();
|
||||||
|
imageFile.delete();
|
||||||
|
bout.close();
|
||||||
|
return bout.toByteArray();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new VisioException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copy(InputStream in, OutputStream out) throws IOException {
|
||||||
|
byte[] buff = new byte[BUFFER_SIZE];
|
||||||
|
int read;
|
||||||
|
do {
|
||||||
|
read = in.read(buff);
|
||||||
|
if (read > 0) {
|
||||||
|
out.write(buff,0,read);
|
||||||
|
}
|
||||||
|
} while (read > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] createPreview(InputStream in) throws VisioException {
|
||||||
|
byte[] preview;
|
||||||
|
//byte[] buff = new byte[2048];
|
||||||
|
//int read = 0;
|
||||||
|
OutputStream out;
|
||||||
|
File tmpFile;
|
||||||
|
|
||||||
|
try {
|
||||||
|
tmpFile = getTempVisioFile();
|
||||||
|
out = new FileOutputStream(tmpFile);
|
||||||
|
copy(in, out);
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new VisioException(ioe);
|
||||||
|
}
|
||||||
|
|
||||||
|
preview = createPreview(tmpFile);
|
||||||
|
tmpFile.delete();
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void editDiagram(File f) throws VisioException {
|
||||||
|
app.open(f);
|
||||||
|
app.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getTempVisioFile() throws IOException {
|
||||||
|
return File.createTempFile("java",VISIO_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getTempImageFile() throws IOException {
|
||||||
|
return File.createTempFile("java",IMAGE_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void quit() {
|
||||||
|
app.quit();
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
181
samples/com/jacob/samples/visio/VisioDemo.java
Normal file
181
samples/com/jacob/samples/visio/VisioDemo.java
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
package com.jacob.samples.visio;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.filechooser.FileFilter;
|
||||||
|
|
||||||
|
import com.jacob.com.ComThread;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
|
||||||
|
* @author miles@rowansoftware.net
|
||||||
|
*
|
||||||
|
* This file contains the main() that runs the demo
|
||||||
|
*
|
||||||
|
* This can be run in Eclipse with options
|
||||||
|
* <pre>
|
||||||
|
* -Djava.library.path=d:/jacob/release -Dcom.jacob.autogc=false
|
||||||
|
* -Dcom.jacob.debug=false
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class VisioDemo extends JFrame implements ActionListener, WindowListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Totally dummy value to make Eclipse quit complaining
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
JButton chooseButton;
|
||||||
|
JButton openButton;
|
||||||
|
JPanel buttons;
|
||||||
|
|
||||||
|
ImageIcon theImage;
|
||||||
|
JLabel theLabel; // the icon on the page is actually this button's icon
|
||||||
|
|
||||||
|
File selectedFile;
|
||||||
|
/** everyone should get this through getVisio() */
|
||||||
|
private VisioAppFacade visioProxy = null;
|
||||||
|
|
||||||
|
// put this up here so it remembers where we were on the last choose
|
||||||
|
JFileChooser chooser = null;
|
||||||
|
|
||||||
|
|
||||||
|
public class VisioFileFilter extends FileFilter {
|
||||||
|
public boolean accept(File f) {
|
||||||
|
if (f.isDirectory()){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return (f.getName().toUpperCase().endsWith(".VSD"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return "Visio Drawings";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public VisioDemo() {
|
||||||
|
super("Visio in Swing POC");
|
||||||
|
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
buttons = new JPanel();
|
||||||
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
chooseButton = new JButton("Choose file to display");
|
||||||
|
openButton = new JButton("Open file chosen file in Visio");
|
||||||
|
chooseButton.addActionListener(this);
|
||||||
|
openButton.addActionListener(this);
|
||||||
|
buttons.add(chooseButton);
|
||||||
|
buttons.add(openButton);
|
||||||
|
getContentPane().add(buttons, BorderLayout.SOUTH);
|
||||||
|
theLabel = new JLabel("");
|
||||||
|
getContentPane().add(theLabel, BorderLayout.CENTER);
|
||||||
|
addWindowListener(this);
|
||||||
|
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
setSize(640,480);
|
||||||
|
this.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Exception {
|
||||||
|
SwingUtilities.invokeLater(new Runnable(){
|
||||||
|
public void run(){
|
||||||
|
ComThread.InitSTA();
|
||||||
|
VisioDemo poc = new VisioDemo();
|
||||||
|
ComThread.Release();
|
||||||
|
if (poc == null){
|
||||||
|
System.out.println("poc== null? That should never happen!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (e.getSource() == chooseButton) {
|
||||||
|
pickFile();
|
||||||
|
} else if (e.getSource() == openButton) {
|
||||||
|
try {
|
||||||
|
openFile();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Awesome!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pickFile() {
|
||||||
|
try {
|
||||||
|
chooser = new JFileChooser();
|
||||||
|
// comment this out if you want it to always go to myDocuments
|
||||||
|
chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||||
|
chooser.setFileFilter(new VisioFileFilter());
|
||||||
|
int returnVal = chooser.showOpenDialog(this);
|
||||||
|
if(returnVal == JFileChooser.APPROVE_OPTION) {
|
||||||
|
selectedFile = chooser.getSelectedFile();
|
||||||
|
showSelectedFilePreview();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use this private method instead of initializing on boot up so that instance
|
||||||
|
* and all listeners are created in this thread (event thread) rather than root thread
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private VisioAppFacade getVisio(){
|
||||||
|
if (visioProxy == null){
|
||||||
|
try {
|
||||||
|
visioProxy = VisioAppFacade.getInstance();
|
||||||
|
} catch (VisioException ve){
|
||||||
|
System.out.println("ailed to openFile()");
|
||||||
|
ve.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return visioProxy;
|
||||||
|
}
|
||||||
|
private void showSelectedFilePreview() throws VisioException {
|
||||||
|
if (selectedFile != null) {
|
||||||
|
byte[] image = getVisio().createPreview(selectedFile);
|
||||||
|
theImage = new ImageIcon(image);
|
||||||
|
theLabel.setIcon(theImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openFile() throws VisioException {
|
||||||
|
try {
|
||||||
|
getVisio().editDiagram(selectedFile);
|
||||||
|
showSelectedFilePreview();
|
||||||
|
} catch (VisioException ve){
|
||||||
|
System.out.println("ailed to openFile()");
|
||||||
|
ve.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void windowActivated(WindowEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void windowClosed(WindowEvent e) {
|
||||||
|
System.out.println("WINDOW CLOSED");
|
||||||
|
if (visioProxy != null){
|
||||||
|
visioProxy.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void windowClosing(WindowEvent e){
|
||||||
|
}
|
||||||
|
|
||||||
|
public void windowDeactivated(WindowEvent e){
|
||||||
|
}
|
||||||
|
|
||||||
|
public void windowDeiconified(WindowEvent e){
|
||||||
|
}
|
||||||
|
|
||||||
|
public void windowIconified(WindowEvent e){
|
||||||
|
System.out.println("Fooboo");
|
||||||
|
}
|
||||||
|
public void windowOpened(WindowEvent e){
|
||||||
|
}
|
||||||
|
}
|
||||||
59
samples/com/jacob/samples/visio/VisioEventAdapter.java
Normal file
59
samples/com/jacob/samples/visio/VisioEventAdapter.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package com.jacob.samples.visio;
|
||||||
|
import com.jacob.com.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
|
||||||
|
* @author miles@rowansoftware.net
|
||||||
|
*
|
||||||
|
* You can subclass this class and only implement the methods you're interested in
|
||||||
|
*/
|
||||||
|
public class VisioEventAdapter implements VisioEventListener {
|
||||||
|
|
||||||
|
VisioApp app = null;
|
||||||
|
|
||||||
|
public VisioEventAdapter(VisioApp pApp){
|
||||||
|
app = pApp;
|
||||||
|
System.out.println("Event listener constructed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BeforeQuit(Variant[] args){ }
|
||||||
|
|
||||||
|
public void DocumentChanged(Variant[] args){
|
||||||
|
System.out.println("documentChanged()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DocumentCloseCanceled(Variant[] args){ }
|
||||||
|
|
||||||
|
public void DocumentCreated(Variant[] args){ }
|
||||||
|
|
||||||
|
public void DocumentOpened(Variant[] args){
|
||||||
|
System.out.println("DocumentOpened()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DocumentSaved(Variant[] args){ }
|
||||||
|
|
||||||
|
public void DocumentSavedAs(Variant[] args){ }
|
||||||
|
|
||||||
|
public Variant QueryCancelDocumentClose(Variant[] args){
|
||||||
|
System.out.println("QueryCancelDocumentClose()");
|
||||||
|
return new Variant(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* we don't actually let it quit. We block it so
|
||||||
|
* that we don't have to relaunch when we look at a new document
|
||||||
|
*/
|
||||||
|
public Variant QueryCancelQuit(Variant[] args) {
|
||||||
|
// these may throw VisioException
|
||||||
|
System.out.println("Saving document, hiding and telling visio not to quit");
|
||||||
|
try {
|
||||||
|
app.save();
|
||||||
|
app.setVisible(false);
|
||||||
|
} catch (VisioException ve){
|
||||||
|
System.out.println("ailed to openFile()");
|
||||||
|
ve.printStackTrace();
|
||||||
|
}
|
||||||
|
return new Variant(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
33
samples/com/jacob/samples/visio/VisioEventListener.java
Normal file
33
samples/com/jacob/samples/visio/VisioEventListener.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package com.jacob.samples.visio;
|
||||||
|
import com.jacob.com.*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
|
||||||
|
* @author miles@rowansoftware.net
|
||||||
|
*
|
||||||
|
* There are many more Visio events available. See the Microsoft
|
||||||
|
* Office SDK documentation. To receive an event, add a method to this interface
|
||||||
|
* whose name matches the event name and has only one parameter, Variant[].
|
||||||
|
* The JACOB library will use reflection to call that method when an event is received.
|
||||||
|
*/
|
||||||
|
public interface VisioEventListener {
|
||||||
|
|
||||||
|
public void BeforeQuit(Variant[] args);
|
||||||
|
|
||||||
|
public void DocumentChanged(Variant[] args);
|
||||||
|
|
||||||
|
public void DocumentCloseCanceled(Variant[] args);
|
||||||
|
|
||||||
|
public void DocumentCreated(Variant[] args);
|
||||||
|
|
||||||
|
public void DocumentOpened(Variant[] args);
|
||||||
|
|
||||||
|
public void DocumentSaved(Variant[] args);
|
||||||
|
|
||||||
|
public void DocumentSavedAs(Variant[] args);
|
||||||
|
|
||||||
|
public Variant QueryCancelQuit(Variant[] args);
|
||||||
|
}
|
||||||
|
|
||||||
22
samples/com/jacob/samples/visio/VisioException.java
Normal file
22
samples/com/jacob/samples/visio/VisioException.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.jacob.samples.visio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers
|
||||||
|
* @author miles@rowansoftware.net
|
||||||
|
*
|
||||||
|
* This extends runtime exception so that we can be sloppy and not put catch blocks everywhere
|
||||||
|
*/
|
||||||
|
public class VisioException extends Exception {
|
||||||
|
/**
|
||||||
|
* Totally dummy value to make Eclipse quit complaining
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public VisioException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VisioException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,12 +28,17 @@ import java.lang.reflect.Method;
|
|||||||
*
|
*
|
||||||
* DispatchProxy wraps this class around any event handlers
|
* DispatchProxy wraps this class around any event handlers
|
||||||
* before making the JNI call that sets up the link with EventProxy.
|
* before making the JNI call that sets up the link with EventProxy.
|
||||||
* This means that EventProxy just calls invoke(String,Variant[])
|
* This means that EventProxy.cpp just calls invoke(String,Variant[])
|
||||||
* against the instance of this class. Then this class does
|
* against the instance of this class. Then this class does
|
||||||
* reflection against the event listener to call the actual event methods.
|
* reflection against the event listener to call the actual event methods.
|
||||||
* All Event methods have the signature
|
* All Event methods have the signature
|
||||||
*
|
*
|
||||||
* <code> void eventMethodName(Variant[])</code>
|
* <code> void eventMethodName(Variant[])</code>
|
||||||
|
* or
|
||||||
|
* <code> Variant eventMethodName(Variant[])</code>
|
||||||
|
* The void returning signature is the standard legacy signature.
|
||||||
|
* The Variant returning signature was added in 1.10 to support event handlers
|
||||||
|
* returning values.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class InvocationProxy {
|
public class InvocationProxy {
|
||||||
@@ -69,7 +74,7 @@ public class InvocationProxy {
|
|||||||
}
|
}
|
||||||
// JNI code apparently bypasses this check and could operate against
|
// JNI code apparently bypasses this check and could operate against
|
||||||
// protected classes. This seems like a security issue...
|
// protected classes. This seems like a security issue...
|
||||||
// mayb eit was because JNI code isn't in a package?
|
// maybe it was because JNI code isn't in a package?
|
||||||
if (!java.lang.reflect.Modifier.isPublic(
|
if (!java.lang.reflect.Modifier.isPublic(
|
||||||
pTargetObject.getClass().getModifiers())){
|
pTargetObject.getClass().getModifiers())){
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -78,17 +83,24 @@ public class InvocationProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the method actually invoked by EventProxy.cpp
|
* The method actually invoked by EventProxy.cpp.
|
||||||
|
* The method name is calculated by the underlying JNI code from the MS windows
|
||||||
|
* Callback function name. The method is assumed to take an array of Variant
|
||||||
|
* objects. The method may return a Variant or be a void. Those are the only
|
||||||
|
* two options that will not blow up.
|
||||||
|
*
|
||||||
* @param methodName name of method in mTargetObject we will invoke
|
* @param methodName name of method in mTargetObject we will invoke
|
||||||
* @param targetParameter Variant[] that is the single parameter to the method
|
* @param targetParameter Variant[] that is the single parameter to the method
|
||||||
*/
|
*/
|
||||||
public void invoke(String methodName, Variant targetParameter[]){
|
public Variant invoke(String methodName, Variant targetParameter[]){
|
||||||
|
Variant mVariantToBeReturned = null;
|
||||||
if (mTargetObject == null){
|
if (mTargetObject == null){
|
||||||
if (JacobObject.isDebugEnabled()){
|
if (JacobObject.isDebugEnabled()){
|
||||||
JacobObject.debug(
|
JacobObject.debug(
|
||||||
"InvocationProxy: received notification with no target set");
|
"InvocationProxy: received notification ("+methodName+") with no target set");
|
||||||
}
|
}
|
||||||
return;
|
// structured programming guidlines say this return should not be up here
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
Class targetClass = mTargetObject.getClass();
|
Class targetClass = mTargetObject.getClass();
|
||||||
if (methodName == null){
|
if (methodName == null){
|
||||||
@@ -103,24 +115,39 @@ public class InvocationProxy {
|
|||||||
JacobObject.debug("InvocationProxy: trying to invoke "+methodName
|
JacobObject.debug("InvocationProxy: trying to invoke "+methodName
|
||||||
+" on "+mTargetObject);
|
+" on "+mTargetObject);
|
||||||
}
|
}
|
||||||
Method targetMethod = targetClass.getMethod(methodName,
|
Method targetMethod;
|
||||||
|
targetMethod = targetClass.getMethod(methodName,
|
||||||
new Class[] {Variant[].class});
|
new Class[] {Variant[].class});
|
||||||
if (targetMethod != null){
|
if (targetMethod != null){
|
||||||
// protected classes can't be invoked against even if they
|
// protected classes can't be invoked against even if they
|
||||||
// let you grab the method. you could do targetMethod.setAccessible(true);
|
// let you grab the method. you could do targetMethod.setAccessible(true);
|
||||||
// but that should be stopped by the security manager
|
// but that should be stopped by the security manager
|
||||||
targetMethod.invoke(mTargetObject,new Object[] {targetParameter});
|
Object mReturnedByInvocation = null;
|
||||||
|
mReturnedByInvocation =
|
||||||
|
targetMethod.invoke(mTargetObject,new Object[] {targetParameter});
|
||||||
|
if (mReturnedByInvocation == null){
|
||||||
|
// so we do something in this block
|
||||||
|
mVariantToBeReturned = null;
|
||||||
|
} else if (!(mReturnedByInvocation instanceof Variant)){
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"InvocationProxy: invokation of target method returned "
|
||||||
|
+"non-null non-variant object: "+mReturnedByInvocation);
|
||||||
|
} else {
|
||||||
|
mVariantToBeReturned = (Variant) mReturnedByInvocation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
// this happens whenever the listener doesn't implement all the methods
|
// this happens whenever the listener doesn't implement all the methods
|
||||||
if (JacobObject.isDebugEnabled()){
|
if (JacobObject.isDebugEnabled()){
|
||||||
JacobObject.debug("InvocationProxy: listener doesn't implement "
|
JacobObject.debug("InvocationProxy: listener ("+mTargetObject+") doesn't implement "
|
||||||
+ methodName);
|
+ methodName);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
// we can throw these inside the catch block so need to re-throw it
|
||||||
|
throw e;
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
if (JacobObject.isDebugEnabled()){
|
if (JacobObject.isDebugEnabled()){
|
||||||
JacobObject.debug("InvocationProxy: probably tried to access public method on non public class"
|
JacobObject.debug("InvocationProxy: probably tried to access public method on non public class"
|
||||||
@@ -130,6 +157,7 @@ public class InvocationProxy {
|
|||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return mVariantToBeReturned;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -74,10 +74,11 @@ public class ExcelEventTest extends InvocationProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* override the invoke method to loga ll the events
|
* override the invoke method to log all the events
|
||||||
*/
|
*/
|
||||||
public void invoke(String methodName, Variant targetParameter[]) {
|
public Variant invoke(String methodName, Variant targetParameter[]) {
|
||||||
System.out.println("Received event from Windows program" + methodName);
|
System.out.println("Received event from Windows program" + methodName);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,8 +68,9 @@ public class WordEventTest extends InvocationProxy {
|
|||||||
/**
|
/**
|
||||||
* override the invoke method to loga ll the events
|
* override the invoke method to loga ll the events
|
||||||
*/
|
*/
|
||||||
public void invoke(String methodName, Variant targetParameter[]) {
|
public Variant invoke(String methodName, Variant targetParameter[]) {
|
||||||
System.out.println("Received event from Windows program" + methodName);
|
System.out.println("Received event from Windows program" + methodName);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user