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