最近用到了SWT
中的Browser类,这个类不允许被继承,在网上搜索的时候发现了下面的帖子。这个类实际上是使用OLE,将IE直接嵌套进SWT程序中去。下面代码的
修改实际上将SWT中的WebBrowser类的子类IE直接和Browser
类合到一起,而同时也就没有了原来SWT中的跨平台的优点。该作者添加了setHtml这个函数和_text属性。从而得到对应的网页的html内容。
/*******************************************************************************
* 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 = "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab"; //$NON-NLS-1$
/* 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是我自己创建的类,没有必要用
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();
}
}
}