1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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.OleControlSite;
14 
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.SWTError;
17 import org.eclipse.swt.SWTException;
18 import org.eclipse.swt.graphics.Color;
19 import org.eclipse.swt.graphics.Font;
20 import org.eclipse.swt.graphics.FontData;
21 import org.eclipse.swt.graphics.Device;
22 import org.eclipse.swt.internal.ole.win32.COM;
23 import org.eclipse.swt.internal.ole.win32.COMTYPES;
24 import org.eclipse.swt.internal.ole.win32.extras;
25 import org.eclipse.swt.internal.ole.win32.ifs;
26 import org.eclipse.swt.internal.ole.win32.OAIDL;
27 import org.eclipse.swt.internal.ole.win32.OBJIDL;
28 import org.eclipse.swt.internal.win32.OS;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.swt.widgets.Event;
31 
32 import org.eclipse.swt.ole.win32.OleClientSite;
33 import org.eclipse.swt.ole.win32.OleEventSink;
34 import org.eclipse.swt.ole.win32.OlePropertyChangeSink;
35 import org.eclipse.swt.ole.win32.OleListener;
36 import org.eclipse.swt.ole.win32.OleAutomation;
37 import org.eclipse.swt.ole.win32.Variant;
38 import org.eclipse.swt.ole.win32.OLE;
39 
40 import java.lang.all;
41 
42 /**
43  * OleControlSite provides a site to manage an embedded ActiveX Control within a container.
44  *
45  * <p>In addition to the behaviour provided by OleClientSite, this object provides the following:
46  * <ul>
47  *  <li>events from the ActiveX control
48  *  <li>notification of property changes from the ActiveX control
49  *  <li>simplified access to well known properties of the ActiveX Control (e.g. font, background color)
50  *  <li>expose ambient properties of the container to the ActiveX Control
51  * </ul>
52  *
53  * <p>This object implements the OLE Interfaces IOleControlSite, IDispatch, and IPropertyNotifySink.
54  *
55  * <p>Note that although this class is a subclass of <code>Composite</code>,
56  * it does not make sense to add <code>Control</code> children to it,
57  * or set a layout on it.
58  * </p><p>
59  * <dl>
60  *  <dt><b>Styles</b> <dd>BORDER
61  *  <dt><b>Events</b> <dd>Dispose, Move, Resize
62  * </dl>
63  *
64  * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
65  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
66  */
67 public class OleControlSite : OleClientSite
68 {
69     // interfaces for this container
70     private _IOleControlSiteImpl iOleControlSite;
71     private _IDispatchImpl       iDispatch;
72 
73     // supporting Property Change attributes
74     private OlePropertyChangeSink olePropertyChangeSink;
75 
76     // supporting Event Sink attributes
77     private OleEventSink[] oleEventSink;
78     private GUID*[] oleEventSinkGUID;
79     private IUnknown[] oleEventSinkIUnknown;
80 
81     // supporting information for the Control COM object
82     private CONTROLINFO* currentControlInfo;
83     private int[] sitePropertyIds;
84     private Variant[] sitePropertyValues;
85 
86     // work around for IE destroying the caret
87     static int SWT_RESTORECARET;
88 
89     override protected int AddRef() {
90         return super.AddRef();
91     }
92 /**
93  * Create an OleControlSite child widget using style bits
94  * to select a particular look or set of properties.
95  *
96  * @param parent a composite widget; must be an OleFrame
97  * @param style the bitwise OR'ing of widget styles
98  * @param progId the unique program identifier which has been registered for this ActiveX Control;
99  *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
100  *               in the registry for this Control (for example, the VersionIndependentProgID for
101  *               Internet Explorer is Shell.Explorer)
102  *
103  * @exception IllegalArgumentException <ul>
104  *     <li>ERROR_NULL_ARGUMENT when the parent is null
105  *</ul>
106  * @exception SWTException <ul>
107  *     <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
108  *     <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
109  *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
110  *     <li>ERROR_CANNOT_ACCESS_CLASSFACTORY when Class Factory could not be found
111  *     <li>ERROR_CANNOT_CREATE_LICENSED_OBJECT when failed to create a licensed OLE Object
112  * </ul>
113  */
114 public this(Composite parent, int style, String progId) {
115     super(parent, style);
116     try {
117 
118         // check for licensing
119         appClsid = getClassID(progId);
120         if (appClsid is null) OLE.error(__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
121 
122         BSTR licinfo = getLicenseInfo(appClsid);
123         if (licinfo is null) {
124 
125             // Open a storage object
126             tempStorage = createTempStorage();
127 
128             // Create ole object with storage object
129             HRESULT result = COM.OleCreate(appClsid, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
130             if (result !is COM.S_OK)
131                 OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
132 
133         } else {
134             // Prepare the ClassFactory
135             try {
136                 IClassFactory2 classFactory;
137                 HRESULT result = COM.CoGetClassObject(appClsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, null, &COM.IIDIClassFactory2, cast(void**)&classFactory);
138                 if (result !is COM.S_OK) {
139                     OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_ACCESS_CLASSFACTORY, result);
140                 }
141                 // Create Com Object
142                 result = classFactory.CreateInstanceLic(null, null, &COM.IIDIUnknown, licinfo, cast(void**)&objIUnknown);
143                 classFactory.Release();
144                 if (result !is COM.S_OK)
145                     OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_LICENSED_OBJECT, result);
146             } finally {
147                 COM.SysFreeString(licinfo);
148             }
149 
150             // Prepare a storage medium
151             IPersistStorage persist;
152             if (objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&persist) is COM.S_OK) {
153                 tempStorage = createTempStorage();
154                 persist.InitNew(tempStorage);
155                 persist.Release();
156             }
157         }
158 
159         // Init sinks
160         addObjectReferences();
161 
162         // Init site properties
163         setSiteProperty(COM.DISPID_AMBIENT_USERMODE, new Variant(true));
164         setSiteProperty(COM.DISPID_AMBIENT_UIDEAD, new Variant(false));
165 
166         if (COM.OleRun(objIUnknown) is OLE.S_OK) state= STATE_RUNNING;
167 
168     } catch (SWTError e) {
169         dispose();
170         disposeCOMInterfaces();
171         throw e;
172     }
173 }
174 /**
175  * Adds the listener to receive events.
176  *
177  * @param eventID the id of the event
178  *
179  * @param listener the listener
180  *
181  * @exception IllegalArgumentException <ul>
182  *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
183  * </ul>
184  */
185 public void addEventListener(int eventID, OleListener listener) {
186     if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
187     GUID* riid = getDefaultEventSinkGUID(objIUnknown);
188     if (riid !is null) {
189         addEventListener(objIUnknown, riid, eventID, listener);
190     }
191 }
192 
193 
194 static GUID* getDefaultEventSinkGUID(IUnknown unknown) {
195     // get Event Sink I/F from IProvideClassInfo2
196     IProvideClassInfo2 pci2;
197     if (unknown.QueryInterface(&COM.IIDIProvideClassInfo2, cast(void**)&pci2) is COM.S_OK) {
198         GUID* riid = new GUID();
199         HRESULT result = pci2.GetGUID(COM.GUIDKIND_DEFAULT_SOURCE_DISP_IID, riid);
200         pci2.Release();
201         if (result is COM.S_OK) return riid;
202     }
203 
204     // get Event Sink I/F from IProvideClassInfo
205     IProvideClassInfo pci;
206     if (unknown.QueryInterface(&COM.IIDIProvideClassInfo, cast(void**)&pci) is COM.S_OK) {
207         ITypeInfo classInfo;
208         ITypeInfo eventInfo;
209         HRESULT result = pci.GetClassInfo(&classInfo);
210         pci.Release();
211 
212         if (result is COM.S_OK && classInfo !is null) {
213             TYPEATTR* typeAttribute;
214             result = classInfo.GetTypeAttr(&typeAttribute);
215             if (result is COM.S_OK  && typeAttribute !is null) {
216                 int implMask = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE | COM.IMPLTYPEFLAG_FRESTRICTED;
217                 int implBits = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE;
218 
219                 for (uint i = 0; i < typeAttribute.cImplTypes; i++) {
220                     int pImplTypeFlags;
221                     if (classInfo.GetImplTypeFlags(i, &pImplTypeFlags) is COM.S_OK) {
222                         if ((pImplTypeFlags & implMask) is implBits) {
223                             uint pRefType;
224                             if (classInfo.GetRefTypeOfImplType(i, &pRefType) is COM.S_OK) {
225                                 classInfo.GetRefTypeInfo(pRefType, &eventInfo);
226                             }
227                         }
228                     }
229                 }
230                 classInfo.ReleaseTypeAttr(typeAttribute);
231             }
232             classInfo.Release();
233 
234             if (eventInfo !is null) {
235                 TYPEATTR* ppTypeAttr;
236                 result = eventInfo.GetTypeAttr(&ppTypeAttr);
237                 GUID* riid = null;
238                 if (result is COM.S_OK && ppTypeAttr !is null) {
239                     riid = new GUID();
240                     *riid = ppTypeAttr.guid;
241                     eventInfo.ReleaseTypeAttr(ppTypeAttr);
242                 }
243                 eventInfo.Release();
244                 return riid;
245             }
246         }
247     }
248     return null;
249 }
250 
251 /**
252  * Adds the listener to receive events.
253  *
254  * @since 2.0
255  *
256  * @param automation the automation object that provides the event notification
257  * @param eventID the id of the event
258  * @param listener the listener
259  *
260  * @exception IllegalArgumentException <ul>
261  *     <li>ERROR_NULL_ARGUMENT when listener is null</li>
262  * </ul>
263  */
264 public void addEventListener(OleAutomation automation, int eventID, OleListener listener) {
265     if (listener is null || automation is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
266     IUnknown unknown = automation.getAddress();
267     GUID* riid = getDefaultEventSinkGUID(unknown);
268     if (riid !is null) {
269         addEventListener(unknown, riid, eventID, listener);
270     }
271 
272 }
273 /**
274  * Adds the listener to receive events.
275  *
276  * @since 3.2
277  *
278  * @param automation the automation object that provides the event notification
279  * @param eventSinkId the GUID of the event sink
280  * @param eventID the id of the event
281  * @param listener the listener
282  *
283  * @exception IllegalArgumentException <ul>
284  *     <li>ERROR_NULL_ARGUMENT when listener is null</li>
285  * </ul>
286  */
287 public void addEventListener(OleAutomation automation, String eventSinkId, int eventID, OleListener listener) {
288     if (listener is null || automation is null || eventSinkId is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
289     auto address = automation.getAddress();
290     if (address is null) return;
291     String16 buffer = StrToWCHARs(0,eventSinkId,true);
292     GUID* guid = new GUID();
293     if (COM.IIDFromString(buffer.ptr, guid) !is COM.S_OK) return;
294     addEventListener(address, guid, eventID, listener);
295 }
296 
297 void addEventListener(IUnknown iunknown, GUID* guid, int eventID, OleListener listener) {
298     if (listener is null || iunknown is null || guid is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
299     // have we connected to this kind of event sink before?
300     int index = -1;
301     for (int i = 0; i < oleEventSinkGUID.length; i++) {
302         if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
303             if (iunknown is oleEventSinkIUnknown[i]) {
304                 index = i;
305                 break;
306             }
307         }
308     }
309     if (index !is -1) {
310         oleEventSink[index].addListener(eventID, listener);
311     } else {
312         int oldLength = cast(int)/*64bit*/oleEventSink.length;
313 
314         oleEventSink ~= new OleEventSink(this, iunknown, guid);
315         oleEventSinkGUID ~= guid;
316         oleEventSinkIUnknown ~= iunknown;
317 
318         oleEventSink[oldLength].AddRef();
319         oleEventSink[oldLength].connect();
320         oleEventSink[oldLength].addListener(eventID, listener);
321 
322     }
323 }
324 override
325 protected void addObjectReferences() {
326 
327     super.addObjectReferences();
328 
329     // Get property change notification from control
330     connectPropertyChangeSink();
331 
332     // Get access to the Control object
333     IOleControl objIOleControl;
334     if (objIUnknown.QueryInterface(&COM.IIDIOleControl, cast(void**)&objIOleControl) is COM.S_OK) {
335         // ask the control for its info in case users
336         // need to act on it
337         currentControlInfo = new CONTROLINFO();
338         objIOleControl.GetControlInfo(currentControlInfo);
339         objIOleControl.Release();
340     }
341 }
342 /**
343  * Adds the listener to receive events.
344  *
345  * @param propertyID the identifier of the property
346  * @param listener the listener
347  *
348  * @exception IllegalArgumentException <ul>
349  *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
350  * </ul>
351  */
352 public void addPropertyListener(int propertyID, OleListener listener) {
353     if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
354     olePropertyChangeSink.addListener(propertyID, listener);
355 }
356 
357 private void connectPropertyChangeSink() {
358     olePropertyChangeSink = new OlePropertyChangeSink(this);
359     olePropertyChangeSink.AddRef();
360     olePropertyChangeSink.connect(objIUnknown);
361 }
362 override
363 protected void createCOMInterfaces () {
364     super.createCOMInterfaces();
365     iOleControlSite = new _IOleControlSiteImpl(this);
366     iDispatch = new _IDispatchImpl(this);
367 }
368 private void disconnectEventSinks() {
369 
370     for (int i = 0; i < oleEventSink.length; i++) {
371         OleEventSink sink = oleEventSink[i];
372         sink.disconnect();
373         sink.Release();
374     }
375     oleEventSink = null;
376     oleEventSinkGUID = null;
377     oleEventSinkIUnknown = null;
378 }
379 private void disconnectPropertyChangeSink() {
380 
381     if (olePropertyChangeSink !is null) {
382         olePropertyChangeSink.disconnect(objIUnknown);
383         olePropertyChangeSink.Release();
384     }
385     olePropertyChangeSink = null;
386 }
387 override
388 protected void disposeCOMInterfaces() {
389     super.disposeCOMInterfaces();
390     iOleControlSite = null;
391     iDispatch = null;
392 }
393 override
394 public Color getBackground () {
395 
396     if (objIUnknown !is null) {
397         // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
398         OleAutomation oleObject= new OleAutomation(this);
399         Variant varBackColor = oleObject.getProperty(COM.DISPID_BACKCOLOR);
400         oleObject.dispose();
401 
402         if (varBackColor !is null){
403             COLORREF colorRef;
404             if (COM.OleTranslateColor(varBackColor.getInt(), getDisplay().hPalette, &colorRef) is COM.S_OK)
405                 return Color.win32_new(getDisplay(), colorRef);
406         }
407     }
408 
409     return super.getBackground();
410 }
411 override
412 public Font getFont () {
413 
414     if (objIUnknown !is null) {
415         OleAutomation oleObject= new OleAutomation(this);
416         Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
417         oleObject.dispose();
418 
419         if (varDispFont !is null){
420             OleAutomation iDispFont = varDispFont.getAutomation();
421             Variant lfFaceName = iDispFont.getProperty(COM.DISPID_FONT_NAME);
422             Variant lfHeight   = iDispFont.getProperty(COM.DISPID_FONT_SIZE);
423             Variant lfItalic   = iDispFont.getProperty(COM.DISPID_FONT_ITALIC);
424             //Variant lfCharSet  = iDispFont.getProperty(COM.DISPID_FONT_CHARSET);
425             Variant lfBold     = iDispFont.getProperty(COM.DISPID_FONT_BOLD);
426             iDispFont.dispose();
427 
428             if (lfFaceName !is null &&
429                 lfHeight !is null &&
430                 lfItalic !is null &&
431                 lfBold !is null){
432                 int style = 3 * lfBold.getInt() + 2 * lfItalic.getInt();
433                 Device dev = getShell().getDisplay();
434                 Font font = new Font(dev, lfFaceName.getString(), lfHeight.getInt(), style);
435                 return font;
436             }
437         }
438     }
439 
440     return super.getFont();
441 }
442 override
443 public Color getForeground () {
444 
445     if (objIUnknown !is null) {
446         // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
447         OleAutomation oleObject= new OleAutomation(this);
448         Variant varForeColor = oleObject.getProperty(COM.DISPID_FORECOLOR);
449         oleObject.dispose();
450 
451         if (varForeColor !is null){
452             COLORREF colorRef;
453             if (COM.OleTranslateColor(varForeColor.getInt(), getDisplay().hPalette, &colorRef) is COM.S_OK)
454                 return Color.win32_new(getDisplay(), colorRef);
455         }
456     }
457 
458     return super.getForeground();
459 }
460 protected BSTR getLicenseInfo(GUID* clsid) {
461     IClassFactory2 classFactory;
462     if (COM.CoGetClassObject(clsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, null, &COM.IIDIClassFactory2, cast(void**)&classFactory) !is COM.S_OK) {
463         return null;
464     }
465     LICINFO licinfo;
466     if (classFactory.GetLicInfo(&licinfo) !is COM.S_OK) {
467         classFactory.Release();
468         return null;
469     }
470     BSTR pBstrKey;
471     if (licinfo.fRuntimeKeyAvail) {
472         if (classFactory.RequestLicKey(0, &pBstrKey) is COM.S_OK) {
473             classFactory.Release();
474             return pBstrKey;
475         }
476     }
477     classFactory.Release();
478     return null;
479 }
480 /**
481  *
482  * Get the control site property specified by the dispIdMember, or
483  * <code>null</code> if the dispId is not recognised.
484  *
485  * @param dispId the dispId
486  *
487  * @return the property value or <code>null</code>
488  * 
489  * @since 2.1
490  */
491 public Variant getSiteProperty(int dispId){
492     for (int i = 0; i < sitePropertyIds.length; i++) {
493         if (sitePropertyIds[i] is dispId) {
494             return sitePropertyValues[i];
495         }
496     }
497     return null;
498 }
499 override
500 protected HRESULT GetWindow(HWND* phwnd) {
501 
502     if (phwnd is null)
503         return COM.E_INVALIDARG;
504     if (frame is null) {
505         *phwnd = null;
506         return COM.E_NOTIMPL;
507     }
508 
509     // Copy the Window's handle into the memory passed in
510     *phwnd = handle;
511     return COM.S_OK;
512 }
513 
514 private HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD dwFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* pArgErr) {
515     int nullv = 0;
516     if (pVarResult is null || dwFlags !is COM.DISPATCH_PROPERTYGET) {
517         if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
518         if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
519         return COM.DISP_E_MEMBERNOTFOUND;
520     }
521     Variant result = getSiteProperty(dispIdMember);
522     if (result !is null) {
523         if (pVarResult !is null) result.getData(pVarResult);
524         return COM.S_OK;
525     }
526     switch (dispIdMember) {
527             // indicate a false result
528         case COM.DISPID_AMBIENT_SUPPORTSMNEMONICS :
529         case COM.DISPID_AMBIENT_SHOWGRABHANDLES :
530         case COM.DISPID_AMBIENT_SHOWHATCHING :
531             if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
532             if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
533             if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
534             return COM.S_FALSE;
535 
536             // not implemented
537         case COM.DISPID_AMBIENT_OFFLINEIFNOTCONNECTED :
538         case COM.DISPID_AMBIENT_BACKCOLOR :
539         case COM.DISPID_AMBIENT_FORECOLOR :
540         case COM.DISPID_AMBIENT_FONT :
541         case COM.DISPID_AMBIENT_LOCALEID :
542         case COM.DISPID_AMBIENT_SILENT :
543         case COM.DISPID_AMBIENT_MESSAGEREFLECT :
544             if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
545             if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
546             if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
547             return COM.E_NOTIMPL;
548 
549         default :
550             if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
551             if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
552             if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
553             return COM.DISP_E_MEMBERNOTFOUND;
554     }
555 }
556 private int OnControlInfoChanged() {
557     IOleControl objIOleControl;
558     if (objIUnknown.QueryInterface(&COM.IIDIOleControl, cast(void**)&objIOleControl ) is COM.S_OK) {
559         // ask the control for its info in case users
560         // need to act on it
561         currentControlInfo = new CONTROLINFO();
562         objIOleControl.GetControlInfo(currentControlInfo);
563         objIOleControl.Release();
564     }
565     return COM.S_OK;
566 }
567 override
568 void onFocusIn(Event e) {
569     if (objIOleInPlaceObject is null) return;
570     doVerb(OLE.OLEIVERB_UIACTIVATE);
571     if (isFocusControl()) return;
572     HWND phwnd;
573     objIOleInPlaceObject.GetWindow(&phwnd);
574     if (phwnd is null) return;
575     OS.SetFocus(phwnd);
576 }
577 override
578 void onFocusOut(Event e) {
579     if (objIOleInPlaceObject !is null) {
580         /*
581         * Bug in Windows.  When IE7 loses focus and UIDeactivate()
582         * is called, IE destroys the caret even though it is
583         * no longer owned by IE.  If focus has moved to a control
584         * that shows a caret then the caret disappears.  The fix
585         * is to detect this case and restore the caret.
586         */
587         auto threadId = OS.GetCurrentThreadId();
588         GUITHREADINFO* lpgui1 = new GUITHREADINFO();
589         lpgui1.cbSize = GUITHREADINFO.sizeof;
590         OS.GetGUIThreadInfo(threadId, lpgui1);
591         objIOleInPlaceObject.UIDeactivate();
592         if (lpgui1.hwndCaret !is null) {
593             GUITHREADINFO* lpgui2 = new GUITHREADINFO();
594             lpgui2.cbSize = GUITHREADINFO.sizeof;
595             OS.GetGUIThreadInfo(threadId, lpgui2);
596             if (lpgui2.hwndCaret is null && lpgui1.hwndCaret is OS.GetFocus()) {
597                 if (SWT_RESTORECARET is 0) {
598                     SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz (0, "SWT_RESTORECARET"));
599                 }
600                 /*
601                 * If the caret was not restored by SWT, put it back using
602                 * the information from GUITHREADINFO.  Note that this will
603                 * not be correct when the caret has a bitmap.  There is no
604                 * API to query the bitmap that the caret is using.
605                 */
606                 if (OS.SendMessage (lpgui1.hwndCaret, SWT_RESTORECARET, 0, 0) is 0) {
607                     int width = lpgui1.rcCaret.right - lpgui1.rcCaret.left;
608                     int height = lpgui1.rcCaret.bottom - lpgui1.rcCaret.top;
609                     OS.CreateCaret (lpgui1.hwndCaret, null, width, height);
610                     OS.SetCaretPos (lpgui1.rcCaret.left, lpgui1.rcCaret.top);
611                     OS.ShowCaret (lpgui1.hwndCaret);
612                 }
613             }
614         }
615     }
616 }
617 private int OnFocus(int fGotFocus) {
618     return COM.S_OK;
619 }
620 protected int OnUIDeactivate(int fUndoable) {
621     // controls don't need to do anything for
622     // border space or menubars
623     state = STATE_INPLACEACTIVE;
624     return COM.S_OK;
625 }
626 override protected HRESULT QueryInterface(REFCIID riid, void ** ppvObject) {
627     int nullv = 0;
628     int result = super.QueryInterface(riid, ppvObject);
629     if (result is COM.S_OK)
630         return result;
631     if (riid is null || ppvObject is null)
632         return COM.E_INVALIDARG;
633     GUID oGuid = *riid;
634     GUID* guid = &oGuid;
635     //COM.MoveMemory(&guid, riid, GUID.sizeof);
636     if (COM.IsEqualGUID(guid, &COM.IIDIOleControlSite)) {
637         *ppvObject = cast(void*)cast(IOleControlSite)iOleControlSite;
638         AddRef();
639         return COM.S_OK;
640     }
641     if (COM.IsEqualGUID(guid, &COM.IIDIDispatch)) {
642         *ppvObject = cast(void*)cast(IDispatch)iDispatch;
643         AddRef();
644         return COM.S_OK;
645     }
646     *ppvObject = null;
647     return COM.E_NOINTERFACE;
648 }
649 override
650 protected int Release() {
651     int result = super.Release();
652     if (result is 0) {
653         for (int i = 0; i < sitePropertyIds.length; i++) {
654             sitePropertyValues[i].dispose();
655         }
656         sitePropertyIds = null;
657         sitePropertyValues = null;
658     }
659     return result;
660 }
661 override
662 protected void releaseObjectInterfaces() {
663 
664     disconnectEventSinks();
665 
666     disconnectPropertyChangeSink();
667 
668     super.releaseObjectInterfaces();
669 }
670 /**
671  * Removes the listener.
672  *
673  * @param eventID the event identifier
674  *
675  * @param listener the listener which should no longer be notified
676  *
677  * @exception IllegalArgumentException <ul>
678  *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
679  * </ul>
680  */
681 public void removeEventListener(int eventID, OleListener listener) {
682     checkWidget();
683     if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
684 
685     GUID* riid = getDefaultEventSinkGUID(objIUnknown);
686     if (riid !is null) {
687         removeEventListener(objIUnknown, riid, eventID, listener);
688     }
689 }
690 /**
691  * Removes the listener.
692  *
693  * @since 2.0
694  * @deprecated - use OleControlSite.removeEventListener(OleAutomation, int, OleListener)
695  *
696  * @param automation the automation object that provides the event notification
697  *
698  * @param guid the identifier of the events COM interface
699  *
700  * @param eventID the event identifier
701  *
702  * @param listener the listener
703  *
704  * @exception IllegalArgumentException <ul>
705  *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
706  * </ul>
707  */
708 public void removeEventListener(OleAutomation automation, GUID* guid, int eventID, OleListener listener) {
709     checkWidget();
710     if (automation is null || listener is null || guid is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
711     removeEventListener(automation.getAddress(), guid, eventID, listener);
712 }
713 /**
714  * Removes the listener.
715  *
716  * @param automation the automation object that provides the event notification
717  * @param eventID the event identifier
718  * @param listener the listener which should no longer be notified
719  *
720  * @exception IllegalArgumentException <ul>
721  *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
722  * </ul>
723  * 
724  * @since 2.0
725  */
726 public void removeEventListener(OleAutomation automation, int eventID, OleListener listener) {
727     checkWidget();
728     if (automation is null || listener is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
729     auto unknown = automation.getAddress();
730     GUID* riid = getDefaultEventSinkGUID(unknown);
731     if (riid !is null) {
732         removeEventListener(unknown, riid, eventID, listener);
733     }
734 }
735 void removeEventListener(IUnknown iunknown, GUID* guid, int eventID, OleListener listener) {
736     if (listener is null || guid is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
737     for (int i = 0; i < oleEventSink.length; i++) {
738         if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
739             if (iunknown is oleEventSinkIUnknown[i]) {
740                 oleEventSink[i].removeListener(eventID, listener);
741                 if (!oleEventSink[i].hasListeners()) {
742                     //free resources associated with event sink
743                     oleEventSink[i].disconnect();
744                     oleEventSink[i].Release();
745                     int oldLength = cast(int)/*64bit*/oleEventSink.length;
746                     if (oldLength is 1) {
747                         oleEventSink = null;
748                         oleEventSinkGUID = null;
749                         oleEventSinkIUnknown = null;
750                     } else {
751                         OleEventSink[] newOleEventSink = new OleEventSink[oldLength - 1];
752                         System.arraycopy(oleEventSink, 0, newOleEventSink, 0, i);
753                         System.arraycopy(oleEventSink, i + 1, newOleEventSink, i, oldLength - i - 1);
754                         oleEventSink = newOleEventSink;
755 
756                         GUID*[] newOleEventSinkGUID = new GUID*[oldLength - 1];
757                         SimpleType!(GUID*).arraycopy(oleEventSinkGUID, 0, newOleEventSinkGUID, 0, i);
758                         SimpleType!(GUID*).arraycopy(oleEventSinkGUID, i + 1, newOleEventSinkGUID, i, oldLength - i - 1);
759                         oleEventSinkGUID = newOleEventSinkGUID;
760 
761                         IUnknown[] newOleEventSinkIUnknown = new IUnknown[oldLength - 1];
762                         SimpleType!(IUnknown).arraycopy(oleEventSinkIUnknown, 0, newOleEventSinkIUnknown, 0, i);
763                         SimpleType!(IUnknown).arraycopy(oleEventSinkIUnknown, i + 1, newOleEventSinkIUnknown, i, oldLength - i - 1);
764                         oleEventSinkIUnknown = newOleEventSinkIUnknown;
765                     }
766                 }
767                 return;
768             }
769         }
770     }
771 }
772 /**
773  * Removes the listener.
774  *
775  * @param propertyID the identifier of the property
776  * @param listener the listener which should no longer be notified
777  *
778  * @exception IllegalArgumentException <ul>
779  *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
780  * </ul>
781  */
782 public void removePropertyListener(int propertyID, OleListener listener) {
783     if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
784     olePropertyChangeSink.removeListener(propertyID, listener);
785 }
786 override
787 public void setBackground (Color color) {
788 
789     super.setBackground(color);
790 
791     //set the background of the ActiveX Control
792     if (objIUnknown !is null) {
793         OleAutomation oleObject= new OleAutomation(this);
794         oleObject.setProperty(COM.DISPID_BACKCOLOR, new Variant(color.handle));
795         oleObject.dispose();
796     }
797 }
798 override
799 public void setFont (Font font) {
800 
801     super.setFont(font);
802 
803     //set the font of the ActiveX Control
804     if (objIUnknown !is null) {
805 
806         OleAutomation oleObject= new OleAutomation(this);
807         Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
808         oleObject.dispose();
809 
810         if (varDispFont !is null){
811             OleAutomation iDispFont = varDispFont.getAutomation();
812             FontData[] fdata = font.getFontData();
813             iDispFont.setProperty(COM.DISPID_FONT_NAME,   new Variant(fdata[0].getName()));
814             iDispFont.setProperty(COM.DISPID_FONT_SIZE,   new Variant(fdata[0].getHeight()));
815             iDispFont.setProperty(COM.DISPID_FONT_ITALIC, new Variant(fdata[0].getStyle() & SWT.ITALIC));
816             //iDispFont.setProperty(COM.DISPID_FONT_CHARSET, new Variant(fdata[0].getCharset));
817             iDispFont.setProperty(COM.DISPID_FONT_BOLD,   new Variant((fdata[0].getStyle() & SWT.BOLD)));
818             iDispFont.dispose();
819         }
820     }
821 
822     return;
823 }
824 override
825 public void setForeground (Color color) {
826 
827     super.setForeground(color);
828 
829     //set the foreground of the ActiveX Control
830     if (objIUnknown !is null) {
831         OleAutomation oleObject= new OleAutomation(this);
832         oleObject.setProperty(COM.DISPID_FORECOLOR, new Variant(color.handle));
833         oleObject.dispose();
834     }
835 }
836 /**
837  * Sets the control site property specified by the dispIdMember to a new value.
838  * The value will be disposed by the control site when it is no longer required
839  * using Variant.dispose.  Passing a value of null will clear the dispId value.
840  *
841  * @param dispId the ID of the property as specified by the IDL of the ActiveX Control
842  * @param value The new value for the property as expressed in a Variant.
843  *
844  * @since 2.1
845  */
846 public void setSiteProperty(int dispId, Variant value){
847     for (int i = 0; i < sitePropertyIds.length; i++) {
848         if (sitePropertyIds[i] is dispId) {
849             if (sitePropertyValues[i] !is null) {
850                 sitePropertyValues[i].dispose();
851             }
852             if (value !is null) {
853                 sitePropertyValues[i] = value;
854             } else {
855                 int oldLength = cast(int)/*64bit*/sitePropertyIds.length;
856                 int[] newSitePropertyIds = new int[oldLength - 1];
857                 Variant[] newSitePropertyValues = new Variant[oldLength - 1];
858                 System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0, i);
859                 System.arraycopy(sitePropertyIds, i + 1, newSitePropertyIds, i, oldLength - i - 1);
860                 System.arraycopy(sitePropertyValues, 0, newSitePropertyValues, 0, i);
861                 System.arraycopy(sitePropertyValues, i + 1, newSitePropertyValues, i, oldLength - i - 1);
862                 sitePropertyIds = newSitePropertyIds;
863                 sitePropertyValues = newSitePropertyValues;
864             }
865             return;
866         }
867     }
868     int oldLength = cast(int)/*64bit*/sitePropertyIds.length;
869     int[] newSitePropertyIds = new int[oldLength + 1];
870     Variant[] newSitePropertyValues = new Variant[oldLength + 1];
871     System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0, oldLength);
872     System.arraycopy(sitePropertyValues, 0, newSitePropertyValues, 0, oldLength);
873     newSitePropertyIds[oldLength] = dispId;
874     newSitePropertyValues[oldLength] = value;
875     sitePropertyIds = newSitePropertyIds;
876     sitePropertyValues = newSitePropertyValues;
877 }
878 }
879 
880 class _IDispatchImpl : IDispatch {
881 
882     OleControlSite  parent;
883     this(OleControlSite p) { parent = p; }
884 extern (Windows):
885     // interface of IUnknown
886     HRESULT QueryInterface(REFCIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
887     ULONG AddRef()  { return parent.AddRef(); }
888     ULONG Release() { return parent.Release(); }
889 
890     // interface of IDispatch : IUnknown
891     HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
892     HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
893     HRESULT GetIDsOfNames(REFCIID riid, LPCOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
894     // Note : <Shawn> one argument is short !!!
895     HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr) {
896         return parent.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
897     }
898 }
899 
900 class _IOleControlSiteImpl : IOleControlSite {
901 
902     OleControlSite  parent;
903     this(OleControlSite p) { parent = p; }
904 extern (Windows):
905     // interface of IUnknown
906     HRESULT QueryInterface(REFCIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
907     ULONG AddRef()  { return parent.AddRef(); }
908     ULONG Release() { return parent.Release(); }
909 
910     // interface IOleControlSite : IUnknown
911     HRESULT OnControlInfoChanged() { return parent.OnControlInfoChanged();}
912     HRESULT LockInPlaceActive(BOOL fLock) { return COM.E_NOTIMPL; }
913     HRESULT GetExtendedControl(LPDISPATCH* ppDisp) { return COM.E_NOTIMPL; }
914     HRESULT TransformCoords(
915       POINTL* pPtlHimetric ,  //Address of POINTL structure
916       POINTF* pPtfContainer ,  //Address of POINTF structure
917       DWORD dwFlags           //Flags indicating the exact conversion
918     ) { return COM.E_NOTIMPL; }
919     HRESULT TranslateAccelerator(
920       LPMSG pMsg ,        //Pointer to the structure
921       DWORD grfModifiers  //Flags describing the state of the keys
922     )
923     { return COM.E_NOTIMPL; }
924     HRESULT OnFocus(
925       BOOL fGotFocus  //Indicates whether the control gained focus
926     )
927     { return COM.S_OK; }
928     HRESULT ShowPropertyFrame() { return COM.E_NOTIMPL; }
929 }
930 
931 
932