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