⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispatch.java

📁 Very Nice library for using ActiveX controls directly from java without heavy knowledge of JNI, simp
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 1999-2004 Sourceforge JACOB Project.
 * All rights reserved. Originator: Dan Adler (http://danadler.com).
 * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package com.jacob.com;

import java.lang.reflect.Array;
import java.util.Date;

/**
 * Object represents MS level dispatch object. Each instance of this points at
 * some data structure on the MS windows side.
 * 
 * 
 * <p>
 * You're going to live here a lot
 */
public class Dispatch extends JacobObject {
	public static final int LOCALE_SYSTEM_DEFAULT = 2048;
	public static final int Method = 1;
	public static final int Get = 2;
	public static final int Put = 4;
	public static final int PutRef = 8;
	public static final int fdexNameCaseSensitive = 1;
	public static final int DISPID_UNKNOWN = -1;
	public static final int DISPID_VALUE = 0;
	public static final int DISPID_PROPERTYPUT = -3;
	public static final int DISPID_NEWENUM = -4;
	public static final int DISPID_EVALUATE = -5;
	public static final int DISPID_CONSTRUCTOR = -6;
	public static final int DISPID_DESTRUCTOR = -7;
	public static final int DISPID_COLLECT = -8;
	public static final int DISPID_AUTOSIZE = -500;
	public static final int DISPID_BACKCOLOR = -501;
	public static final int DISPID_BACKSTYLE = -502;
	public static final int DISPID_BORDERCOLOR = -503;
	public static final int DISPID_BORDERSTYLE = -504;
	public static final int DISPID_BORDERWIDTH = -505;
	public static final int DISPID_DRAWMODE = -507;
	public static final int DISPID_DRAWSTYLE = -508;
	public static final int DISPID_DRAWWIDTH = -509;
	public static final int DISPID_FILLCOLOR = -510;
	public static final int DISPID_FILLSTYLE = -511;
	public static final int DISPID_FONT = -512;
	public static final int DISPID_FORECOLOR = -513;
	public static final int DISPID_ENABLED = -514;
	public static final int DISPID_HWND = -515;
	public static final int DISPID_TABSTOP = -516;
	public static final int DISPID_TEXT = -517;
	public static final int DISPID_CAPTION = -518;
	public static final int DISPID_BORDERVISIBLE = -519;
	public static final int DISPID_APPEARANCE = -520;
	public static final int DISPID_MOUSEPOINTER = -521;
	public static final int DISPID_MOUSEICON = -522;
	public static final int DISPID_PICTURE = -523;
	public static final int DISPID_VALID = -524;
	public static final int DISPID_READYSTATE = -525;
	public static final int DISPID_REFRESH = -550;
	public static final int DISPID_DOCLICK = -551;
	public static final int DISPID_ABOUTBOX = -552;
	public static final int DISPID_CLICK = -600;
	public static final int DISPID_DBLCLICK = -601;
	public static final int DISPID_KEYDOWN = -602;
	public static final int DISPID_KEYPRESS = -603;
	public static final int DISPID_KEYUP = -604;
	public static final int DISPID_MOUSEDOWN = -605;
	public static final int DISPID_MOUSEMOVE = -606;
	public static final int DISPID_MOUSEUP = -607;
	public static final int DISPID_ERROREVENT = -608;
	public static final int DISPID_READYSTATECHANGE = -609;
	public static final int DISPID_AMBIENT_BACKCOLOR = -701;
	public static final int DISPID_AMBIENT_DISPLAYNAME = -702;
	public static final int DISPID_AMBIENT_FONT = -703;
	public static final int DISPID_AMBIENT_FORECOLOR = -704;
	public static final int DISPID_AMBIENT_LOCALEID = -705;
	public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706;
	public static final int DISPID_AMBIENT_SCALEUNITS = -707;
	public static final int DISPID_AMBIENT_TEXTALIGN = -708;
	public static final int DISPID_AMBIENT_USERMODE = -709;
	public static final int DISPID_AMBIENT_UIDEAD = -710;
	public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711;
	public static final int DISPID_AMBIENT_SHOWHATCHING = -712;
	public static final int DISPID_AMBIENT_DISPLAYASDEFAULT = -713;
	public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714;
	public static final int DISPID_AMBIENT_AUTOCLIP = -715;
	public static final int DISPID_AMBIENT_APPEARANCE = -716;
	public static final int DISPID_AMBIENT_CODEPAGE = -725;
	public static final int DISPID_AMBIENT_PALETTE = -726;
	public static final int DISPID_AMBIENT_CHARSET = -727;
	public static final int DISPID_AMBIENT_TRANSFERPRIORITY = -728;
	/**
	 * This is public because Dispatch.cpp knows its name and accesses it
	 * directly to get the disptach id. You really can't rename it or make it
	 * private
	 */
	public int m_pDispatch;

	/** program Id passed in by ActiveX components in their constructor */
	private String programId = null;

	private static int NOT_ATTACHED = 0;

	/**
	 * Dummy empty array used one doesn't have to be created on every invocation
	 */
	private final static Object[] NO_OBJECT_ARGS = new Object[0];
	/**
	 * Dummy empty array used one doesn't have to be created on every invocation
	 */
	private final static Variant[] NO_VARIANT_ARGS = new Variant[0];
	/**
	 * Dummy empty array used one doesn't have to be created on every invocation
	 */
	private final static int[] NO_INT_ARGS = new int[0];

	/**
	 * zero argument constructor that sets the dispatch pointer to 0 This is the
	 * only way to create a Dispatch without a value in the pointer field.
	 */
	public Dispatch() {
		m_pDispatch = NOT_ATTACHED;
	}

	/**
	 * This constructor calls createInstance with progid. This is the
	 * constructor used by the ActiveXComponent or by programs that don't like
	 * the activeX interface but wish to create new connections to windows
	 * programs.
	 * <p>
	 * This constructor always creates a new windows/program object because it
	 * is based on the CoCreate() windows function.
	 * <p>
	 * 
	 * @throws IllegalArgumentException
	 *             if null is passed in as the program id
	 *             <p>
	 * @param requestedProgramId
	 */
	public Dispatch(String requestedProgramId) {
		programId = requestedProgramId;
		if (programId != null && !"".equals(programId)) {
			createInstanceNative(requestedProgramId);
		} else {
			throw new IllegalArgumentException(
					"Dispatch(String) does not accept null or an empty string as a parameter");
		}
	}

	/**
	 * native call createInstance only used by the constructor with the same
	 * parm type. This probably should be private. It is the wrapper for the
	 * Windows CoCreate() call
	 * <P>
	 * This ends up calling CoCreate down in the JNI layer
	 * <p>
	 * The behavior is different if a ":" character exists in the progId. In
	 * that case CoGetObject and CreateInstance (someone needs to describe this
	 * better)
	 * 
	 * @param progid
	 */
	private native void createInstanceNative(String progid);

	/**
	 * native call getActiveInstance only used by the constructor with the same
	 * parm type. This probably should be private. It is the wrapper for the
	 * Windows GetActiveObject() call
	 * <P>
	 * This ends up calling GetActiveObject down in the JNI layer
	 * <p>
	 * This does not have the special behavior for program ids with ":" in them
	 * that createInstance has.
	 * 
	 * @param progid
	 */
	private native void getActiveInstanceNative(String progid);

	/**
	 * Wrapper around the native method
	 * 
	 * @param pProgramIdentifier
	 *            name of the program you wish to connect to
	 */
	protected void getActiveInstance(String pProgramIdentifier) {
		if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) {
			throw new IllegalArgumentException("program id is required");
		}
		this.programId = pProgramIdentifier;
		getActiveInstanceNative(pProgramIdentifier);
	}

	/**
	 * native call coCreateInstance only used by the constructor with the same
	 * parm type. This probably should be private. It is the wrapper for the
	 * Windows CoCreate() call
	 * <P>
	 * This ends up calling CoCreate down in the JNI layer
	 * <p>
	 * This does not have the special behavior for program ids with ":" in them
	 * that createInstance has.
	 * 
	 * @param progid
	 */
	private native void coCreateInstanceNative(String progid);

	/**
	 * Wrapper around the native method
	 * 
	 * @param pProgramIdentifier
	 */
	protected void coCreateInstance(String pProgramIdentifier) {
		if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) {
			throw new IllegalArgumentException("program id is required");
		}
		this.programId = pProgramIdentifier;
		coCreateInstanceNative(pProgramIdentifier);
	}

	/**
	 * Return a different interface by IID string.
	 * <p>
	 * Once you have a Dispatch object, you can navigate to the other interfaces
	 * of a COM object by calling QueryInterafce. The argument is an IID string
	 * in the format: "{9BF24410-B2E0-11D4-A695-00104BFF3241}". You typically
	 * get this string from the idl file (it's called uuid in there). Any
	 * interface you try to use must be derived from IDispatch. T The atl
	 * example uses this.
	 * <p>
	 * The Dispatch instance resulting from this query is instanciated in the
	 * JNI code.
	 * 
	 * @param iid
	 * @return Dispatch a disptach that matches ??
	 */
	public native Dispatch QueryInterface(String iid);

	/**
	 * Constructor that only gets called from JNI QueryInterface calls JNI code
	 * that looks up the object for the key passed in. The JNI CODE then creates
	 * a new dispatch object using this constructor
	 * 
	 * @param pDisp
	 */
	protected Dispatch(int pDisp) {
		m_pDispatch = pDisp;
	}

	/**
	 * Constructor to be used by subclass that want to swap themselves in for
	 * the default Dispatch class. Usually you will have a class like
	 * WordDocument that is a subclass of Dispatch and it will have a
	 * constructor public WordDocument(Dispatch). That constructor should just
	 * call this constructor as super(Dispatch)
	 * 
	 * @param dispatchToBeDisplaced
	 */
	public Dispatch(Dispatch dispatchToBeDisplaced) {
		// TAKE OVER THE IDispatch POINTER
		this.m_pDispatch = dispatchToBeDisplaced.m_pDispatch;
		// NULL OUT THE INPUT POINTER
		dispatchToBeDisplaced.m_pDispatch = NOT_ATTACHED;
	}

	/**
	 * returns the program id if an activeX component created this otherwise it
	 * returns null. This was added to aid in debugging
	 * 
	 * @return the program id an activeX component was created against
	 */
	public String getProgramId() {
		return programId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#finalize()
	 */
	protected void finalize() {
		safeRelease();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.jacob.com.JacobObject#safeRelease()
	 */
	public void safeRelease() {
		super.safeRelease();
		if (isAttached()) {
			release();
			m_pDispatch = NOT_ATTACHED;
		} else {
			// looks like a double release
			if (isDebugEnabled()) {
				debug(this.getClass().getName() + ":" + this.hashCode()
						+ " double release");
			}
		}
	}

	/**
	 * 
	 * @return true if there is an underlying windows dispatch object
	 */
	protected boolean isAttached() {
		if (m_pDispatch == NOT_ATTACHED) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * @throws IllegalStateException
	 *             if this dispatch isn't hooked up
	 * @throws IllegalArgumentException
	 *             if null the dispatch under test is null
	 * @param theOneInQuestion
	 *            dispatch being tested
	 */
	private static void throwIfUnattachedDispatch(Dispatch theOneInQuestion) {
		if (theOneInQuestion == null) {
			throw new IllegalArgumentException(
					"Can't pass in null Dispatch object");
		} else if (theOneInQuestion.isAttached()) {
			return;
		} else {
			throw new IllegalStateException(
					"Dispatch not hooked to windows memory");
		}
	}

	/**
	 * Map args based on msdn doc This method relies on the variant constructor
	 * except for arrays
	 * 
	 * @param objectToBeMadeIntoVariant
	 * @return Variant that represents the object
	 */
	@SuppressWarnings("unchecked")
	protected static Variant obj2variant(Object objectToBeMadeIntoVariant) {
		if (objectToBeMadeIntoVariant == null)
			return new Variant();
		if (objectToBeMadeIntoVariant instanceof Variant)
			// if a variant was passed in then be a slacker and just return it
			return (Variant) objectToBeMadeIntoVariant;
		if (objectToBeMadeIntoVariant instanceof Integer
				|| objectToBeMadeIntoVariant instanceof Short
				|| objectToBeMadeIntoVariant instanceof String
				|| objectToBeMadeIntoVariant instanceof Boolean
				|| objectToBeMadeIntoVariant instanceof Double
				|| objectToBeMadeIntoVariant instanceof Float
				|| objectToBeMadeIntoVariant instanceof SafeArray
				|| objectToBeMadeIntoVariant instanceof Date
				|| objectToBeMadeIntoVariant instanceof Dispatch)
			return new Variant(objectToBeMadeIntoVariant);

		// automatically convert arrays using reflection
		Class c1 = objectToBeMadeIntoVariant.getClass();
		SafeArray sa = null;
		if (c1.isArray()) {
			int len1 = Array.getLength(objectToBeMadeIntoVariant);
			Object first = Array.get(objectToBeMadeIntoVariant, 0);
			if (first.getClass().isArray()) {
				int max = 0;
				for (int i = 0; i < len1; i++) {
					Object e1 = Array.get(objectToBeMadeIntoVariant, i);
					int len2 = Array.getLength(e1);
					if (max < len2) {
						max = len2;
					}
				}
				sa = new SafeArray(Variant.VariantVariant, len1, max);
				for (int i = 0; i < len1; i++) {
					Object e1 = Array.get(objectToBeMadeIntoVariant, i);
					for (int j = 0; j < Array.getLength(e1); j++) {
						sa.setVariant(i, j, obj2variant(Array.get(e1, j)));
					}
				}
			} else {
				sa = new SafeArray(Variant.VariantVariant, len1);
				for (int i = 0; i < len1; i++) {
					sa.setVariant(i, obj2variant(Array.get(
							objectToBeMadeIntoVariant, i)));
				}
			}
			return new Variant(sa);
		}
		throw new ClassCastException("cannot convert to Variant");
	}

	/**
	 * converts an array of objects into an array of Variants by repeatedly
	 * calling obj2Variant(Object)
	 * 
	 * @param arrayOfObjectsToBeConverted
	 * @return Variant[]
	 */
	protected static Variant[] obj2variant(Object[] arrayOfObjectsToBeConverted) {
		Variant vArg[] = new Variant[arrayOfObjectsToBeConverted.length];
		for (int i = 0; i < arrayOfObjectsToBeConverted.length; i++) {
			vArg[i] = obj2variant(arrayOfObjectsToBeConverted[i]);
		}
		return vArg;
	}

	/**
	 * now private so only this object can asccess was: call this to explicitly
	 * release the com object before gc
	 * 
	 */
	private native void release();

	/**
	 * not implemented yet
	 * 
	 * @param dispatchTarget
	 * @param name
	 * @param val
	 * @throws com.jacob.com.NotImplementedException
	 */
	public static void put_Casesensitive(Dispatch dispatchTarget, String name,
			Object val) {
		throw new NotImplementedException("not implemented yet");
	}

	/*
	 * ============================================================ start of the
	 * invokev section
	 * ===========================================================
	 */
	// eliminate _Guid arg
	/**
	 * @param dispatchTarget
	 * @param name
	 * @param dispID
	 * @param lcid
	 * @param wFlags
	 * @param vArg
	 * @param uArgErr
	 */
	public static void invokeSubv(Dispatch dispatchTarget, String name,
			int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr) {
		throwIfUnattachedDispatch(dispatchTarget);
		invokev(dispatchTarget, name, dispID, lcid, wFlags, vArg, uArgErr);
	}

	/**
	 * @param dispatchTarget
	 * @param name
	 * @param wFlags
	 * @param vArg
	 * @param uArgErr
	 */
	public static void invokeSubv(Dispatch dispatchTarget, String name,
			int wFlags, Variant[] vArg, int[] uArgErr) {
		throwIfUnattachedDispatch(dispatchTarget);
		invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT,
				wFlags, vArg, uArgErr);
	}

	/**
	 * @param dispatchTarget
	 * @param dispID
	 * @param wFlags

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -