0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.swt.ole.win32;
0011:
0012: import org.eclipse.swt.*;
0013: import org.eclipse.swt.internal.ole.win32.*;
0014: import org.eclipse.swt.graphics.*;
0015: import org.eclipse.swt.widgets.*;
0016: import org.eclipse.swt.internal.win32.*;
0017:
0018: /**
0019: * OleControlSite provides a site to manage an embedded ActiveX Control within a container.
0020: *
0021: * <p>In addition to the behaviour provided by OleClientSite, this object provides the following:
0022: * <ul>
0023: * <li>events from the ActiveX control
0024: * <li>notification of property changes from the ActiveX control
0025: * <li>simplified access to well known properties of the ActiveX Control (e.g. font, background color)
0026: * <li>expose ambient properties of the container to the ActiveX Control
0027: * </ul>
0028: *
0029: * <p>This object implements the OLE Interfaces IOleControlSite, IDispatch, and IPropertyNotifySink.
0030: *
0031: * <p>Note that although this class is a subclass of <code>Composite</code>,
0032: * it does not make sense to add <code>Control</code> children to it,
0033: * or set a layout on it.
0034: * </p><p>
0035: * <dl>
0036: * <dt><b>Styles</b> <dd>BORDER
0037: * <dt><b>Events</b> <dd>Dispose, Move, Resize
0038: * </dl>
0039: *
0040: */
0041: public class OleControlSite extends OleClientSite {
0042: // interfaces for this container
0043: private COMObject iOleControlSite;
0044: private COMObject iDispatch;
0045:
0046: // supporting Property Change attributes
0047: private OlePropertyChangeSink olePropertyChangeSink;
0048:
0049: // supporting Event Sink attributes
0050: private OleEventSink[] oleEventSink = new OleEventSink[0];
0051: private GUID[] oleEventSinkGUID = new GUID[0];
0052: private int /*long*/[] oleEventSinkIUnknown = new int /*long*/[0];
0053:
0054: // supporting information for the Control COM object
0055: private CONTROLINFO currentControlInfo;
0056: private int[] sitePropertyIds = new int[0];
0057: private Variant[] sitePropertyValues = new Variant[0];
0058:
0059: // work around for IE destroying the caret
0060: static int SWT_RESTORECARET;
0061:
0062: /**
0063: * Create an OleControlSite child widget using style bits
0064: * to select a particular look or set of properties.
0065: *
0066: * @param parent a composite widget; must be an OleFrame
0067: * @param style the bitwise OR'ing of widget styles
0068: * @param progId the unique program identifier which has been registered for this ActiveX Control;
0069: * the value of the ProgID key or the value of the VersionIndependentProgID key specified
0070: * in the registry for this Control (for example, the VersionIndependentProgID for
0071: * Internet Explorer is Shell.Explorer)
0072: *
0073: *@exception IllegalArgumentException <ul>
0074: * <li>ERROR_NULL_ARGUMENT when the parent is null
0075: *</ul>
0076: * @exception SWTException <ul>
0077: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
0078: * <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
0079: * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
0080: * <li>ERROR_CANNOT_ACCESS_CLASSFACTORY when Class Factory could not be found
0081: * <li>ERROR_CANNOT_CREATE_LICENSED_OBJECT when failed to create a licensed OLE Object
0082: * </ul>
0083: */
0084: public OleControlSite(Composite parent, int style, String progId) {
0085: super (parent, style);
0086: try {
0087:
0088: // check for licensing
0089: appClsid = getClassID(progId);
0090: if (appClsid == null)
0091: OLE.error(OLE.ERROR_INVALID_CLASSID);
0092:
0093: int /*long*/licinfo = getLicenseInfo(appClsid);
0094: if (licinfo == 0) {
0095:
0096: // Open a storage object
0097: tempStorage = createTempStorage();
0098:
0099: // Create ole object with storage object
0100: int /*long*/[] address = new int /*long*/[1];
0101: int result = COM.OleCreate(appClsid, COM.IIDIUnknown,
0102: COM.OLERENDER_DRAW, null, 0, tempStorage
0103: .getAddress(), address);
0104: if (result != COM.S_OK)
0105: OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
0106:
0107: objIUnknown = new IUnknown(address[0]);
0108:
0109: } else {
0110: // Prepare the ClassFactory
0111: int /*long*/[] ppvObject = new int /*long*/[1];
0112: try {
0113: int result = COM.CoGetClassObject(appClsid,
0114: COM.CLSCTX_INPROC_HANDLER
0115: | COM.CLSCTX_INPROC_SERVER, 0,
0116: COM.IIDIClassFactory2, ppvObject);
0117: if (result != COM.S_OK) {
0118: OLE.error(OLE.ERROR_CANNOT_ACCESS_CLASSFACTORY,
0119: result);
0120: }
0121: IClassFactory2 classFactory = new IClassFactory2(
0122: ppvObject[0]);
0123: // Create Com Object
0124: ppvObject = new int /*long*/[1];
0125: result = classFactory.CreateInstanceLic(0, 0,
0126: COM.IIDIUnknown, licinfo, ppvObject);
0127: classFactory.Release();
0128: if (result != COM.S_OK)
0129: OLE
0130: .error(
0131: OLE.ERROR_CANNOT_CREATE_LICENSED_OBJECT,
0132: result);
0133: } finally {
0134: COM.SysFreeString(licinfo);
0135: }
0136:
0137: objIUnknown = new IUnknown(ppvObject[0]);
0138:
0139: // Prepare a storage medium
0140: ppvObject = new int /*long*/[1];
0141: if (objIUnknown.QueryInterface(COM.IIDIPersistStorage,
0142: ppvObject) == COM.S_OK) {
0143: IPersistStorage persist = new IPersistStorage(
0144: ppvObject[0]);
0145: tempStorage = createTempStorage();
0146: persist.InitNew(tempStorage.getAddress());
0147: persist.Release();
0148: }
0149: }
0150:
0151: // Init sinks
0152: addObjectReferences();
0153:
0154: // Init site properties
0155: setSiteProperty(COM.DISPID_AMBIENT_USERMODE, new Variant(
0156: true));
0157: setSiteProperty(COM.DISPID_AMBIENT_UIDEAD, new Variant(
0158: false));
0159:
0160: if (COM.OleRun(objIUnknown.getAddress()) == OLE.S_OK)
0161: state = STATE_RUNNING;
0162:
0163: } catch (SWTError e) {
0164: dispose();
0165: disposeCOMInterfaces();
0166: throw e;
0167: }
0168: }
0169:
0170: /**
0171: * Adds the listener to receive events.
0172: *
0173: * @param eventID the id of the event
0174: *
0175: * @param listener the listener
0176: *
0177: * @exception IllegalArgumentException <ul>
0178: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0179: * </ul>
0180: */
0181: public void addEventListener(int eventID, OleListener listener) {
0182: if (listener == null)
0183: OLE.error(SWT.ERROR_NULL_ARGUMENT);
0184: GUID riid = getDefaultEventSinkGUID(objIUnknown);
0185: if (riid != null) {
0186: addEventListener(objIUnknown.getAddress(), riid, eventID,
0187: listener);
0188: }
0189:
0190: }
0191:
0192: static GUID getDefaultEventSinkGUID(IUnknown unknown) {
0193: // get Event Sink I/F from IProvideClassInfo2
0194: int /*long*/[] ppvObject = new int /*long*/[1];
0195: if (unknown
0196: .QueryInterface(COM.IIDIProvideClassInfo2, ppvObject) == COM.S_OK) {
0197: IProvideClassInfo2 pci2 = new IProvideClassInfo2(
0198: ppvObject[0]);
0199: GUID riid = new GUID();
0200: int result = pci2.GetGUID(
0201: COM.GUIDKIND_DEFAULT_SOURCE_DISP_IID, riid);
0202: pci2.Release();
0203: if (result == COM.S_OK)
0204: return riid;
0205: }
0206:
0207: // get Event Sink I/F from IProvideClassInfo
0208: if (unknown.QueryInterface(COM.IIDIProvideClassInfo, ppvObject) == COM.S_OK) {
0209: IProvideClassInfo pci = new IProvideClassInfo(ppvObject[0]);
0210: int /*long*/[] ppTI = new int /*long*/[1];
0211: int /*long*/[] ppEI = new int /*long*/[1];
0212: int result = pci.GetClassInfo(ppTI);
0213: pci.Release();
0214:
0215: if (result == COM.S_OK && ppTI[0] != 0) {
0216: ITypeInfo classInfo = new ITypeInfo(ppTI[0]);
0217: int /*long*/[] ppTypeAttr = new int /*long*/[1];
0218: result = classInfo.GetTypeAttr(ppTypeAttr);
0219: if (result == COM.S_OK && ppTypeAttr[0] != 0) {
0220: TYPEATTR typeAttribute = new TYPEATTR();
0221: COM.MoveMemory(typeAttribute, ppTypeAttr[0],
0222: TYPEATTR.sizeof);
0223: classInfo.ReleaseTypeAttr(ppTypeAttr[0]);
0224: int implMask = COM.IMPLTYPEFLAG_FDEFAULT
0225: | COM.IMPLTYPEFLAG_FSOURCE
0226: | COM.IMPLTYPEFLAG_FRESTRICTED;
0227: int implBits = COM.IMPLTYPEFLAG_FDEFAULT
0228: | COM.IMPLTYPEFLAG_FSOURCE;
0229:
0230: for (int i = 0; i < typeAttribute.cImplTypes; i++) {
0231: int[] pImplTypeFlags = new int[1];
0232: if (classInfo.GetImplTypeFlags(i,
0233: pImplTypeFlags) == COM.S_OK) {
0234: if ((pImplTypeFlags[0] & implMask) == implBits) {
0235: int[] pRefType = new int[1];
0236: if (classInfo.GetRefTypeOfImplType(i,
0237: pRefType) == COM.S_OK) {
0238: classInfo.GetRefTypeInfo(
0239: pRefType[0], ppEI);
0240: }
0241: }
0242: }
0243: }
0244: }
0245: classInfo.Release();
0246:
0247: if (ppEI[0] != 0) {
0248: ITypeInfo eventInfo = new ITypeInfo(ppEI[0]);
0249: ppTypeAttr = new int /*long*/[1];
0250: result = eventInfo.GetTypeAttr(ppTypeAttr);
0251: GUID riid = null;
0252: if (result == COM.S_OK && ppTypeAttr[0] != 0) {
0253: riid = new GUID();
0254: COM
0255: .MoveMemory(riid, ppTypeAttr[0],
0256: GUID.sizeof);
0257: eventInfo.ReleaseTypeAttr(ppTypeAttr[0]);
0258: }
0259: eventInfo.Release();
0260: return riid;
0261: }
0262: }
0263: }
0264: return null;
0265: }
0266:
0267: /**
0268: * Adds the listener to receive events.
0269: *
0270: * @since 2.0
0271: *
0272: * @param automation the automation object that provides the event notification
0273: * @param eventID the id of the event
0274: * @param listener the listener
0275: *
0276: * @exception IllegalArgumentException <ul>
0277: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0278: * </ul>
0279: */
0280: public void addEventListener(OleAutomation automation, int eventID,
0281: OleListener listener) {
0282: if (listener == null || automation == null)
0283: OLE.error(SWT.ERROR_NULL_ARGUMENT);
0284: int /*long*/address = automation.getAddress();
0285: IUnknown unknown = new IUnknown(address);
0286: GUID riid = getDefaultEventSinkGUID(unknown);
0287: if (riid != null) {
0288: addEventListener(address, riid, eventID, listener);
0289: }
0290:
0291: }
0292:
0293: /**
0294: * Adds the listener to receive events.
0295: *
0296: * @since 3.2
0297: *
0298: * @param automation the automation object that provides the event notification
0299: * @param eventSinkId the GUID of the event sink
0300: * @param eventID the id of the event
0301: * @param listener the listener
0302: *
0303: * @exception IllegalArgumentException <ul>
0304: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0305: * </ul>
0306: */
0307: public void addEventListener(OleAutomation automation,
0308: String eventSinkId, int eventID, OleListener listener) {
0309: if (listener == null || automation == null
0310: || eventSinkId == null)
0311: OLE.error(SWT.ERROR_NULL_ARGUMENT);
0312: int /*long*/address = automation.getAddress();
0313: if (address == 0)
0314: return;
0315: char[] buffer = (eventSinkId + "\0").toCharArray();
0316: GUID guid = new GUID();
0317: if (COM.IIDFromString(buffer, guid) != COM.S_OK)
0318: return;
0319: addEventListener(address, guid, eventID, listener);
0320: }
0321:
0322: void addEventListener(int /*long*/iunknown, GUID guid,
0323: int eventID, OleListener listener) {
0324: if (listener == null || iunknown == 0 || guid == null)
0325: OLE.error(SWT.ERROR_NULL_ARGUMENT);
0326: // have we connected to this kind of event sink before?
0327: int index = -1;
0328: for (int i = 0; i < oleEventSinkGUID.length; i++) {
0329: if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
0330: if (iunknown == oleEventSinkIUnknown[i]) {
0331: index = i;
0332: break;
0333: }
0334: }
0335: }
0336: if (index != -1) {
0337: oleEventSink[index].addListener(eventID, listener);
0338: } else {
0339: int oldLength = oleEventSink.length;
0340: OleEventSink[] newOleEventSink = new OleEventSink[oldLength + 1];
0341: GUID[] newOleEventSinkGUID = new GUID[oldLength + 1];
0342: int /*long*/[] newOleEventSinkIUnknown = new int /*long*/[oldLength + 1];
0343: System.arraycopy(oleEventSink, 0, newOleEventSink, 0,
0344: oldLength);
0345: System.arraycopy(oleEventSinkGUID, 0, newOleEventSinkGUID,
0346: 0, oldLength);
0347: System.arraycopy(oleEventSinkIUnknown, 0,
0348: newOleEventSinkIUnknown, 0, oldLength);
0349: oleEventSink = newOleEventSink;
0350: oleEventSinkGUID = newOleEventSinkGUID;
0351: oleEventSinkIUnknown = newOleEventSinkIUnknown;
0352:
0353: oleEventSink[oldLength] = new OleEventSink(this , iunknown,
0354: guid);
0355: oleEventSinkGUID[oldLength] = guid;
0356: oleEventSinkIUnknown[oldLength] = iunknown;
0357: oleEventSink[oldLength].AddRef();
0358: oleEventSink[oldLength].connect();
0359: oleEventSink[oldLength].addListener(eventID, listener);
0360:
0361: }
0362: }
0363:
0364: protected void addObjectReferences() {
0365:
0366: super .addObjectReferences();
0367:
0368: // Get property change notification from control
0369: connectPropertyChangeSink();
0370:
0371: // Get access to the Control object
0372: int /*long*/[] ppvObject = new int /*long*/[1];
0373: if (objIUnknown.QueryInterface(COM.IIDIOleControl, ppvObject) == COM.S_OK) {
0374: IOleControl objIOleControl = new IOleControl(ppvObject[0]);
0375: // ask the control for its info in case users
0376: // need to act on it
0377: currentControlInfo = new CONTROLINFO();
0378: objIOleControl.GetControlInfo(currentControlInfo);
0379: objIOleControl.Release();
0380: }
0381: }
0382:
0383: /**
0384: * Adds the listener to receive events.
0385: *
0386: * @param propertyID the identifier of the property
0387: * @param listener the listener
0388: *
0389: * @exception IllegalArgumentException <ul>
0390: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0391: * </ul>
0392: */
0393: public void addPropertyListener(int propertyID, OleListener listener) {
0394: if (listener == null)
0395: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0396: olePropertyChangeSink.addListener(propertyID, listener);
0397: }
0398:
0399: private void connectPropertyChangeSink() {
0400: olePropertyChangeSink = new OlePropertyChangeSink(this );
0401: olePropertyChangeSink.AddRef();
0402: olePropertyChangeSink.connect(objIUnknown);
0403: }
0404:
0405: protected void createCOMInterfaces() {
0406: super .createCOMInterfaces();
0407:
0408: // register each of the interfaces that this object implements
0409: iOleControlSite = new COMObject(new int[] { 2, 0, 0, 0, 1, 1,
0410: 3, 2, 1, 0 }) {
0411: public int /*long*/method0(int /*long*/[] args) {
0412: return QueryInterface(args[0], args[1]);
0413: }
0414:
0415: public int /*long*/method1(int /*long*/[] args) {
0416: return AddRef();
0417: }
0418:
0419: public int /*long*/method2(int /*long*/[] args) {
0420: return Release();
0421: }
0422:
0423: public int /*long*/method3(int /*long*/[] args) {
0424: return OnControlInfoChanged();
0425: }
0426:
0427: // method4 LockInPlaceActive - not implemented
0428: // method5 GetExtendedControl - not implemented
0429: // method6 TransformCoords - not implemented
0430: // method7 Translate Accelerator - not implemented
0431: public int /*long*/method8(int /*long*/[] args) {
0432: return OnFocus((int) /*64*/args[0]);
0433: }
0434: // method9 ShowPropertyFrame - not implemented
0435: };
0436:
0437: iDispatch = new COMObject(new int[] { 2, 0, 0, 1, 3, 5, 8 }) {
0438: public int /*long*/method0(int /*long*/[] args) {
0439: return QueryInterface(args[0], args[1]);
0440: }
0441:
0442: public int /*long*/method1(int /*long*/[] args) {
0443: return AddRef();
0444: }
0445:
0446: public int /*long*/method2(int /*long*/[] args) {
0447: return Release();
0448: }
0449:
0450: // method3 GetTypeInfoCount - not implemented
0451: // method4 GetTypeInfo - not implemented
0452: // method5 GetIDsOfNames - not implemented
0453: public int /*long*/method6(int /*long*/[] args) {
0454: return Invoke((int) /*64*/args[0], args[1],
0455: (int) /*64*/args[2], (int) /*64*/args[3],
0456: args[4], args[5], args[6], args[7]);
0457: }
0458: };
0459: }
0460:
0461: private void disconnectEventSinks() {
0462:
0463: for (int i = 0; i < oleEventSink.length; i++) {
0464: OleEventSink sink = oleEventSink[i];
0465: sink.disconnect();
0466: sink.Release();
0467: }
0468: oleEventSink = new OleEventSink[0];
0469: oleEventSinkGUID = new GUID[0];
0470: oleEventSinkIUnknown = new int /*long*/[0];
0471: }
0472:
0473: private void disconnectPropertyChangeSink() {
0474:
0475: if (olePropertyChangeSink != null) {
0476: olePropertyChangeSink.disconnect(objIUnknown);
0477: olePropertyChangeSink.Release();
0478: }
0479: olePropertyChangeSink = null;
0480: }
0481:
0482: protected void disposeCOMInterfaces() {
0483: super .disposeCOMInterfaces();
0484:
0485: if (iOleControlSite != null)
0486: iOleControlSite.dispose();
0487: iOleControlSite = null;
0488:
0489: if (iDispatch != null)
0490: iDispatch.dispose();
0491: iDispatch = null;
0492: }
0493:
0494: public Color getBackground() {
0495:
0496: if (objIUnknown != null) {
0497: // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
0498: OleAutomation oleObject = new OleAutomation(this );
0499: Variant varBackColor = oleObject
0500: .getProperty(COM.DISPID_BACKCOLOR);
0501: oleObject.dispose();
0502:
0503: if (varBackColor != null) {
0504: int[] colorRef = new int[1];
0505: if (COM.OleTranslateColor(varBackColor.getInt(),
0506: getDisplay().hPalette, colorRef) == COM.S_OK)
0507: return Color.win32_new(getDisplay(), colorRef[0]);
0508: }
0509: }
0510:
0511: return super .getBackground();
0512: }
0513:
0514: public Font getFont() {
0515:
0516: if (objIUnknown != null) {
0517: OleAutomation oleObject = new OleAutomation(this );
0518: Variant varDispFont = oleObject
0519: .getProperty(COM.DISPID_FONT);
0520: oleObject.dispose();
0521:
0522: if (varDispFont != null) {
0523: OleAutomation iDispFont = varDispFont.getAutomation();
0524: Variant lfFaceName = iDispFont
0525: .getProperty(COM.DISPID_FONT_NAME);
0526: Variant lfHeight = iDispFont
0527: .getProperty(COM.DISPID_FONT_SIZE);
0528: Variant lfItalic = iDispFont
0529: .getProperty(COM.DISPID_FONT_ITALIC);
0530: //Variant lfCharSet = iDispFont.getProperty(COM.DISPID_FONT_CHARSET);
0531: Variant lfBold = iDispFont
0532: .getProperty(COM.DISPID_FONT_BOLD);
0533: iDispFont.dispose();
0534:
0535: if (lfFaceName != null && lfHeight != null
0536: && lfItalic != null && lfBold != null) {
0537: int style = 3 * lfBold.getInt() + 2
0538: * lfItalic.getInt();
0539: Font font = new Font(getShell().getDisplay(),
0540: lfFaceName.getString(), lfHeight.getInt(),
0541: style);
0542: return font;
0543: }
0544: }
0545: }
0546:
0547: return super .getFont();
0548: }
0549:
0550: public Color getForeground() {
0551:
0552: if (objIUnknown != null) {
0553: // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
0554: OleAutomation oleObject = new OleAutomation(this );
0555: Variant varForeColor = oleObject
0556: .getProperty(COM.DISPID_FORECOLOR);
0557: oleObject.dispose();
0558:
0559: if (varForeColor != null) {
0560: int[] colorRef = new int[1];
0561: if (COM.OleTranslateColor(varForeColor.getInt(),
0562: getDisplay().hPalette, colorRef) == COM.S_OK)
0563: return Color.win32_new(getDisplay(), colorRef[0]);
0564: }
0565: }
0566:
0567: return super .getForeground();
0568: }
0569:
0570: protected int /*long*/getLicenseInfo(GUID clsid) {
0571: int /*long*/[] ppvObject = new int /*long*/[1];
0572:
0573: if (COM.CoGetClassObject(clsid, COM.CLSCTX_INPROC_HANDLER
0574: | COM.CLSCTX_INPROC_SERVER, 0, COM.IIDIClassFactory2,
0575: ppvObject) != COM.S_OK) {
0576: return 0;
0577: }
0578: IClassFactory2 classFactory = new IClassFactory2(ppvObject[0]);
0579: LICINFO licinfo = new LICINFO();
0580: if (classFactory.GetLicInfo(licinfo) != COM.S_OK) {
0581: classFactory.Release();
0582: return 0;
0583: }
0584: int /*long*/[] pBstrKey = new int /*long*/[1];
0585: if (licinfo != null && licinfo.fRuntimeKeyAvail) {
0586: if (classFactory.RequestLicKey(0, pBstrKey) == COM.S_OK) {
0587: classFactory.Release();
0588: return pBstrKey[0];
0589: }
0590: }
0591: classFactory.Release();
0592: return 0;
0593: }
0594:
0595: /**
0596: *
0597: * Get the control site property specified by the dispIdMember.
0598: *
0599: * @since 2.1
0600: *
0601: */
0602: public Variant getSiteProperty(int dispId) {
0603: for (int i = 0; i < sitePropertyIds.length; i++) {
0604: if (sitePropertyIds[i] == dispId) {
0605: return sitePropertyValues[i];
0606: }
0607: }
0608: return null;
0609: }
0610:
0611: protected int GetWindow(int /*long*/phwnd) {
0612:
0613: if (phwnd == 0)
0614: return COM.E_INVALIDARG;
0615: if (frame == null) {
0616: COM.MoveMemory(phwnd, new int /*long*/[] { 0 },
0617: OS.PTR_SIZEOF);
0618: return COM.E_NOTIMPL;
0619: }
0620:
0621: // Copy the Window's handle into the memory passed in
0622: COM.MoveMemory(phwnd, new int /*long*/[] { handle },
0623: OS.PTR_SIZEOF);
0624: return COM.S_OK;
0625: }
0626:
0627: private int Invoke(int dispIdMember, int /*long*/riid, int lcid,
0628: int dwFlags, int /*long*/pDispParams,
0629: int /*long*/pVarResult, int /*long*/pExcepInfo,
0630: int /*long*/pArgErr) {
0631: if (pVarResult == 0 || dwFlags != COM.DISPATCH_PROPERTYGET) {
0632: if (pExcepInfo != 0)
0633: COM.MoveMemory(pExcepInfo, new int /*long*/[] { 0 },
0634: OS.PTR_SIZEOF);
0635: if (pArgErr != 0)
0636: COM.MoveMemory(pArgErr, new int[] { 0 }, 4);
0637: return COM.DISP_E_MEMBERNOTFOUND;
0638: }
0639: Variant result = getSiteProperty(dispIdMember);
0640: if (result != null) {
0641: if (pVarResult != 0)
0642: result.getData(pVarResult);
0643: return COM.S_OK;
0644: }
0645: switch (dispIdMember) {
0646: // indicate a false result
0647: case COM.DISPID_AMBIENT_SUPPORTSMNEMONICS:
0648: case COM.DISPID_AMBIENT_SHOWGRABHANDLES:
0649: case COM.DISPID_AMBIENT_SHOWHATCHING:
0650: if (pVarResult != 0)
0651: COM.MoveMemory(pVarResult, new int /*long*/[] { 0 },
0652: OS.PTR_SIZEOF);
0653: if (pExcepInfo != 0)
0654: COM.MoveMemory(pExcepInfo, new int /*long*/[] { 0 },
0655: OS.PTR_SIZEOF);
0656: if (pArgErr != 0)
0657: COM.MoveMemory(pArgErr, new int[] { 0 }, 4);
0658: return COM.S_FALSE;
0659:
0660: // not implemented
0661: case COM.DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
0662: case COM.DISPID_AMBIENT_BACKCOLOR:
0663: case COM.DISPID_AMBIENT_FORECOLOR:
0664: case COM.DISPID_AMBIENT_FONT:
0665: case COM.DISPID_AMBIENT_LOCALEID:
0666: case COM.DISPID_AMBIENT_SILENT:
0667: case COM.DISPID_AMBIENT_MESSAGEREFLECT:
0668: if (pVarResult != 0)
0669: COM.MoveMemory(pVarResult, new int /*long*/[] { 0 },
0670: OS.PTR_SIZEOF);
0671: if (pExcepInfo != 0)
0672: COM.MoveMemory(pExcepInfo, new int /*long*/[] { 0 },
0673: OS.PTR_SIZEOF);
0674: if (pArgErr != 0)
0675: COM.MoveMemory(pArgErr, new int[] { 0 }, 4);
0676: return COM.E_NOTIMPL;
0677:
0678: default:
0679: if (pVarResult != 0)
0680: COM.MoveMemory(pVarResult, new int /*long*/[] { 0 },
0681: OS.PTR_SIZEOF);
0682: if (pExcepInfo != 0)
0683: COM.MoveMemory(pExcepInfo, new int /*long*/[] { 0 },
0684: OS.PTR_SIZEOF);
0685: if (pArgErr != 0)
0686: COM.MoveMemory(pArgErr, new int[] { 0 }, 4);
0687: return COM.DISP_E_MEMBERNOTFOUND;
0688: }
0689: }
0690:
0691: private int OnControlInfoChanged() {
0692: int /*long*/[] ppvObject = new int /*long*/[1];
0693: if (objIUnknown.QueryInterface(COM.IIDIOleControl, ppvObject) == COM.S_OK) {
0694: IOleControl objIOleControl = new IOleControl(ppvObject[0]);
0695: // ask the control for its info in case users
0696: // need to act on it
0697: currentControlInfo = new CONTROLINFO();
0698: objIOleControl.GetControlInfo(currentControlInfo);
0699: objIOleControl.Release();
0700: }
0701: return COM.S_OK;
0702: }
0703:
0704: void onFocusIn(Event e) {
0705: if (objIOleInPlaceObject == null)
0706: return;
0707: doVerb(OLE.OLEIVERB_UIACTIVATE);
0708: if (isFocusControl())
0709: return;
0710: int /*long*/[] phwnd = new int /*long*/[1];
0711: objIOleInPlaceObject.GetWindow(phwnd);
0712: if (phwnd[0] == 0)
0713: return;
0714: OS.SetFocus(phwnd[0]);
0715: }
0716:
0717: void onFocusOut(Event e) {
0718: if (objIOleInPlaceObject != null) {
0719: /*
0720: * Bug in Windows. When IE7 loses focus and UIDeactivate()
0721: * is called, IE destroys the caret even though it is
0722: * no longer owned by IE. If focus has moved to a control
0723: * that shows a caret then the caret disappears. The fix
0724: * is to detect this case and restore the caret.
0725: */
0726: int threadId = OS.GetCurrentThreadId();
0727: GUITHREADINFO lpgui1 = new GUITHREADINFO();
0728: lpgui1.cbSize = GUITHREADINFO.sizeof;
0729: OS.GetGUIThreadInfo(threadId, lpgui1);
0730: objIOleInPlaceObject.UIDeactivate();
0731: if (lpgui1.hwndCaret != 0) {
0732: GUITHREADINFO lpgui2 = new GUITHREADINFO();
0733: lpgui2.cbSize = GUITHREADINFO.sizeof;
0734: OS.GetGUIThreadInfo(threadId, lpgui2);
0735: if (lpgui2.hwndCaret == 0
0736: && lpgui1.hwndCaret == OS.GetFocus()) {
0737: if (SWT_RESTORECARET == 0) {
0738: SWT_RESTORECARET = OS
0739: .RegisterWindowMessage(new TCHAR(0,
0740: "SWT_RESTORECARET", true));
0741: }
0742: /*
0743: * If the caret was not restored by SWT, put it back using
0744: * the information from GUITHREADINFO. Note that this will
0745: * not be correct when the caret has a bitmap. There is no
0746: * API to query the bitmap that the caret is using.
0747: */
0748: if (OS.SendMessage(lpgui1.hwndCaret,
0749: SWT_RESTORECARET, 0, 0) == 0) {
0750: int width = lpgui1.right - lpgui1.left;
0751: int height = lpgui1.bottom - lpgui1.top;
0752: OS.CreateCaret(lpgui1.hwndCaret, 0, width,
0753: height);
0754: OS.SetCaretPos(lpgui1.left, lpgui1.top);
0755: OS.ShowCaret(lpgui1.hwndCaret);
0756: }
0757: }
0758: }
0759: }
0760: }
0761:
0762: private int OnFocus(int fGotFocus) {
0763: return COM.S_OK;
0764: }
0765:
0766: protected int OnUIDeactivate(int fUndoable) {
0767: // controls don't need to do anything for
0768: // border space or menubars
0769: state = STATE_INPLACEACTIVE;
0770: return COM.S_OK;
0771: }
0772:
0773: protected int QueryInterface(int /*long*/riid,
0774: int /*long*/ppvObject) {
0775: int result = super .QueryInterface(riid, ppvObject);
0776: if (result == COM.S_OK)
0777: return result;
0778: if (riid == 0 || ppvObject == 0)
0779: return COM.E_INVALIDARG;
0780: GUID guid = new GUID();
0781: COM.MoveMemory(guid, riid, GUID.sizeof);
0782: if (COM.IsEqualGUID(guid, COM.IIDIOleControlSite)) {
0783: COM
0784: .MoveMemory(ppvObject,
0785: new int /*long*/[] { iOleControlSite
0786: .getAddress() }, OS.PTR_SIZEOF);
0787: AddRef();
0788: return COM.S_OK;
0789: }
0790: if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) {
0791: COM.MoveMemory(ppvObject, new int /*long*/[] { iDispatch
0792: .getAddress() }, OS.PTR_SIZEOF);
0793: AddRef();
0794: return COM.S_OK;
0795: }
0796: COM.MoveMemory(ppvObject, new int /*long*/[] { 0 },
0797: OS.PTR_SIZEOF);
0798: return COM.E_NOINTERFACE;
0799: }
0800:
0801: protected int Release() {
0802: int result = super .Release();
0803: if (result == 0) {
0804: for (int i = 0; i < sitePropertyIds.length; i++) {
0805: sitePropertyValues[i].dispose();
0806: }
0807: sitePropertyIds = new int[0];
0808: sitePropertyValues = new Variant[0];
0809: }
0810: return result;
0811: }
0812:
0813: protected void releaseObjectInterfaces() {
0814:
0815: disconnectEventSinks();
0816:
0817: disconnectPropertyChangeSink();
0818:
0819: super .releaseObjectInterfaces();
0820: }
0821:
0822: /**
0823: * Removes the listener.
0824: *
0825: * @param eventID the event identifier
0826: *
0827: * @param listener the listener
0828: *
0829: * @exception IllegalArgumentException <ul>
0830: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0831: * </ul>
0832: */
0833: public void removeEventListener(int eventID, OleListener listener) {
0834: checkWidget();
0835: if (listener == null)
0836: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0837:
0838: GUID riid = getDefaultEventSinkGUID(objIUnknown);
0839: if (riid != null) {
0840: removeEventListener(objIUnknown.getAddress(), riid,
0841: eventID, listener);
0842: }
0843: }
0844:
0845: /**
0846: * Removes the listener.
0847: *
0848: * @since 2.0
0849: * @deprecated - use OleControlSite.removeEventListener(OleAutomation, int, OleListener)
0850: *
0851: * @param automation the automation object that provides the event notification
0852: *
0853: * @param guid the identifier of the events COM interface
0854: *
0855: * @param eventID the event identifier
0856: *
0857: * @param listener the listener
0858: *
0859: * @exception IllegalArgumentException <ul>
0860: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0861: * </ul>
0862: */
0863: public void removeEventListener(OleAutomation automation,
0864: GUID guid, int eventID, OleListener listener) {
0865: checkWidget();
0866: if (automation == null || listener == null || guid == null)
0867: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0868: removeEventListener(automation.getAddress(), guid, eventID,
0869: listener);
0870: }
0871:
0872: /**
0873: * Removes the listener.
0874: *
0875: * @since 2.0
0876: *
0877: * @param automation the automation object that provides the event notification
0878: *
0879: * @param eventID the event identifier
0880: *
0881: * @param listener the listener
0882: *
0883: * @exception IllegalArgumentException <ul>
0884: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0885: * </ul>
0886: */
0887: public void removeEventListener(OleAutomation automation,
0888: int eventID, OleListener listener) {
0889: checkWidget();
0890: if (automation == null || listener == null)
0891: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0892: int /*long*/address = automation.getAddress();
0893: IUnknown unknown = new IUnknown(address);
0894: GUID riid = getDefaultEventSinkGUID(unknown);
0895: if (riid != null) {
0896: removeEventListener(address, riid, eventID, listener);
0897: }
0898: }
0899:
0900: void removeEventListener(int /*long*/iunknown, GUID guid,
0901: int eventID, OleListener listener) {
0902: if (listener == null || guid == null)
0903: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0904: for (int i = 0; i < oleEventSink.length; i++) {
0905: if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
0906: if (iunknown == oleEventSinkIUnknown[i]) {
0907: oleEventSink[i].removeListener(eventID, listener);
0908: if (!oleEventSink[i].hasListeners()) {
0909: //free resources associated with event sink
0910: oleEventSink[i].disconnect();
0911: oleEventSink[i].Release();
0912: int oldLength = oleEventSink.length;
0913: if (oldLength == 1) {
0914: oleEventSink = new OleEventSink[0];
0915: oleEventSinkGUID = new GUID[0];
0916: oleEventSinkIUnknown = new int /*long*/[0];
0917: } else {
0918: OleEventSink[] newOleEventSink = new OleEventSink[oldLength - 1];
0919: System.arraycopy(oleEventSink, 0,
0920: newOleEventSink, 0, i);
0921: System.arraycopy(oleEventSink, i + 1,
0922: newOleEventSink, i, oldLength - i
0923: - 1);
0924: oleEventSink = newOleEventSink;
0925:
0926: GUID[] newOleEventSinkGUID = new GUID[oldLength - 1];
0927: System.arraycopy(oleEventSinkGUID, 0,
0928: newOleEventSinkGUID, 0, i);
0929: System.arraycopy(oleEventSinkGUID, i + 1,
0930: newOleEventSinkGUID, i, oldLength
0931: - i - 1);
0932: oleEventSinkGUID = newOleEventSinkGUID;
0933:
0934: int /*long*/[] newOleEventSinkIUnknown = new int /*long*/[oldLength - 1];
0935: System.arraycopy(oleEventSinkIUnknown, 0,
0936: newOleEventSinkIUnknown, 0, i);
0937: System.arraycopy(oleEventSinkIUnknown,
0938: i + 1, newOleEventSinkIUnknown, i,
0939: oldLength - i - 1);
0940: oleEventSinkIUnknown = newOleEventSinkIUnknown;
0941: }
0942: }
0943: return;
0944: }
0945: }
0946: }
0947: }
0948:
0949: /**
0950: * Removes the listener.
0951: *
0952: * @param listener the listener
0953: *
0954: * @exception IllegalArgumentException <ul>
0955: * <li>ERROR_NULL_ARGUMENT when listener is null</li>
0956: * </ul>
0957: */
0958: public void removePropertyListener(int propertyID,
0959: OleListener listener) {
0960: if (listener == null)
0961: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0962: olePropertyChangeSink.removeListener(propertyID, listener);
0963: }
0964:
0965: public void setBackground(Color color) {
0966:
0967: super .setBackground(color);
0968:
0969: //set the background of the ActiveX Control
0970: if (objIUnknown != null) {
0971: OleAutomation oleObject = new OleAutomation(this );
0972: oleObject.setProperty(COM.DISPID_BACKCOLOR, new Variant(
0973: color.handle));
0974: oleObject.dispose();
0975: }
0976: }
0977:
0978: public void setFont(Font font) {
0979:
0980: super .setFont(font);
0981:
0982: //set the font of the ActiveX Control
0983: if (objIUnknown != null) {
0984:
0985: OleAutomation oleObject = new OleAutomation(this );
0986: Variant varDispFont = oleObject
0987: .getProperty(COM.DISPID_FONT);
0988: oleObject.dispose();
0989:
0990: if (varDispFont != null) {
0991: OleAutomation iDispFont = varDispFont.getAutomation();
0992: FontData[] fdata = font.getFontData();
0993: iDispFont.setProperty(COM.DISPID_FONT_NAME,
0994: new Variant(fdata[0].getName()));
0995: iDispFont.setProperty(COM.DISPID_FONT_SIZE,
0996: new Variant(fdata[0].getHeight()));
0997: iDispFont.setProperty(COM.DISPID_FONT_ITALIC,
0998: new Variant(fdata[0].getStyle() & SWT.ITALIC));
0999: //iDispFont.setProperty(COM.DISPID_FONT_CHARSET, new Variant(fdata[0].getCharset));
1000: iDispFont.setProperty(COM.DISPID_FONT_BOLD,
1001: new Variant((fdata[0].getStyle() & SWT.BOLD)));
1002: iDispFont.dispose();
1003: }
1004: }
1005:
1006: return;
1007: }
1008:
1009: public void setForeground(Color color) {
1010:
1011: super .setForeground(color);
1012:
1013: //set the foreground of the ActiveX Control
1014: if (objIUnknown != null) {
1015: OleAutomation oleObject = new OleAutomation(this );
1016: oleObject.setProperty(COM.DISPID_FORECOLOR, new Variant(
1017: color.handle));
1018: oleObject.dispose();
1019: }
1020: }
1021:
1022: /**
1023: * Sets the control site property specified by the dispIdMember to a new value.
1024: * The value will be disposed by the control site when it is no longer required
1025: * using Variant.dispose. Passing a value of null will clear the dispId value.
1026: *
1027: * @param dispId the ID of the property as specified by the IDL of the ActiveX Control
1028: * @param value The new value for the property as expressed in a Variant.
1029: *
1030: * @since 2.1
1031: */
1032: public void setSiteProperty(int dispId, Variant value) {
1033: for (int i = 0; i < sitePropertyIds.length; i++) {
1034: if (sitePropertyIds[i] == dispId) {
1035: if (sitePropertyValues[i] != null) {
1036: sitePropertyValues[i].dispose();
1037: }
1038: if (value != null) {
1039: sitePropertyValues[i] = value;
1040: } else {
1041: int oldLength = sitePropertyIds.length;
1042: int[] newSitePropertyIds = new int[oldLength - 1];
1043: Variant[] newSitePropertyValues = new Variant[oldLength - 1];
1044: System.arraycopy(sitePropertyIds, 0,
1045: newSitePropertyIds, 0, i);
1046: System.arraycopy(sitePropertyIds, i + 1,
1047: newSitePropertyIds, i, oldLength - i - 1);
1048: System.arraycopy(sitePropertyValues, 0,
1049: newSitePropertyValues, 0, i);
1050: System
1051: .arraycopy(sitePropertyValues, i + 1,
1052: newSitePropertyValues, i, oldLength
1053: - i - 1);
1054: sitePropertyIds = newSitePropertyIds;
1055: sitePropertyValues = newSitePropertyValues;
1056: }
1057: return;
1058: }
1059: }
1060: int oldLength = sitePropertyIds.length;
1061: int[] newSitePropertyIds = new int[oldLength + 1];
1062: Variant[] newSitePropertyValues = new Variant[oldLength + 1];
1063: System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0,
1064: oldLength);
1065: System.arraycopy(sitePropertyValues, 0, newSitePropertyValues,
1066: 0, oldLength);
1067: newSitePropertyIds[oldLength] = dispId;
1068: newSitePropertyValues[oldLength] = value;
1069: sitePropertyIds = newSitePropertyIds;
1070: sitePropertyValues = newSitePropertyValues;
1071: }
1072: }
|