/******************************************************************************* * Copyright (c) 2000, 2010 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 org.eclipse.swt.ole.win32; import org.eclipse.swt.*; import org.eclipse.swt.internal.ole.win32.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.internal.*; import java.util.Vector; /** * * OleFrame is an OLE Container's top level frame. * *
This object implements the OLE Interfaces IUnknown and IOleInPlaceFrame * *
OleFrame allows the container to do the following:
When an OLE Document is in-place active, the Document provides its own menus but the application * is given the opportunity to merge some of its menus into the menubar. The application * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window * (far right just before Help). The OLE Document retains control of the Edit, Object and Help * menu locations. Note that an application can insert more than one menu into a single location. * * @return the application menu items that will appear in the Container location when an OLE Document * is in-place activated. * */ public MenuItem[] getContainerMenus(){ return containerMenuItems; } /** * * Returns the application menu items that will appear in the File location when an OLE Document * is in-place activated. * *
When an OLE Document is in-place active, the Document provides its own menus but the application * is given the opportunity to merge some of its menus into the menubar. The application * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window * (far right just before Help). The OLE Document retains control of the Edit, Object and Help * menu locations. Note that an application can insert more than one menu into a single location. * * @return the application menu items that will appear in the File location when an OLE Document * is in-place activated. * */ public MenuItem[] getFileMenus(){ return fileMenuItems; } int /*long*/ getIOleInPlaceFrame() { return iOleInPlaceFrame.getAddress(); } private int /*long*/ getMenuItemID(int /*long*/ hMenu, int index) { int /*long*/ id = 0; MENUITEMINFO lpmii = new MENUITEMINFO(); lpmii.cbSize = MENUITEMINFO.sizeof; lpmii.fMask = OS.MIIM_STATE | OS.MIIM_SUBMENU | OS.MIIM_ID; OS.GetMenuItemInfo(hMenu, index, true, lpmii); if ((lpmii.fState & OS.MF_POPUP) == OS.MF_POPUP) { id = lpmii.hSubMenu; } else { id = lpmii.wID; } return id; } private int GetWindow(int /*long*/ phwnd) { if (phwnd != 0) { COM.MoveMemory(phwnd, new int /*long*/[] {handle}, OS.PTR_SIZEOF); } return COM.S_OK; } /** * * Returns the application menu items that will appear in the Window location when an OLE Document * is in-place activated. * *
When an OLE Document is in-place active, the Document provides its own menus but the application * is given the opportunity to merge some of its menus into the menubar. The application * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window * (far right just before Help). The OLE Document retains control of the Edit, Object and Help * menu locations. Note that an application can insert more than one menu into a single location. * * @return the application menu items that will appear in the Window location when an OLE Document * is in-place activated. * */ public MenuItem[] getWindowMenus(){ return windowMenuItems; } private int InsertMenus(int /*long*/ hmenuShared, int /*long*/ lpMenuWidths) { // locate menu bar Menu menubar = getShell().getMenuBar(); if (menubar == null || menubar.isDisposed()) { COM.MoveMemory(lpMenuWidths, new int[] {0}, 4); return COM.S_OK; } int /*long*/ hMenu = menubar.handle; // Create a holder for menu information. This will be passed down to // the OS and the OS will fill in the requested information for each menu. MENUITEMINFO lpmii = new MENUITEMINFO(); int /*long*/ hHeap = OS.GetProcessHeap(); int cch = 128; int byteCount = cch * TCHAR.sizeof; int /*long*/ pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount); lpmii.cbSize = MENUITEMINFO.sizeof; lpmii.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_SUBMENU | OS.MIIM_DATA; lpmii.dwTypeData = pszText; lpmii.cch = cch; // Loop over all "File-like" menus in the menubar and get information about the // item from the OS. int fileMenuCount = 0; int newindex = 0; if (this.fileMenuItems != null) { for (int i = 0; i < this.fileMenuItems.length; i++) { MenuItem item = this.fileMenuItems[i]; if (item != null) { int index = item.getParent().indexOf(item); lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the // exact number of characters in name. Reset it to our max size // before each call. if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) { if (OS.InsertMenuItem(hmenuShared, newindex, true, lpmii)) { // keep track of the number of items fileMenuCount++; newindex++; } } } } } // copy the menu item count information to the pointer COM.MoveMemory(lpMenuWidths, new int[] {fileMenuCount}, 4); // Loop over all "Container-like" menus in the menubar and get information about the // item from the OS. int containerMenuCount = 0; if (this.containerMenuItems != null) { for (int i = 0; i < this.containerMenuItems.length; i++) { MenuItem item = this.containerMenuItems[i]; if (item != null) { int index = item.getParent().indexOf(item); lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the // exact number of characters in name. Reset it to a large number // before each call. if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) { if (OS.InsertMenuItem(hmenuShared, newindex, true, lpmii)) { // keep track of the number of items containerMenuCount++; newindex++; } } } } } // copy the menu item count information to the pointer COM.MoveMemory(lpMenuWidths + 8, new int[] {containerMenuCount}, 4); // Loop over all "Window-like" menus in the menubar and get information about the // item from the OS. int windowMenuCount = 0; if (this.windowMenuItems != null) { for (int i = 0; i < this.windowMenuItems.length; i++) { MenuItem item = this.windowMenuItems[i]; if (item != null) { int index = item.getParent().indexOf(item); lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the // exact number of characters in name. Reset it to a large number // before each call. if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) { if (OS.InsertMenuItem(hmenuShared, newindex, true, lpmii)) { // keep track of the number of items windowMenuCount++; newindex++; } } } } } // copy the menu item count information to the pointer COM.MoveMemory(lpMenuWidths + 16, new int[] {windowMenuCount}, 4); // free resources used in querying the OS if (pszText != 0) OS.HeapFree(hHeap, 0, pszText); return COM.S_OK; } void onActivate(Event e) { if (objIOleInPlaceActiveObject != null) { objIOleInPlaceActiveObject.OnFrameWindowActivate(true); } } void onDeactivate(Event e) { if (objIOleInPlaceActiveObject != null) { objIOleInPlaceActiveObject.OnFrameWindowActivate(false); } } private void onDispose(Event e) { releaseObjectInterfaces(); currentdoc = null; this.Release(); removeListener(SWT.Activate, listener); removeListener(SWT.Deactivate, listener); removeListener(SWT.Dispose, listener); removeListener(SWT.Resize, listener); removeListener(SWT.Move, listener); } private void onResize(Event e) { if (objIOleInPlaceActiveObject != null) { RECT lpRect = new RECT(); OS.GetClientRect(handle, lpRect); objIOleInPlaceActiveObject.ResizeBorder(lpRect, iOleInPlaceFrame.getAddress(), true); } } private int QueryInterface(int /*long*/ riid, int /*long*/ ppvObject) { // implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG; GUID guid = new GUID(); COM.MoveMemory(guid, riid, GUID.sizeof); if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame) ) { COM.MoveMemory(ppvObject, new int /*long*/ [] {iOleInPlaceFrame.getAddress()}, OS.PTR_SIZEOF); AddRef(); return COM.S_OK; } COM.MoveMemory(ppvObject, new int /*long*/ [] {0}, OS.PTR_SIZEOF); return COM.E_NOINTERFACE; } /** * Decrement the count of references to this instance * * @return the current reference count */ int Release() { refCount--; if (refCount == 0){ disposeCOMInterfaces(); if (COM.FreeUnusedLibraries) { COM.CoFreeUnusedLibraries(); } } return refCount; } private void releaseObjectInterfaces() { if (objIOleInPlaceActiveObject != null) { objIOleInPlaceActiveObject.Release(); } objIOleInPlaceActiveObject = null; } private int RemoveMenus(int /*long*/ hmenuShared) { Menu menubar = getShell().getMenuBar(); if (menubar == null || menubar.isDisposed()) return COM.S_FALSE; int /*long*/ hMenu = menubar.handle; Vector ids = new Vector(); if (this.fileMenuItems != null) { for (int i = 0; i < this.fileMenuItems.length; i++) { MenuItem item = this.fileMenuItems[i]; if (item != null && !item.isDisposed()) { int index = item.getParent().indexOf(item); // get Id from original menubar int /*long*/ id = getMenuItemID(hMenu, index); ids.addElement(new LONG(id)); } } } if (this.containerMenuItems != null) { for (int i = 0; i < this.containerMenuItems.length; i++) { MenuItem item = this.containerMenuItems[i]; if (item != null && !item.isDisposed()) { int index = item.getParent().indexOf(item); int /*long*/ id = getMenuItemID(hMenu, index); ids.addElement(new LONG(id)); } } } if (this.windowMenuItems != null) { for (int i = 0; i < this.windowMenuItems.length; i++) { MenuItem item = this.windowMenuItems[i]; if (item != null && !item.isDisposed()) { int index = item.getParent().indexOf(item); int /*long*/ id = getMenuItemID(hMenu, index); ids.addElement(new LONG(id)); } } } int index = OS.GetMenuItemCount(hmenuShared) - 1; for (int i = index; i >= 0; i--) { int /*long*/ id = getMenuItemID(hmenuShared, i); if (ids.contains(new LONG(id))){ OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION); } } return COM.S_OK; } private int RequestBorderSpace(int /*long*/ pborderwidths) { return COM.S_OK; } int SetActiveObject(int /*long*/ pActiveObject, int /*long*/ pszObjName) { if (objIOleInPlaceActiveObject != null) { objIOleInPlaceActiveObject.Release(); objIOleInPlaceActiveObject = null; } if (pActiveObject != 0) { objIOleInPlaceActiveObject = new IOleInPlaceActiveObject(pActiveObject); objIOleInPlaceActiveObject.AddRef(); } return COM.S_OK; } private int SetBorderSpace(int /*long*/ pborderwidths) { // A Control/Document can : // Use its own toolbars, requesting border space of a specific size, or, // Use no toolbars, but force the container to remove its toolbars by passing a // valid BORDERWIDTHS structure containing nothing but zeros in the pborderwidths parameter, or, // Use no toolbars but allow the in-place container to leave its toolbars up by // passing NULL as the pborderwidths parameter. if (objIOleInPlaceActiveObject == null) return COM.S_OK; RECT borderwidth = new RECT(); if (pborderwidths == 0 || currentdoc == null ) return COM.S_OK; COM.MoveMemory(borderwidth, pborderwidths, RECT.sizeof); currentdoc.setBorderSpace(borderwidth); return COM.S_OK; } /** * * Specify the menu items that should appear in the Container location when an OLE Document * is in-place activated. * *
When an OLE Document is in-place active, the Document provides its own menus but the application * is given the opportunity to merge some of its menus into the menubar. The application * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window * (far right just before Help). The OLE Document retains control of the Edit, Object and Help * menu locations. Note that an application can insert more than one menu into a single location. * *
This method must be called before in place activation of the OLE Document. After the Document * is activated, the menu bar will not be modified until a subsequent activation. * * @param containerMenus an array of top level MenuItems to be inserted into the Container location of * the menubar */ public void setContainerMenus(MenuItem[] containerMenus){ containerMenuItems = containerMenus; } OleClientSite getCurrentDocument() { return currentdoc; } void setCurrentDocument(OleClientSite doc) { currentdoc = doc; if (currentdoc != null && objIOleInPlaceActiveObject != null) { RECT lpRect = new RECT(); OS.GetClientRect(handle, lpRect); objIOleInPlaceActiveObject.ResizeBorder(lpRect, iOleInPlaceFrame.getAddress(), true); } } /** * * Specify the menu items that should appear in the File location when an OLE Document * is in-place activated. * *
When an OLE Document is in-place active, the Document provides its own menus but the application * is given the opportunity to merge some of its menus into the menubar. The application * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window * (far right just before Help). The OLE Document retains control of the Edit, Object and Help * menu locations. Note that an application can insert more than one menu into a single location. * *
This method must be called before in place activation of the OLE Document. After the Document * is activated, the menu bar will not be modified until a subsequent activation. * * @param fileMenus an array of top level MenuItems to be inserted into the File location of * the menubar */ public void setFileMenus(MenuItem[] fileMenus){ fileMenuItems = fileMenus; } private int SetMenu(int /*long*/ hmenuShared, int /*long*/ holemenu, int /*long*/ hwndActiveObject) { int /*long*/ inPlaceActiveObject = 0; if (objIOleInPlaceActiveObject != null) inPlaceActiveObject = objIOleInPlaceActiveObject.getAddress(); Menu menubar = getShell().getMenuBar(); if (menubar == null || menubar.isDisposed()){ return COM.OleSetMenuDescriptor(0, getShell().handle, hwndActiveObject, iOleInPlaceFrame.getAddress(), inPlaceActiveObject); } int /*long*/ handle = menubar.getShell().handle; if (hmenuShared == 0 && holemenu == 0) { // re-instate the original menu - this occurs on deactivation hmenuShared = menubar.handle; } if (hmenuShared == 0) return COM.E_FAIL; OS.SetMenu(handle, hmenuShared); OS.DrawMenuBar(handle); return COM.OleSetMenuDescriptor(holemenu, handle, hwndActiveObject, iOleInPlaceFrame.getAddress(), inPlaceActiveObject); } /** * * Set the menu items that should appear in the Window location when an OLE Document * is in-place activated. * *
When an OLE Document is in-place active, the Document provides its own menus but the application * is given the opportunity to merge some of its menus into the menubar. The application * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window * (far right just before Help). The OLE Document retains control of the Edit, Object and Help * menu locations. Note that an application can insert more than one menu into a single location. * *
This method must be called before in place activation of the OLE Document. After the Document * is activated, the menu bar will not be modified until a subsequent activation. * * @param windowMenus an array of top level MenuItems to be inserted into the Window location of * the menubar */ public void setWindowMenus(MenuItem[] windowMenus){ windowMenuItems = windowMenus; } private boolean translateOleAccelerator(MSG msg) { if (objIOleInPlaceActiveObject == null) return false; int result = objIOleInPlaceActiveObject.TranslateAccelerator(msg); return (result != COM.S_FALSE && result != COM.E_NOTIMPL); } private int TranslateAccelerator(int /*long*/ lpmsg, int wID){ Menu menubar = getShell().getMenuBar(); if (menubar == null || menubar.isDisposed() || !menubar.isEnabled()) return COM.S_FALSE; if (wID < 0) return COM.S_FALSE; Shell shell = menubar.getShell(); int /*long*/ hwnd = shell.handle; int /*long*/ hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0); if (hAccel == 0) return COM.S_FALSE; MSG msg = new MSG(); OS.MoveMemory(msg, lpmsg, MSG.sizeof); int result = OS.TranslateAccelerator(hwnd, hAccel, msg); return result == 0 ? COM.S_FALSE : COM.S_OK; } }