📄 oleframe.java
字号:
/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-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. * * <p>This object implements the OLE Interfaces IUnknown and IOleInPlaceFrame * * <p>OleFrame allows the container to do the following: <ul> * <li>position and size the ActiveX Control or OLE Document within the application * <li>insert menu items from the application into the OLE Document's menu * <li>activate and deactivate the OLE Document's menus * <li>position the OLE Document's menu in the application * <li>translate accelerator keystrokes intended for the container's frame</ul> * * <dl> * <dt><b>Styles</b> <dd>BORDER * <dt><b>Events</b> <dd>Dispose, Move, Resize * </dl> * */final public class OleFrame extends Composite{ // Interfaces for this Ole Client Container private COMObject iUnknown; private COMObject iOleInPlaceFrame; // Access to the embedded/linked Ole Object private IOleInPlaceActiveObject objIOleInPlaceActiveObject; private OleClientSite currentdoc; private int refCount = 0; private MenuItem[] fileMenuItems; private MenuItem[] containerMenuItems; private MenuItem[] windowMenuItems; private Listener listener; private static String CHECK_FOCUS = "OLE_CHECK_FOCUS"; //$NON-NLS-1$ private static String HHOOK = "OLE_HHOOK"; //$NON-NLS-1$ private static String HHOOKMSG = "OLE_HHOOK_MSG"; //$NON-NLS-1$ /** * Create an OleFrame child widget using style bits * to select a particular look or set of properties. * * @param parent a composite widget (cannot be null) * @param style the bitwise OR'ing of widget styles * * @exception SWTError * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread * <li>ERROR_NULL_ARGUMENT when the parent is null * <li>ERROR_INTERFACES_NOT_INITIALIZED when unable to create callbacks for OLE Interfaces</ul> * */public OleFrame(Composite parent, int style) { // set up widget attributes super(parent, style | SWT.CLIP_CHILDREN | SWT.CLIP_SIBLINGS); createCOMInterfaces(); // setup cleanup proc listener = new Listener() { public void handleEvent(Event e) { switch (e.type) { case SWT.Dispose : onDispose(e); break; case SWT.Resize : case SWT.Move : onResize(e); break; default : OLE.error(SWT.ERROR_NOT_IMPLEMENTED); } } }; addListener(SWT.Dispose, listener); // inform inplaceactiveobject whenever frame resizes addListener(SWT.Resize, listener); // inform inplaceactiveobject whenever frame moves addListener(SWT.Move, listener); // Maintain a reference to yourself so that when // ClientSites close, they don't take the frame away // with them. this.AddRef(); // Check for focus change Display display = getDisplay(); initCheckFocus(display); initMsgHook(display);}private static void initCheckFocus (final Display display) { if (display.getData(CHECK_FOCUS) != null) return; display.setData(CHECK_FOCUS, CHECK_FOCUS); final int time = 50; final Runnable[] timer = new Runnable[1]; final Control[] lastFocus = new Control[1]; timer[0] = new Runnable() { public void run() { if (lastFocus[0] instanceof OleClientSite && !lastFocus[0].isDisposed()) { // ignore popup menus and dialogs int hwnd = OS.GetFocus(); while (hwnd != 0) { int ownerHwnd = OS.GetWindow(hwnd, 4/*GW_OWNER*/); if (ownerHwnd != 0) { display.timerExec(time, timer[0]); return; } hwnd = OS.GetParent(hwnd); } } if (lastFocus[0] == null || lastFocus[0].isDisposed() || !lastFocus[0].isFocusControl()) { Control currentFocus = display.getFocusControl(); if (currentFocus instanceof OleFrame) { OleFrame frame = (OleFrame) currentFocus; currentFocus = frame.getCurrentDocument(); } if (lastFocus[0] != currentFocus) { Event event = new Event(); if (lastFocus[0] instanceof OleClientSite && !lastFocus[0].isDisposed()) { lastFocus[0].notifyListeners (SWT.FocusOut, event); } if (currentFocus instanceof OleClientSite && !currentFocus.isDisposed()) { currentFocus.notifyListeners(SWT.FocusIn, event); } } lastFocus[0] = currentFocus; } display.timerExec(time, timer[0]); } }; display.timerExec(time, timer[0]);}private static void initMsgHook(Display display) { if (display.getData(HHOOK) != null) return; final Callback callback = new Callback(OleFrame.class, "getMsgProc", 3); //$NON-NLS-1$ int address = callback.getAddress(); int threadId = OS.GetCurrentThreadId(); final int hHook = OS.SetWindowsHookEx(OS.WH_GETMESSAGE, address, 0, threadId); if (hHook == 0) { callback.dispose(); return; } display.setData(HHOOK, new Integer(hHook)); display.setData(HHOOKMSG, new MSG()); display.disposeExec(new Runnable() { public void run() { if (hHook != 0) OS.UnhookWindowsHookEx(hHook); if (callback != null) callback.dispose(); } });}static int getMsgProc(int code, int wParam, int lParam) { Display display = Display.getCurrent(); if (display == null) return 0; Integer hHook = (Integer)display.getData(HHOOK); if (hHook == null) return 0; if (code < 0) { return OS.CallNextHookEx(hHook.intValue(), code, wParam, lParam); } MSG msg = (MSG)display.getData(HHOOKMSG); OS.MoveMemory(msg, lParam, MSG.sizeof); int message = msg.message; if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) { if (display != null) { Widget widget = null; int hwnd = msg.hwnd; while (hwnd != 0) { widget = display.findWidget (hwnd); if (widget != null) break; hwnd = OS.GetParent (hwnd); } if (widget != null && widget instanceof OleClientSite) { OleClientSite site = (OleClientSite)widget; if (site.handle == hwnd) { /* * Do not allow the activeX control to translate events * when a menu is active. */ int thread = OS.GetWindowThreadProcessId(msg.hwnd, null); GUITHREADINFO lpgui = new GUITHREADINFO(); lpgui.cbSize = GUITHREADINFO.sizeof; boolean rc = OS.GetGUIThreadInfo(thread, lpgui); int mask = OS.GUI_INMENUMODE | OS.GUI_INMOVESIZE | OS.GUI_POPUPMENUMODE | OS.GUI_SYSTEMMENUMODE; if (!rc || (lpgui.flags & mask) == 0) { OleFrame frame = site.frame; if (frame.translateOleAccelerator(msg)) { // In order to prevent this message from also being processed // by the application, zero out message, wParam and lParam msg.message = OS.WM_NULL; msg.wParam = 0; msg.lParam = 0; OS.MoveMemory(lParam, msg, MSG.sizeof); return 0; } } } } } } return OS.CallNextHookEx(hHook.intValue(), code, wParam, lParam);}/** * Increment the count of references to this instance * * @return the current reference count */int AddRef() { refCount++; return refCount;}private int ContextSensitiveHelp(int fEnterMode) { return COM.S_OK;}private void createCOMInterfaces() { // Create each of the interfaces that this object implements iUnknown = new COMObject(new int[]{2, 0, 0}){ public int method0(int[] args) {return QueryInterface(args[0], args[1]);} public int method1(int[] args) {return AddRef();} public int method2(int[] args) {return Release();} }; iOleInPlaceFrame = new COMObject(new int[]{2, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 1, 1, 1, 2}){ public int method0(int[] args) {return QueryInterface(args[0], args[1]);} public int method1(int[] args) {return AddRef();} public int method2(int[] args) {return Release();} public int method3(int[] args) {return GetWindow(args[0]);} public int method4(int[] args) {return ContextSensitiveHelp(args[0]);} public int method5(int[] args) {return GetBorder(args[0]);} public int method6(int[] args) {return RequestBorderSpace(args[0]);} public int method7(int[] args) {return SetBorderSpace(args[0]);} public int method8(int[] args) {return SetActiveObject(args[0], args[1]);} public int method9(int[] args) {return InsertMenus(args[0], args[1]);} public int method10(int[] args) {return SetMenu(args[0], args[1], args[2]);} public int method11(int[] args) {return RemoveMenus(args[0]);} // method12 SetStatusText - not implemented // method13 EnableModeless - not implemented public int method14(int[] args) {return TranslateAccelerator(args[0], args[1]);} };}private void disposeCOMInterfaces () { if (iUnknown != null) iUnknown.dispose(); iUnknown = null; if (iOleInPlaceFrame != null) iOleInPlaceFrame.dispose(); iOleInPlaceFrame = null;}private int GetBorder(int lprectBorder) { /* The IOleInPlaceUIWindow::GetBorder function, when called on a document or frame window object, returns the outer rectangle (relative to the window) where the object can put toolbars or similar controls. */ if (lprectBorder == 0) return COM.E_INVALIDARG; RECT rectBorder = new RECT(); // Coordinates must be relative to the window OS.GetClientRect(handle, rectBorder); OS.MoveMemory(lprectBorder, rectBorder, RECT.sizeof); return COM.S_OK;}/** * * Returns the application menu items that will appear in the Container location when an OLE Document * is in-place activated. * * <p>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. * * <p>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 getIOleInPlaceFrame() { return iOleInPlaceFrame.getAddress();}private int getMenuItemID(int hMenu, int index) { int 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 phwnd) { if (phwnd != 0) { COM.MoveMemory(phwnd, new int[] {handle}, 4); } return COM.S_OK;}/** * * Returns the application menu items that will appear in the Window location when an OLE Document * is in-place activated. * * <p>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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -