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