<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sealyu

    --- 博客已遷移至: http://www.sealyu.com/blog

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      618 隨筆 :: 87 文章 :: 225 評論 :: 0 Trackbacks
    最近用到了SWT 中的Browser類,這個類不允許被繼承,在網(wǎng)上搜索的時候發(fā)現(xiàn)了下面的帖子。這個類實際上是使用OLE,將IE直接嵌套進(jìn)SWT程序中去。下面代碼的 修改實際上將SWT中的WebBrowser類的子類IE直接和Browser 類合到一起,而同時也就沒有了原來SWT中的跨平臺的優(yōu)點。該作者添加了setHtml這個函數(shù)和_text屬性。從而得到對應(yīng)的網(wǎng)頁的html內(nèi)容。

    /*******************************************************************************
     * Copyright (c) 2003, 2005 IBM Corporation and others.
     * All rights reserved. This program and the accompanying materials
     * are made available under the terms of the Eclipse Public License v1.0
     * which accompanies this distribution, and is available at
     * http://www.eclipse.org/legal/epl-v10.html
     *
     * Contributors:
     *     IBM Corporation - initial API and implementation
     *******************************************************************************/
    package com.***.browser;

    import java.text.Collator;
    import java.util.Locale;

    import org.eclipse.swt.*;
    import org.eclipse.swt.graphics.*;
    import org.eclipse.swt.internal.ole.win32.*;
    import org.eclipse.swt.internal.win32.*;
    import org.eclipse.swt.ole.win32.*;
    import org.eclipse.swt.widgets.*;

    /**
     * Instances of this class implement the browser user interface metaphor. It
     * allows the user to visualize and navigate through HTML documents.
     * <p>
     * Note that although this class is a subclass of <code>Composite</code>, it
     * does not make sense to set a layout on it.
     * </p>
     * <p>
     * IMPORTANT: This class is <em>not</em> intended to be subclassed.
     * </p>
     *
     * @since 3.0
     */
    public class Browser extends Composite {

     static int CodePage = OS.GetACP();

     public static int maxBrowserId = 0;
     private int browserId = 0;
     private BrowserInfo browserInfo = null;

     OleFrame frame;
     OleControlSite site;
     OleAutomation auto;

     boolean back, forward, navigate, delaySetText;
     Point location;
     Point size;
     boolean addressBar = true, menuBar = true, statusBar = true, toolBar = true;
     int info;

     int globalDispatch;
     String _text;
     String html;

     /* External Listener management */
     CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0];
     LocationListener[] locationListeners = new LocationListener[0];
     OpenWindowListener[] openWindowListeners = new OpenWindowListener[0];
     ProgressListener[] progressListeners = new ProgressListener[0];
     StatusTextListener[] statusTextListeners = new StatusTextListener[0];
     TitleListener[] titleListeners = new TitleListener[0];
     VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0];

     static final int BeforeNavigate2 = 0xfa;
     static final int CommandStateChange = 0x69;
     static final int DocumentComplete = 0x103;
     static final int NavigateComplete2 = 0xfc;
     static final int NewWindow2 = 0xfb;
     static final int OnMenuBar = 0x100;
     static final int OnStatusBar = 0x101;
     static final int OnToolBar = 0xff;
     static final int OnVisible = 0xfe;
     static final int ProgressChange = 0x6c;
     static final int RegisterAsBrowser = 0x228;
     static final int StatusTextChange = 0x66;
     static final int TitleChange = 0x71;
     static final int WindowClosing = 0x107;
     static final int WindowSetHeight = 0x10b;
     static final int WindowSetLeft = 0x108;
     static final int WindowSetResizable = 0x106;
     static final int WindowSetTop = 0x109;
     static final int WindowSetWidth = 0x10a;

     static final short CSC_NAVIGATEFORWARD = 1;
     static final short CSC_NAVIGATEBACK = 2;
     static final int INET_E_DEFAULT_ACTION = 0x800C0011;
     static final int READYSTATE_COMPLETE = 4;
     static final int URLPOLICY_ALLOW = 0x00;
     static final int URLPOLICY_DISALLOW = 0x03;
     static final int URLZONE_LOCAL_MACHINE = 0;
     static final int URLZONE_INTRANET = 1;
     static final int URLACTION_ACTIVEX_MIN = 0x00001200;
     static final int URLACTION_ACTIVEX_MAX = 0x000013ff;
     static final int URLACTION_ACTIVEX_RUN = 0x00001200;
     static final int URLACTION_JAVA_MIN = 0x00001C00;
     static final int URLPOLICY_JAVA_LOW = 0x00030000;
     static final int URLACTION_JAVA_MAX = 0x00001Cff;

     static final int DISPID_AMBIENT_DLCONTROL = -5512;
     static final int DLCTL_DLIMAGES = 0x00000010;
     static final int DLCTL_VIDEOS = 0x00000020;
     static final int DLCTL_BGSOUNDS = 0x00000040;
     static final int DLCTL_NO_SCRIPTS = 0x00000080;
     static final int DLCTL_NO_JAVA = 0x00000100;
     static final int DLCTL_NO_RUNACTIVEXCTLS = 0x00000200;
     static final int DLCTL_NO_DLACTIVEXCTLS = 0x00000400;
     static final int DLCTL_DOWNLOADONLY = 0x00000800;
     static final int DLCTL_NO_FRAMEDOWNLOAD = 0x00001000;
     static final int DLCTL_RESYNCHRONIZE = 0x00002000;
     static final int DLCTL_PRAGMA_NO_CACHE = 0x00004000;
     static final int DLCTL_FORCEOFFLINE = 0x10000000;
     static final int DLCTL_NO_CLIENTPULL = 0x20000000;
     static final int DLCTL_SILENT = 0x40000000;
     static final int DOCHOSTUIFLAG_THEME = 0x00040000;
     static final int DOCHOSTUIFLAG_NO3DBORDER = 0x0000004;
     static final int DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000;

     static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
     static final String URL_DIRECTOR = "

     /* Package Name */
     static final String PACKAGE_PREFIX = "com.macrosoft.browser."; //$NON-NLS-1$

     /**
      * Constructs a new instance of this class given its parent and a style
      * value describing its behavior and appearance.
      * <p>
      * The style value is either one of the style constants defined in class
      * <code>SWT</code> which is applicable to instances of this class, or
      * must be built by <em>bitwise OR</em>'ing together (that is, using the
      * <code>int</code> "|" operator) two or more of those <code>SWT</code>
      * style constants. The class description lists the style constants that are
      * applicable to the class. Style bits are also inherited from superclasses.
      * </p>
      *
      * @param parent
      *            a widget which will be the parent of the new instance (cannot
      *            be null)
      * @param style
      *            the style of widget to construct
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
      *                </ul>
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
      *                thread that created the parent</li>
      *                </ul>
      * @exception SWTError
      *                <ul>
      *                <li>ERROR_NO_HANDLES if a handle could not be obtained
      *                for browser creation</li>
      *                </ul>
      *
      * @see Widget#getStyle
      *
      * @since 3.0
      */
     public Browser(Composite parent, int style) {
      super(parent, style & ~SWT.BORDER);

      this.browserId = ++maxBrowserId;
      browserInfo = new BrowserInfo(this.browserId);//BorserInfo是我自己創(chuàng)建的類,沒有必要用
      BrowserManager.addBrowserInfo(browserInfo);// ????????browser

      info = Browser.DOCHOSTUIFLAG_THEME;
      if ((style & SWT.BORDER) == 0)
       info |= Browser.DOCHOSTUIFLAG_NO3DOUTERBORDER;
      frame = new OleFrame(this, SWT.NONE);
      try {
       site = new WebSite(frame, SWT.NONE, "Shell.Explorer"); //$NON-NLS-1$
      } catch (SWTException e) {
       dispose();
       SWT.error(SWT.ERROR_NO_HANDLES);
      }

      site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
      auto = new OleAutomation(site);

      Listener listener = new Listener() {
       public void handleEvent(Event e) {
        switch (e.type) {
        case SWT.Dispose: {
         if (auto != null)
          auto.dispose();
         auto = null;
         break;
        }
        case SWT.Resize: {
         frame.setBounds(getClientArea());
         break;
        }
        case SWT.KeyDown:
        case SWT.KeyUp: {
         notifyListeners(e.type, e);
         break;
        }
        }
       }
      };
      addListener(SWT.Dispose, listener);
      addListener(SWT.Resize, listener);
      site.addListener(SWT.KeyDown, listener);
      site.addListener(SWT.KeyUp, listener);

      // addListener(SWT.FocusIn, new Listener() {
      // public void handleEvent(Event e) {
      // System.out.println("Browser " + browserId + " Selected");
      // }
      // });

      OleListener oleListener = new OleListener() {
       public void handleEvent(OleEvent event) {
        switch (event.type) {
        case BeforeNavigate2: {
         Variant varResult = event.arguments[1];
         String url = varResult.getString();
         LocationEvent newEvent = new LocationEvent(Browser.this);
         newEvent.display = getDisplay();
         newEvent.widget = Browser.this;
         newEvent.location = url;
         newEvent.doit = true;
         for (int i = 0; i < locationListeners.length; i++)
          locationListeners[i].changing(newEvent);

         // browserInfo.setUrl(event.arguments[1].getString());
         //開出該段代碼讀取請求的url和postdata
         //Variant postData = event.arguments[4];
         //if (!browserInfo.isOpenWindow()) {
         // System.out.println("URL = " + event.arguments[1].getString());
         // System.out.println("PostData = " + readSafeArray(postData));
         // browserInfo.setPostData(readSafeArray(postData));
         //}

         Variant cancel = event.arguments[6];
         if (cancel != null) {
          int pCancel = cancel.getByRef();
          COM
            .MoveMemory(pCancel,
              new short[] { newEvent.doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE }, 2);
         }
         break;
        }
        case CommandStateChange: {
         boolean enabled = false;
         Variant varResult = event.arguments[0];
         int command = varResult.getInt();
         varResult = event.arguments[1];
         enabled = varResult.getBoolean();
         switch (command) {
         case CSC_NAVIGATEBACK:
          back = enabled;
          break;
         case CSC_NAVIGATEFORWARD:
          forward = enabled;
          break;
         }
         break;
        }
        case DocumentComplete: {
         Variant varResult = event.arguments[0];
         IDispatch dispatch = varResult.getDispatch();

         varResult = event.arguments[1];
         String url = varResult.getString();
         if (html != null && url.equals(ABOUT_BLANK)) {
          Runnable runnable = new Runnable() {
           public void run() {
            if (isDisposed() || html == null)
             return;
            int charCount = html.length();
            char[] chars = new char[charCount];
            html.getChars(0, charCount, chars, 0);
            _text = html;
            html = null;
            int byteCount = OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, null, 0, null,
              null);
            /*
             * Note. Internet Explorer appears to treat the
             * data loaded with nsIPersistStreamInit.Load as
             * if it were encoded using the default local
             * charset. There does not seem to be an API to
             * set the desired charset explicitely in this
             * case. The fix is to prepend the UTF-8 Byte
             * Order Mark signature to the data.
             */
            byte[] UTF8BOM = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
            int hGlobal = OS.GlobalAlloc(OS.GMEM_FIXED, UTF8BOM.length + byteCount);
            if (hGlobal != 0) {
             OS.MoveMemory(hGlobal, UTF8BOM, UTF8BOM.length);
             OS.WideCharToMultiByte(OS.CP_UTF8, 0, chars, charCount, hGlobal + UTF8BOM.length,
               byteCount, null, null);
             int[] ppstm = new int[1];
             /*
              * Note. CreateStreamOnHGlobal is called
              * with the flag fDeleteOnRelease. If the
              * call succeeds the buffer hGlobal is freed
              * automatically when the IStream object is
              * released. If the call fails, free the
              * buffer hGlobal.
              */
             if (OS.CreateStreamOnHGlobal(hGlobal, true, ppstm) == OS.S_OK) {
              int[] rgdispid = auto.getIDsOfNames(new String[] { "Document" }); //$NON-NLS-1$
              Variant pVarResult = auto.getProperty(rgdispid[0]);
              IDispatch dispatchDocument = pVarResult.getDispatch();
              int[] ppvObject = new int[1];
              int result = dispatchDocument.QueryInterface(COM.IIDIPersistStreamInit,
                ppvObject);
              if (result == OS.S_OK) {
               IPersistStreamInit persistStreamInit = new IPersistStreamInit(ppvObject[0]);
               if (persistStreamInit.InitNew() == OS.S_OK) {
                persistStreamInit.Load(ppstm[0]);
               }
               persistStreamInit.Release();
              }
              pVarResult.dispose();
              /*
               * This code is intentionally commented.
               * The IDispatch obtained from a Variant
               * did not increase the reference count
               * for the enclosed interface.
               */
              // dispatchDocument.Release();
              IUnknown stream = new IUnknown(ppstm[0]);
              stream.Release();
             } else {
              OS.GlobalFree(hGlobal);
             }
            }
           }
          };
          if (delaySetText) {
           delaySetText = false;
           getDisplay().asyncExec(runnable);
          } else {
           runnable.run();
          }
         } else {
          setHTML();

          Variant variant = new Variant(auto);
          IDispatch top = variant.getDispatch();
          LocationEvent locationEvent = new LocationEvent(Browser.this);
          locationEvent.display = getDisplay();
          locationEvent.widget = Browser.this;
          locationEvent.location = url;
          locationEvent.top = top.getAddress() == dispatch.getAddress();
          for (int i = 0; i < locationListeners.length; i++)
           locationListeners[i].changed(locationEvent);
          /*
           * This code is intentionally commented. A Variant
           * constructed from an OleAutomation object does not
           * increase its reference count. The IDispatch obtained
           * from this Variant did not increase the reference
           * count for the OleAutomation instance either.
           */
          // top.Release();
          // variant.dispose();
          /*
           * Note. The completion of the page loading is detected
           * as described in the MSDN article "Determine when a
           * page is done loading in WebBrowser Control".
           */
          if (globalDispatch != 0 && dispatch.getAddress() == globalDispatch) {
           /* final document complete */
           globalDispatch = 0;
           ProgressEvent progressEvent = new ProgressEvent(Browser.this);
           progressEvent.display = getDisplay();
           progressEvent.widget = Browser.this;
           for (int i = 0; i < progressListeners.length; i++)
            progressListeners[i].completed(progressEvent);
          }
         }

         /*
          * This code is intentionally commented. This IDispatch was
          * received as an argument from the OleEvent and it will be
          * disposed along with the other arguments.
          */
         // dispatch.Release();
         break;
        }
        case NavigateComplete2: {
         Variant varResult = event.arguments[0];
         IDispatch dispatch = varResult.getDispatch();
         if (globalDispatch == 0)
          globalDispatch = dispatch.getAddress();
         break;
        }
        case NewWindow2: {
         Variant cancel = event.arguments[1];
         int pCancel = cancel.getByRef();
         WindowEvent newEvent = new WindowEvent(Browser.this);
         newEvent.display = getDisplay();
         newEvent.widget = Browser.this;
         newEvent.required = false;
         for (int i = 0; i < openWindowListeners.length; i++)
          openWindowListeners[i].open(newEvent);
         Browser browser = newEvent.browser;
         boolean doit = browser != null && !browser.isDisposed();
         if (doit) {
          Variant variant = new Variant(browser.auto);
          IDispatch iDispatch = variant.getDispatch();
          Variant ppDisp = event.arguments[0];
          int byref = ppDisp.getByRef();
          if (byref != 0)
           COM.MoveMemory(byref, new int[] { iDispatch.getAddress() }, 4);
          /*
           * This code is intentionally commented. A Variant
           * constructed from an OleAutomation object does not
           * increase its reference count. The IDispatch obtained
           * from this Variant did not increase the reference
           * count for the OleAutomation instance either.
           */
          // variant.dispose();
          // iDispatch.Release();
         }
         if (newEvent.required) {
          COM.MoveMemory(pCancel, new short[] { doit ? COM.VARIANT_FALSE : COM.VARIANT_TRUE }, 2);
         }
         break;
        }
        case OnMenuBar: {
         Variant arg0 = event.arguments[0];
         menuBar = arg0.getBoolean();
         break;
        }
        case OnStatusBar: {
         Variant arg0 = event.arguments[0];
         statusBar = arg0.getBoolean();
         break;
        }
        case OnToolBar: {
         Variant arg0 = event.arguments[0];
         toolBar = arg0.getBoolean();
         /*
          * Feature in Internet Explorer. OnToolBar FALSE is emitted
          * when both tool bar, address bar and menu bar must not be
          * visible. OnToolBar TRUE is emitted when either of tool
          * bar, address bar or menu bar is visible.
          */
         if (!toolBar) {
          addressBar = false;
          menuBar = false;
         }
         break;
        }
        case OnVisible: {
         Variant arg1 = event.arguments[0];
         boolean visible = arg1.getBoolean();
         WindowEvent newEvent = new WindowEvent(Browser.this);
         newEvent.display = getDisplay();
         newEvent.widget = Browser.this;
         if (visible) {
          if (addressBar) {
           /*
            * Bug in Internet Explorer. There is no distinct
            * notification for the address bar. If neither
            * address, menu or tool bars are visible, OnToolBar
            * FALSE is emitted. For some reason, querying the
            * value of AddressBar in this case returns true
            * even though it should not be set visible. The
            * workaround is to only query the value of
            * AddressBar when OnToolBar FALSE has not been
            * emitted.
            */
           int[] rgdispid = auto.getIDsOfNames(new String[] { "AddressBar" }); //$NON-NLS-1$
           Variant pVarResult = auto.getProperty(rgdispid[0]);
           if (pVarResult != null && pVarResult.getType() == OLE.VT_BOOL)
            addressBar = pVarResult.getBoolean();
          }
          newEvent.addressBar = addressBar;
          newEvent.menuBar = menuBar;
          newEvent.statusBar = statusBar;
          newEvent.toolBar = toolBar;
          newEvent.location = location;
          newEvent.size = size;
          for (int i = 0; i < visibilityWindowListeners.length; i++) {
           visibilityWindowListeners[i].show(newEvent);
          }
          location = null;
          size = null;
         } else {
          for (int i = 0; i < visibilityWindowListeners.length; i++)
           visibilityWindowListeners[i].hide(newEvent);
         }
         break;
        }
        case ProgressChange: {
         Variant arg1 = event.arguments[0];
         int nProgress = arg1.getType() != OLE.VT_I4 ? 0 : arg1.getInt(); // may
                          // be
                          // -1
         Variant arg2 = event.arguments[1];
         int nProgressMax = arg2.getType() != OLE.VT_I4 ? 0 : arg2.getInt();
         ProgressEvent newEvent = new ProgressEvent(Browser.this);
         newEvent.display = getDisplay();
         newEvent.widget = Browser.this;
         newEvent.current = nProgress;
         newEvent.total = nProgressMax;
         if (nProgress != -1) {
          for (int i = 0; i < progressListeners.length; i++)
           progressListeners[i].changed(newEvent);
         }
         break;
        }
        case StatusTextChange: {
         Variant arg1 = event.arguments[0];
         if (arg1.getType() == OLE.VT_BSTR) {
          String text = arg1.getString();
          StatusTextEvent newEvent = new StatusTextEvent(Browser.this);
          newEvent.display = getDisplay();
          newEvent.widget = Browser.this;
          newEvent.text = text;
          for (int i = 0; i < statusTextListeners.length; i++)
           statusTextListeners[i].changed(newEvent);
         }
         break;
        }
        case TitleChange: {
         Variant arg1 = event.arguments[0];
         if (arg1.getType() == OLE.VT_BSTR) {
          String title = arg1.getString();
          TitleEvent newEvent = new TitleEvent(Browser.this);
          newEvent.display = getDisplay();
          newEvent.widget = Browser.this;
          newEvent.title = title;
          for (int i = 0; i < titleListeners.length; i++)
           titleListeners[i].changed(newEvent);
         }
         break;
        }
        case WindowClosing: {
         WindowEvent newEvent = new WindowEvent(Browser.this);
         newEvent.display = getDisplay();
         newEvent.widget = Browser.this;
         for (int i = 0; i < closeWindowListeners.length; i++)
          closeWindowListeners[i].close(newEvent);
         Variant cancel = event.arguments[1];
         int pCancel = cancel.getByRef();
         COM.MoveMemory(pCancel, new short[] { COM.VARIANT_FALSE }, 2);
         dispose();
         break;
        }
        case WindowSetHeight: {
         if (size == null)
          size = new Point(0, 0);
         Variant arg1 = event.arguments[0];
         size.y = arg1.getInt();
         break;
        }
        case WindowSetLeft: {
         if (location == null)
          location = new Point(0, 0);
         Variant arg1 = event.arguments[0];
         location.x = arg1.getInt();
         break;
        }
        case WindowSetTop: {
         if (location == null)
          location = new Point(0, 0);
         Variant arg1 = event.arguments[0];
         location.y = arg1.getInt();
         break;
        }
        case WindowSetWidth: {
         if (size == null)
          size = new Point(0, 0);
         Variant arg1 = event.arguments[0];
         size.x = arg1.getInt();
         break;
        }
        }
        /*
         * Dispose all arguments passed in the OleEvent. This must be
         * done to properly release any IDispatch reference that was
         * automatically addRef'ed when constructing the OleEvent.
         */
        Variant[] arguments = event.arguments;
        for (int i = 0; i < arguments.length; i++)
         arguments[i].dispose();
       }
      };
      site.addEventListener(BeforeNavigate2, oleListener);
      site.addEventListener(CommandStateChange, oleListener);
      site.addEventListener(DocumentComplete, oleListener);
      site.addEventListener(NavigateComplete2, oleListener);
      site.addEventListener(NewWindow2, oleListener);
      site.addEventListener(OnMenuBar, oleListener);
      site.addEventListener(OnStatusBar, oleListener);
      site.addEventListener(OnToolBar, oleListener);
      site.addEventListener(OnVisible, oleListener);
      site.addEventListener(ProgressChange, oleListener);
      site.addEventListener(StatusTextChange, oleListener);
      site.addEventListener(TitleChange, oleListener);
      site.addEventListener(WindowClosing, oleListener);
      site.addEventListener(WindowSetHeight, oleListener);
      site.addEventListener(WindowSetLeft, oleListener);
      site.addEventListener(WindowSetTop, oleListener);
      site.addEventListener(WindowSetWidth, oleListener);

      Variant variant = new Variant(true);
      auto.setProperty(RegisterAsBrowser, variant);
      variant.dispose();

      variant = new Variant(false);
      int[] rgdispid = auto.getIDsOfNames(new String[] { "RegisterAsDropTarget" }); //$NON-NLS-1$
      if (rgdispid != null)
       auto.setProperty(rgdispid[0], variant);
      variant.dispose();
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when the window hosting the receiver should be closed.
      * <p>
      * This notification occurs when a javascript command such as
      * <code>window.close</code> gets executed by a <code>Browser</code>.
      * </p>
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addCloseWindowListener(CloseWindowListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1];
      System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, closeWindowListeners.length);
      closeWindowListeners = newCloseWindowListeners;
      closeWindowListeners[closeWindowListeners.length - 1] = listener;
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when the current location has changed or is about to change.
      * <p>
      * This notification typically occurs when the application navigates to a
      * new location with
    {@link #setUrl(String)} or when the user activates a
      * hyperlink.
      * </p>
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addLocationListener(LocationListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1];
      System.arraycopy(locationListeners, 0, newLocationListeners, 0, locationListeners.length);
      locationListeners = newLocationListeners;
      locationListeners[locationListeners.length - 1] = listener;
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when a new window needs to be created.
      * <p>
      * This notification occurs when a javascript command such as
      * <code>window.open</code> gets executed by a <code>Browser</code>.
      * </p>
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addOpenWindowListener(OpenWindowListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1];
      System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, openWindowListeners.length);
      openWindowListeners = newOpenWindowListeners;
      openWindowListeners[openWindowListeners.length - 1] = listener;
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when a progress is made during the loading of the current URL or when the
      * loading of the current URL has been completed.
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addProgressListener(ProgressListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1];
      System.arraycopy(progressListeners, 0, newProgressListeners, 0, progressListeners.length);
      progressListeners = newProgressListeners;
      progressListeners[progressListeners.length - 1] = listener;
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when the status text is changed.
      * <p>
      * The status text is typically displayed in the status bar of a browser
      * application.
      * </p>
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addStatusTextListener(StatusTextListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1];
      System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, statusTextListeners.length);
      statusTextListeners = newStatusTextListeners;
      statusTextListeners[statusTextListeners.length - 1] = listener;
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when the title of the current document is available or has changed.
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addTitleListener(TitleListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1];
      System.arraycopy(titleListeners, 0, newTitleListeners, 0, titleListeners.length);
      titleListeners = newTitleListeners;
      titleListeners[titleListeners.length - 1] = listener;
     }

     /**
      * Adds the listener to the collection of listeners who will be notified
      * when a window hosting the receiver needs to be displayed or hidden.
      *
      * @param listener
      *            the listener which should be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void addVisibilityWindowListener(VisibilityWindowListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1];
      System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0,
        visibilityWindowListeners.length);
      visibilityWindowListeners = newVisibilityWindowListeners;
      visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener;
     }

     /**
      * Navigate to the previous session history item.
      *
      * @return <code>true</code> if the operation was successful and
      *         <code>false</code> otherwise
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @see #forward
      *
      * @since 3.0
      */
     public boolean back() {
      checkWidget();
      if (!back)
       return false;
      int[] rgdispid = auto.getIDsOfNames(new String[] { "GoBack" }); //$NON-NLS-1$
      Variant pVarResult = auto.invoke(rgdispid[0]);
      return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
     }

     protected void checkSubclass() {
      String name = getClass().getName();
      int index = name.lastIndexOf('.');
      if (!name.substring(0, index + 1).equals(PACKAGE_PREFIX)) {
       SWT.error(SWT.ERROR_INVALID_SUBCLASS);
      }
     }

     /**
      * Execute the specified script.
      *
      * <p>
      * Execute a script containing javascript commands in the context of the
      * current document.
      *
      * @param script
      *            the script with javascript commands
      *
      * @return <code>true</code> if the operation was successful and
      *         <code>false</code> otherwise
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the script is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.1
      */
     public boolean execute(String script) {
      checkWidget();
      if (script == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);

      /* get IHTMLDocument2 */
      int[] rgdispid = auto.getIDsOfNames(new String[] { "Document" }); //$NON-NLS-1$
      int dispIdMember = rgdispid[0];
      Variant pVarResult = auto.getProperty(dispIdMember);
      if (pVarResult == null || pVarResult.getType() == COM.VT_EMPTY)
       return false;
      OleAutomation document = pVarResult.getAutomation();
      pVarResult.dispose();

      /* get IHTMLWindow2 */
      rgdispid = document.getIDsOfNames(new String[] { "parentWindow" }); //$NON-NLS-1$
      dispIdMember = rgdispid[0];
      pVarResult = document.getProperty(dispIdMember);
      OleAutomation ihtmlWindow2 = pVarResult.getAutomation();
      pVarResult.dispose();
      document.dispose();

      rgdispid = ihtmlWindow2.getIDsOfNames(new String[] { "execScript", "code" }); //$NON-NLS-1$  //$NON-NLS-2$
      Variant[] rgvarg = new Variant[1];
      rgvarg[0] = new Variant(script);
      int[] rgdispidNamedArgs = new int[1];
      rgdispidNamedArgs[0] = rgdispid[1];
      pVarResult = ihtmlWindow2.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
      rgvarg[0].dispose();
      ihtmlWindow2.dispose();
      if (pVarResult == null)
       return false;
      pVarResult.dispose();
      return true;
     }

     /**
      * Navigate to the next session history item.
      *
      * @return <code>true</code> if the operation was successful and
      *         <code>false</code> otherwise
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @see #back
      *
      * @since 3.0
      */
     public boolean forward() {
      checkWidget();
      if (!forward)
       return false;
      int[] rgdispid = auto.getIDsOfNames(new String[] { "GoForward" }); //$NON-NLS-1$
      Variant pVarResult = auto.invoke(rgdispid[0]);
      return pVarResult != null && pVarResult.getType() == OLE.VT_EMPTY;
     }

     /**
      * Returns <code>true</code> if the receiver can navigate to the previous
      * session history item, and <code>false</code> otherwise.
      *
      * @return the receiver's back command enabled state
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
      *                disposed</li>
      *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
      *                thread that created the receiver</li>
      *                </ul>
      *
      * @see #back
      */
     public boolean isBackEnabled() {
      checkWidget();
      return back;
     }

     /**
      * Returns <code>true</code> if the receiver can navigate to the next
      * session history item, and <code>false</code> otherwise.
      *
      * @return the receiver's forward command enabled state
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
      *                disposed</li>
      *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
      *                thread that created the receiver</li>
      *                </ul>
      *
      * @see #forward
      */
     public boolean isForwardEnabled() {
      checkWidget();
      return forward;
     }

     /**
      * Returns the current URL.
      *
      * @return the current URL or an empty <code>String</code> if there is no
      *         current URL
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @see #setUrl
      *
      * @since 3.0
      */
     public String getUrl() {
      checkWidget();
      int[] rgdispid = auto.getIDsOfNames(new String[] { "LocationURL" }); //$NON-NLS-1$
      Variant pVarResult = auto.getProperty(rgdispid[0]);
      if (pVarResult == null || pVarResult.getType() != OLE.VT_BSTR)
       return "";
      String result = pVarResult.getString();
      pVarResult.dispose();
      return result;
     }

     /**
      * Refresh the current page.
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void refresh() {
      checkWidget();
      int[] rgdispid = auto.getIDsOfNames(new String[] { "Refresh" }); //$NON-NLS-1$
      auto.invoke(rgdispid[0]);
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when the window hosting the receiver should be closed.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeCloseWindowListener(CloseWindowListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (closeWindowListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < closeWindowListeners.length; i++) {
       if (listener == closeWindowListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (closeWindowListeners.length == 1) {
       closeWindowListeners = new CloseWindowListener[0];
       return;
      }
      CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1];
      System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, index);
      System.arraycopy(closeWindowListeners, index + 1, newCloseWindowListeners, index, closeWindowListeners.length
        - index - 1);
      closeWindowListeners = newCloseWindowListeners;
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when the current location is changed or about to be changed.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeLocationListener(LocationListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (locationListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < locationListeners.length; i++) {
       if (listener == locationListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (locationListeners.length == 1) {
       locationListeners = new LocationListener[0];
       return;
      }
      LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1];
      System.arraycopy(locationListeners, 0, newLocationListeners, 0, index);
      System.arraycopy(locationListeners, index + 1, newLocationListeners, index, locationListeners.length - index
        - 1);
      locationListeners = newLocationListeners;
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when a new window needs to be created.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeOpenWindowListener(OpenWindowListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (openWindowListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < openWindowListeners.length; i++) {
       if (listener == openWindowListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (openWindowListeners.length == 1) {
       openWindowListeners = new OpenWindowListener[0];
       return;
      }
      OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1];
      System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, index);
      System.arraycopy(openWindowListeners, index + 1, newOpenWindowListeners, index, openWindowListeners.length
        - index - 1);
      openWindowListeners = newOpenWindowListeners;
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when a progress is made during the loading of the current URL or
      * when the loading of the current URL has been completed.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeProgressListener(ProgressListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (progressListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < progressListeners.length; i++) {
       if (listener == progressListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (progressListeners.length == 1) {
       progressListeners = new ProgressListener[0];
       return;
      }
      ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1];
      System.arraycopy(progressListeners, 0, newProgressListeners, 0, index);
      System.arraycopy(progressListeners, index + 1, newProgressListeners, index, progressListeners.length - index
        - 1);
      progressListeners = newProgressListeners;
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when the status text is changed.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeStatusTextListener(StatusTextListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (statusTextListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < statusTextListeners.length; i++) {
       if (listener == statusTextListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (statusTextListeners.length == 1) {
       statusTextListeners = new StatusTextListener[0];
       return;
      }
      StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1];
      System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, index);
      System.arraycopy(statusTextListeners, index + 1, newStatusTextListeners, index, statusTextListeners.length
        - index - 1);
      statusTextListeners = newStatusTextListeners;
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when the title of the current document is available or has
      * changed.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeTitleListener(TitleListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (titleListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < titleListeners.length; i++) {
       if (listener == titleListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (titleListeners.length == 1) {
       titleListeners = new TitleListener[0];
       return;
      }
      TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1];
      System.arraycopy(titleListeners, 0, newTitleListeners, 0, index);
      System.arraycopy(titleListeners, index + 1, newTitleListeners, index, titleListeners.length - index - 1);
      titleListeners = newTitleListeners;
     }

     /**
      * Removes the listener from the collection of listeners who will be
      * notified when a window hosting the receiver needs to be displayed or
      * hidden.
      *
      * @param listener
      *            the listener which should no longer be notified
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void removeVisibilityWindowListener(VisibilityWindowListener listener) {
      checkWidget();
      if (listener == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (visibilityWindowListeners.length == 0)
       return;
      int index = -1;
      for (int i = 0; i < visibilityWindowListeners.length; i++) {
       if (listener == visibilityWindowListeners[i]) {
        index = i;
        break;
       }
      }
      if (index == -1)
       return;
      if (visibilityWindowListeners.length == 1) {
       visibilityWindowListeners = new VisibilityWindowListener[0];
       return;
      }
      VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1];
      System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, index);
      System.arraycopy(visibilityWindowListeners, index + 1, newVisibilityWindowListeners, index,
        visibilityWindowListeners.length - index - 1);
      visibilityWindowListeners = newVisibilityWindowListeners;
     }

     /**
      * Renders HTML.
      *
      * <p>
      * The html parameter is Unicode encoded since it is a java
      * <code>String</code>. As a result, the HTML meta tag charset should not
      * be set. The charset is implied by the <code>String</code> itself.
      *
      * @param html
      *            the HTML content to be rendered
      *
      * @return true if the operation was successful and false otherwise.
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the html is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @see #setUrl
      *
      * @since 3.0
      */
     public boolean setText(String html) {
      checkWidget();
      if (html == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);

      /*
       * If the html field is non-null then the about:blank page is already
       * being loaded, so no Stop or Navigate is required. Just set the html
       * that is to be shown.
       */
      boolean blankLoading = this.html != null;
      this.html = html;
      if (blankLoading)
       return true;

      /*
       * Navigate to the blank page and insert the given html when receiving
       * the next DocumentComplete notification. See the MSDN article "Loading
       * HTML content from a Stream".
       *
       * Note. Stop any pending request. This is required to avoid displaying
       * a blank page as a result of consecutive calls to setUrl and/or
       * setText. The previous request would otherwise render the new html
       * content and reset the html field before the browser actually
       * navigates to the blank page as requested below.
       *
       * Feature in Internet Explorer. Stopping pending requests when no
       * request is pending causes a default page 'Action cancelled' to be
       * displayed. The workaround is to not invoke 'stop' when no request has
       * been set since that instance was created.
       */
      int[] rgdispid;
      if (navigate) {
       /*
        * Stopping the loading of a page causes DocumentComplete events
        * from previous requests to be received before the DocumentComplete
        * for this page. In such cases we must be sure to not set the html
        * into the browser too soon, since doing so could result in its
        * page being cleared out by a subsequent DocumentComplete. The
        * Browser's ReadyState can be used to determine whether these extra
        * events will be received or not.
        */
       rgdispid = auto.getIDsOfNames(new String[] { "ReadyState" }); //$NON-NLS-1$
       Variant pVarResult = auto.getProperty(rgdispid[0]);
       if (pVarResult == null)
        return false;
       delaySetText = pVarResult.getInt() != READYSTATE_COMPLETE;
       pVarResult.dispose();
       rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
       auto.invoke(rgdispid[0]);
      }
      rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
      navigate = true;
      Variant[] rgvarg = new Variant[1];
      rgvarg[0] = new Variant(ABOUT_BLANK);
      int[] rgdispidNamedArgs = new int[1];
      rgdispidNamedArgs[0] = rgdispid[1];
      Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
      rgvarg[0].dispose();
      if (pVarResult == null)
       return false;
      boolean result = pVarResult.getType() == OLE.VT_EMPTY;
      pVarResult.dispose();
      return result;
     }

     /**
      * Loads a URL.
      *
      * @param url
      *            the URL to be loaded
      *
      * @return true if the operation was successful and false otherwise.
      *
      * @exception IllegalArgumentException
      *                <ul>
      *                <li>ERROR_NULL_ARGUMENT - if the url is null</li>
      *                </ul>
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @see #getUrl
      *
      * @since 3.0
      */
     public boolean setUrl(String url) {
      checkWidget();
      if (url == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      html = null;

      /*
       * Bug in Internet Explorer. For some reason, Navigating to an xml
       * document before a previous Navigate has completed will leave the
       * Browser in a bad state if the Navigate to the xml document does not
       * complete. This bad state causes a GP when the parent window is
       * eventually disposed. The workaround is to issue a Stop before
       * navigating to any xml document.
       */
      if (url.endsWith(".xml")) { //$NON-NLS-1$
       /*
        * Feature in Internet Explorer. Stopping pending requests when no
        * request has been issued causes a default 'Action cancelled' page
        * to be displayed. Since Stop must be issued here, the workaround
        * is to first Navigate to the about:blank page before issuing Stop
        * so that the 'Action cancelled' page is not displayed.
        */
       if (!navigate) {
        int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
        Variant[] rgvarg = new Variant[1];
        rgvarg[0] = new Variant(ABOUT_BLANK);
        int[] rgdispidNamedArgs = new int[1];
        rgdispidNamedArgs[0] = rgdispid[1];
        auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
        rgvarg[0].dispose();
       }
       int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
       auto.invoke(rgdispid[0]);
      }

      int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
      navigate = true;
      Variant[] rgvarg = new Variant[1];
      rgvarg[0] = new Variant(url);
      int[] rgdispidNamedArgs = new int[1];
      rgdispidNamedArgs[0] = rgdispid[1];
      Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
      rgvarg[0].dispose();
      if (pVarResult == null)
       return false;
      boolean result = pVarResult.getType() == OLE.VT_EMPTY;
      pVarResult.dispose();
      return result;
     }


     public boolean setUrl(String url, String postData) {
      checkWidget();
      if (url == null)
       SWT.error(SWT.ERROR_NULL_ARGUMENT);
      html = null;

      /*
       * Bug in Internet Explorer. For some reason, Navigating to an xml
       * document before a previous Navigate has completed will leave the
       * Browser in a bad state if the Navigate to the xml document does not
       * complete. This bad state causes a GP when the parent window is
       * eventually disposed. The workaround is to issue a Stop before
       * navigating to any xml document.
       */
      if (url.endsWith(".xml")) { //$NON-NLS-1$
       /*
        * Feature in Internet Explorer. Stopping pending requests when no
        * request has been issued causes a default 'Action cancelled' page
        * to be displayed. Since Stop must be issued here, the workaround
        * is to first Navigate to the about:blank page before issuing Stop
        * so that the 'Action cancelled' page is not displayed.
        */
       if (!navigate) {
        int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); //$NON-NLS-1$ //$NON-NLS-2$
        Variant[] rgvarg = new Variant[1];
        rgvarg[0] = new Variant(ABOUT_BLANK);
        int[] rgdispidNamedArgs = new int[1];
        rgdispidNamedArgs[0] = rgdispid[1];
        auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);
        rgvarg[0].dispose();
       }
       int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
       auto.invoke(rgdispid[0]);
      }

      int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL", "PostData" }); //$NON-NLS-1$ //$NON-NLS-2$
      navigate = true;
      Variant[] rgvarg = new Variant[2];
      rgvarg[0] = new Variant(url);
      rgvarg[1] = writeSafeArray(postData);
      int[] rgdispidNamedArgs = new int[2];
      rgdispidNamedArgs[0] = rgdispid[1];
      rgdispidNamedArgs[1] = rgdispid[2];
      Variant pVarResult = auto.invoke(rgdispid[0], rgvarg, rgdispidNamedArgs);

    //  int[] rgdispid = automation.getIDsOfNames(new String[] { "Navigate", "URL", "PostData" });
    //  int dispIdMember = rgdispid[0];
    //  Variant[] rgvarg = new Variant[2];
    //  rgvarg[0] = new Variant(text.getText());
    //  rgvarg[1] = writeSafeArray("hello world");
    //  int[] rgdispidNamedArgs = new int[2];
    //  rgdispidNamedArgs[0] = rgdispid[1];
    //  rgdispidNamedArgs[1] = rgdispid[2];
    //  automation.invoke(dispIdMember, rgvarg, rgdispidNamedArgs);

      rgvarg[0].dispose();
      if (pVarResult == null)
       return false;
      boolean result = pVarResult.getType() == OLE.VT_EMPTY;
      pVarResult.dispose();
      return result;
     }

     /**
      * Stop any loading and rendering activity.
      *
      * @exception SWTException
      *                <ul>
      *                <li>ERROR_THREAD_INVALID_ACCESS when called from the
      *                wrong thread</li>
      *                <li>ERROR_WIDGET_DISPOSED when the widget has been
      *                disposed</li>
      *                </ul>
      *
      * @since 3.0
      */
     public void stop() {
      checkWidget();
      int[] rgdispid = auto.getIDsOfNames(new String[] { "Stop" }); //$NON-NLS-1$
      auto.invoke(rgdispid[0]);
     }

     static String readSafeArray(Variant variantByRef) {
      // Read a safearray that contains data of
      // type VT_UI1 (unsigned shorts) which contains
      // a text stream.
      int pPostData = variantByRef.getByRef();
      short[] vt_type = new short[1];
      OS.MoveMemory(vt_type, pPostData, 2);
      String result = null;
      if (vt_type[0] == (short) (OLE.VT_BYREF | OLE.VT_VARIANT)) {
       int[] pVariant = new int[1];
       OS.MoveMemory(pVariant, pPostData + 8, 4);
       vt_type = new short[1];
       OS.MoveMemory(vt_type, pVariant[0], 2);
       if (vt_type[0] == (short) (OLE.VT_ARRAY | OLE.VT_UI1)) {
        int[] pSafearray = new int[1];
        OS.MoveMemory(pSafearray, pVariant[0] + 8, 4);
        short[] cDims = new short[1];
        OS.MoveMemory(cDims, pSafearray[0], 2);
        int[] pvData = new int[1];
        OS.MoveMemory(pvData, pSafearray[0] + 12, 4);
        int safearrayboundOffset = 0;
        for (int i = 0; i < cDims[0]; i++) {
         int[] cElements = new int[1];
         OS.MoveMemory(cElements, pSafearray[0] + 16 + safearrayboundOffset, 4);
         safearrayboundOffset += 8;
         int cchWideChar = OS.MultiByteToWideChar(CodePage, OS.MB_PRECOMPOSED, pvData[0], -1, null, 0);
         if (cchWideChar == 0)
          return null;
         char[] lpWideCharStr = new char[cchWideChar - 1];
         OS.MultiByteToWideChar(CodePage, OS.MB_PRECOMPOSED, pvData[0], -1, lpWideCharStr,
           lpWideCharStr.length);
         result = new String(lpWideCharStr);
        }
       }
      }
      return result;
     }

     static Variant writeSafeArray(String string) {
      // Create a one dimensional safearray containing two VT_UI1 values
      // where VT_UI1 is an unsigned char

      // Define cDims, fFeatures and cbElements
      short cDims = 1;
      short FADF_FIXEDSIZE = 0x10;
      short FADF_HAVEVARTYPE = 0x80;
      short fFeatures = (short) (FADF_FIXEDSIZE | FADF_HAVEVARTYPE);
      int cbElements = 1;
      // Create a pointer and copy the data into it
      int count = string.length();
      char[] chars = new char[count + 1];
      string.getChars(0, count, chars, 0);
      int cchMultiByte = OS.WideCharToMultiByte(CodePage, 0, chars, -1, null, 0, null, null);
      if (cchMultiByte == 0)
       return null;
      int pvData = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
      OS.WideCharToMultiByte(CodePage, 0, chars, -1, pvData, cchMultiByte, null, null);
      int cElements1 = cchMultiByte;
      int lLbound1 = 0;
      // Create a safearray in memory
      // 12 bytes for cDims, fFeatures and cbElements + 4 bytes for pvData +
      // number of dimensions * (size of safearraybound)
      int sizeofSafeArray = 12 + 4 + 1 * 8;
      int pSafeArray = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, sizeofSafeArray);
      // Copy the data into the safe array
      int offset = 0;
      OS.MoveMemory(pSafeArray + offset, new short[] { cDims }, 2);
      offset += 2;
      OS.MoveMemory(pSafeArray + offset, new short[] { fFeatures }, 2);
      offset += 2;
      OS.MoveMemory(pSafeArray + offset, new int[] { cbElements }, 4);
      offset += 4;
      OS.MoveMemory(pSafeArray + offset, new int[] { 0 }, 4);
      offset += 4;
      OS.MoveMemory(pSafeArray + offset, new int[] { pvData }, 4);
      offset += 4;
      OS.MoveMemory(pSafeArray + offset, new int[] { cElements1 }, 4);
      offset += 4;
      OS.MoveMemory(pSafeArray + offset, new int[] { lLbound1 }, 4);
      offset += 4;
      // Create a variant in memory to hold the safearray
      int pVariant = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, Variant.sizeof);
      short vt = (short) (OLE.VT_ARRAY | OLE.VT_UI1);
      OS.MoveMemory(pVariant, new short[] { vt }, 2);
      OS.MoveMemory(pVariant + 8, new int[] { pSafeArray }, 4);
      // Create a by ref variant
      Variant variantByRef = new Variant(pVariant, (short) (OLE.VT_BYREF | OLE.VT_VARIANT));
      return variantByRef;
     }

     public int getBrowserId() {
      return this.browserId;
     }

     public String getText() {
      return _text;
     }

     /**
      * Modified by TMB on 8/15/2005
      *
      * Sets the html between the root node of the Document automation object.
      * The root node will generally start at the <HTML> node
      *
      * From MSDN: With Internet Explorer 6 and later, when you use the !DOCTYPE
      * declaration to specify standards-compliant mode, this element represents
      * the canvas—the entire surface onto which a document's contents can be
      * rendered. When you switch on standards-compliant mode, this element also
      * becomes the positioning container for positioned elements that don't have
      * a positioned parent. When the !DOCTYPE declaration does not specify
      * standards-compliant mode, and with earler versions of Internet Explorer,
      * the body object represents the entire surface onto which a document's
      * contents can be rendered.
      *
      * By retrieving the documentElement, we do not care what tag represents the
      * canvas. This method allows us to take what we are given and work with it,
      * including malformed HTML.
      *
      */
     private void setHTML() {
      Variant pVarResult = null;
      OleAutomation autox = null;
      int[] rgdispid = auto.getIDsOfNames(new String[] { "Document" }); //$NON-NLS-1$
      if (rgdispid != null) {
       pVarResult = auto.getProperty(rgdispid[0]);
       autox = pVarResult.getAutomation();
       rgdispid = autox.getIDsOfNames(new String[] { "documentElement" });
       if (rgdispid != null) {
        pVarResult = autox.getProperty(rgdispid[0]);
        autox = pVarResult.getAutomation();
        rgdispid = autox.getIDsOfNames(new String[] { "innerHTML" });
        if (rgdispid != null) {
         pVarResult = autox.getProperty(rgdispid[0]);
         _text = pVarResult.getString();
        }
       }
      }
      // be sure to dispose of any native references so that Release() is
      // called on their IUnknown pointer
      if (pVarResult != null) {
       pVarResult.dispose();
      }
      if (autox != null) {
       autox.dispose();
      }
     }
    }


    posted on 2008-04-10 22:35 seal 閱讀(1246) 評論(0)  編輯  收藏 所屬分類: Eclipse SWT/JFace RCP
    主站蜘蛛池模板: 亚洲国产一区二区三区青草影视| 亚洲成AV人影片在线观看| 国产精品免费看香蕉| 7723日本高清完整版免费| 999久久久免费精品播放| 中文字幕乱码一区二区免费| 中文字幕在线视频免费| rh男男车车的车车免费网站| 免费人成网上在线观看| 日本免费精品一区二区三区| 可以免费观看的国产视频| 成人性做爰aaa片免费看| 国产一卡二卡四卡免费| 免费看一级做a爰片久久| 免费一级一片一毛片| 日韩亚洲国产综合久久久| 一区二区三区亚洲视频| 亚洲第一AAAAA片| 久久狠狠高潮亚洲精品| 亚洲伊人精品综合在合线| 99热亚洲色精品国产88| 亚洲日韩精品无码AV海量| 亚洲a∨无码一区二区| 狼色精品人妻在线视频免费| 亚洲一区二区三区免费| 中文字幕在线免费观看| 男女免费观看在线爽爽爽视频 | 18观看免费永久视频| 2022久久国产精品免费热麻豆| 麻豆成人精品国产免费| jjzz亚洲亚洲女人| 久久精品国产亚洲av麻豆色欲| 国产精品亚洲专区一区| 国产一级黄片儿免费看| 欧美大尺寸SUV免费| 四虎影视永久免费观看地址| 色拍自拍亚洲综合图区| 黄网站色视频免费观看45分钟| 亚洲成人免费电影| 亚洲最大av无码网址| 亚洲欧洲日产国产综合网|