1 /******************************************************************************* 2 * Copyright (c) 2000, 2007 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.ole.win32.OleEventSink; 14 15 import org.eclipse.swt.SWT; 16 import org.eclipse.swt.SWTException; 17 import org.eclipse.swt.internal.ole.win32.COM; 18 import org.eclipse.swt.internal.ole.win32.extras; 19 import org.eclipse.swt.internal.ole.win32.OAIDL; 20 import org.eclipse.swt.internal.ole.win32.ifs; 21 22 import org.eclipse.swt.ole.win32.OleControlSite; 23 import org.eclipse.swt.ole.win32.OleEventTable; 24 import org.eclipse.swt.ole.win32.OleListener; 25 import org.eclipse.swt.ole.win32.OleEvent; 26 import org.eclipse.swt.ole.win32.OLE; 27 import org.eclipse.swt.ole.win32.Variant; 28 29 final class OleEventSink 30 { 31 private OleControlSite widget; 32 33 private _DispatchImpl iDispatch; 34 private int refCount; 35 36 private IUnknown objIUnknown; 37 private int eventCookie; 38 private GUID* eventGuid; 39 40 private OleEventTable eventTable; 41 42 this(OleControlSite widget, IUnknown iUnknown, GUID* riid) { 43 44 this.widget = widget; 45 this.eventGuid = riid; 46 this.objIUnknown = iUnknown; 47 48 createCOMInterfaces(); 49 } 50 51 void connect () { 52 IConnectionPointContainer cpc; 53 if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) { 54 IConnectionPoint cp; 55 if (cpc.FindConnectionPoint(eventGuid, &cp) is COM.S_OK) { 56 uint pCookie; 57 if (cp.Advise(iDispatch, &pCookie) is COM.S_OK) 58 eventCookie = pCookie; 59 cp.Release(); 60 } 61 cpc.Release(); 62 } 63 } 64 void addListener(int eventID, OleListener listener) { 65 if (listener is null) OLE.error (SWT.ERROR_NULL_ARGUMENT); 66 if (eventTable is null) eventTable = new OleEventTable (); 67 eventTable.hook(eventID, listener); 68 } 69 int AddRef() { 70 refCount++; 71 return refCount; 72 } 73 private void createCOMInterfaces() { 74 iDispatch = new _DispatchImpl(this); 75 } 76 void disconnect() { 77 // disconnect event sink 78 if (eventCookie !is 0 && objIUnknown !is null) { 79 IConnectionPointContainer cpc; 80 if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) { 81 IConnectionPoint cp; 82 if (cpc.FindConnectionPoint(eventGuid, &cp) is COM.S_OK) { 83 if (cp.Unadvise(eventCookie) is COM.S_OK) { 84 eventCookie = 0; 85 } 86 cp.Release(); 87 } 88 cpc.Release(); 89 } 90 } 91 } 92 private void disposeCOMInterfaces() { 93 iDispatch = null; 94 } 95 96 private HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr) 97 { 98 if (eventTable is null || !eventTable.hooks(dispIdMember)) return COM.S_OK; 99 100 // Construct an array of the parameters that are passed in 101 // Note: parameters are passed in reverse order - here we will correct the order 102 Variant[] eventInfo = null; 103 if (pDispParams !is null) { 104 DISPPARAMS* dispParams = new DISPPARAMS(); 105 COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof); 106 eventInfo = new Variant[dispParams.cArgs]; 107 int size = Variant.sizeof; 108 int offset = (dispParams.cArgs - 1) * size; 109 110 for (int j = 0; j < dispParams.cArgs; j++){ 111 eventInfo[j] = new Variant(); 112 eventInfo[j].setData(dispParams.rgvarg + offset); 113 offset = offset - size; 114 } 115 } 116 117 OleEvent event = new OleEvent(); 118 event.arguments = eventInfo; 119 notifyListener(dispIdMember,event); 120 return COM.S_OK; 121 } 122 /** 123 * Notify listeners of an event. 124 * <p> 125 * This method notifies all listeners that an event 126 * has occurred. 127 * 128 * @param eventType the desired SWT event 129 * @param event the event data 130 * 131 * @exception IllegalArgumentException <ul> 132 * <li>ERROR_NULL_ARGUMENT when handler is null</li> 133 * </ul> 134 * @exception SWTException <ul> 135 * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li> 136 * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li> 137 * </ul> 138 */ 139 private void notifyListener (int eventType, OleEvent event) { 140 if (event is null) OLE.error (SWT.ERROR_NULL_ARGUMENT); 141 if (eventTable is null) return; 142 event.type = eventType; 143 event.widget = widget; 144 eventTable.sendEvent (event); 145 } 146 147 private HRESULT QueryInterface(REFCIID riid, void ** ppvObject) { 148 149 if (riid is null || ppvObject is null) 150 return COM.E_INVALIDARG; 151 152 if ( COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDispatch) || 153 COM.IsEqualGUID(riid, eventGuid)) { 154 *ppvObject = cast(void*)cast(IDispatch)iDispatch; 155 AddRef(); 156 return OLE.S_OK; 157 } 158 159 *ppvObject = null; 160 return COM.E_NOINTERFACE; 161 } 162 int Release() { 163 refCount--; 164 if (refCount is 0) { 165 disposeCOMInterfaces(); 166 } 167 168 return refCount; 169 } 170 void removeListener(int eventID, OleListener listener) { 171 if (listener is null) OLE.error (SWT.ERROR_NULL_ARGUMENT); 172 if (eventTable is null) return; 173 eventTable.unhook (eventID, listener); 174 } 175 bool hasListeners() { 176 return eventTable.hasEntries(); 177 } 178 } 179 180 private class _DispatchImpl : IDispatch { 181 182 OleEventSink parent; 183 this(OleEventSink sink) { parent = sink;} 184 extern (Windows) : 185 HRESULT QueryInterface(REFCIID riid, void ** ppvObject){ 186 return parent.QueryInterface(riid, ppvObject); 187 } 188 ULONG AddRef() { return parent.AddRef(); } 189 ULONG Release() { return parent.Release(); } 190 HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; } 191 HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; } 192 HRESULT GetIDsOfNames(REFCIID riid, LPCOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; } 193 HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr){ 194 return parent.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 195 } 196 } 197