Java tutorial
/* * Reading and writing to a SAFEARRAY * * This example reads from a PostData object in a BeforeNavigate2 event and * creates a PostData object in a call to Navigate. * * For a list of all SWT example snippets see * http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-swt-home/dev.html#snippets */ import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.internal.win32.OS; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.ole.win32.OLE; import org.eclipse.swt.ole.win32.OleAutomation; import org.eclipse.swt.ole.win32.OleControlSite; import org.eclipse.swt.ole.win32.OleEvent; import org.eclipse.swt.ole.win32.OleFrame; import org.eclipse.swt.ole.win32.OleListener; import org.eclipse.swt.ole.win32.Variant; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class Snippet186 { static int CodePage = OS.GetACP(); public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new GridLayout(2, false)); final Text text = new Text(shell, SWT.BORDER); text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); Button go = new Button(shell, SWT.PUSH); go.setText("Go"); OleFrame oleFrame = new OleFrame(shell, SWT.NONE); oleFrame.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); OleControlSite controlSite; OleAutomation automation; try { controlSite = new OleControlSite(oleFrame, SWT.NONE, "Shell.Explorer"); automation = new OleAutomation(controlSite); controlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE); } catch (SWTException ex) { return; } final OleAutomation auto = automation; go.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { String url = text.getText(); int[] rgdispid = auto.getIDsOfNames(new String[] { "Navigate", "URL" }); int dispIdMember = rgdispid[0]; Variant[] rgvarg = new Variant[1]; rgvarg[0] = new Variant(url); int[] rgdispidNamedArgs = new int[1]; rgdispidNamedArgs[0] = rgdispid[1]; auto.invoke(dispIdMember, rgvarg, rgdispidNamedArgs); } }); // Read PostData whenever we navigate to a site that uses it int BeforeNavigate2 = 0xfa; controlSite.addEventListener(BeforeNavigate2, new OleListener() { public void handleEvent(OleEvent event) { Variant url = event.arguments[1]; Variant postData = event.arguments[4]; if (postData != null) { System.out.println("PostData = " + readSafeArray(postData) + ", URL = " + url.getString()); } } }); // Navigate to this web site which uses post data to fill in the text // field // and put the string "hello world" into the text box text.setText("file://" + Snippet186.class.getResource("Snippet186.html").getFile()); 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); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } // The following structs are accessed in the readSafeArray and // writeSafeArray // functions: // // VARIANT: // short vt // short wReserved1 // short wReserved2 // short wReserved3 // int parray // // SAFEARRAY: // short cDims // Count of dimensions in this array // short fFeatures // Flags used by the SafeArray // int cbElements // Size of an element of the array // int cLocks // Number of times the array has been locked without // corresponding unlock // int pvData // Pointer to the data // SAFEARRAYBOUND[] rgsabound // One bound for each dimension // // SAFEARRAYBOUND: // int cElements // the number of elements in the dimension // int lLbound // the lower bound of the dimension 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; } }