Mercurial > projects > dwt-win
view dwt/ole/win32/OleFrame.d @ 212:ab60f3309436
reverted the char[] to String and use the an alias.
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 05 May 2008 00:12:38 +0200 |
parents | 619faee45ef6 |
children | fd9c62a2998e |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2007 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 * Port to the D programming language: * Frank Benoit <benoit@tionex.de> *******************************************************************************/ module dwt.ole.win32.OleFrame; import dwt.DWT; import dwt.DWTException; import dwt.internal.ole.win32.COM; import dwt.internal.ole.win32.OLEIDL; import dwt.internal.ole.win32.extras; import dwt.internal.win32.OS; import dwt.widgets.Composite; import dwt.widgets.Control; import dwt.widgets.Display; import dwt.widgets.Event; import dwt.widgets.Listener; import dwt.widgets.Menu; import dwt.widgets.MenuItem; import dwt.widgets.Shell; import dwt.widgets.Widget; import dwt.ole.win32.OleClientSite; import dwt.ole.win32.OLE; import dwt.dwthelper.utils; import dwt.dwthelper.Runnable; import tango.core.Array; /** * * 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 : Composite { // Interfaces for this Ole Client Container //private COMObject iUnknown; private _IOleInPlaceFrameImpl 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$ private static bool ignoreNextKey; private static const short [] ACCENTS = [ cast(short)'~', '`', '\'', '^', '"']; private static const String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$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 IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when the parent is null * </ul> * @exception DWTException <ul> * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread * </ul> * */ public this(Composite parent, int style) { super(parent, style); createCOMInterfaces(); // setup cleanup proc listener = new class() Listener { public void handleEvent(Event e) { switch (e.type) { case DWT.Activate : onActivate(e); break; case DWT.Deactivate : onDeactivate(e); break; case DWT.Dispose : onDispose(e); break; case DWT.Resize : case DWT.Move : onResize(e); break; default : OLE.error(DWT.ERROR_NOT_IMPLEMENTED); } } }; addListener(DWT.Activate, listener); addListener(DWT.Deactivate, listener); addListener(DWT.Dispose, listener); // inform inplaceactiveobject whenever frame resizes addListener(DWT.Resize, listener); // inform inplaceactiveobject whenever frame moves addListener(DWT.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 (Display display_) { if (display_.getData(CHECK_FOCUS) !is null) return; display_.setData(CHECK_FOCUS, new ArrayWrapperString(CHECK_FOCUS)); static const int time = 50; auto timer = new class(display_) Runnable { Display display; Control[1] lastFocus; this( Display display){ this.display = display; } public void run() { if (( null !is cast(OleClientSite)lastFocus[0] ) && !lastFocus[0].isDisposed()) { // ignore popup menus and dialogs auto hwnd = OS.GetFocus(); while (hwnd !is null) { auto ownerHwnd = OS.GetWindow(hwnd, OS.GW_OWNER); if (ownerHwnd !is null) { display.timerExec(time, this); return; } hwnd = OS.GetParent(hwnd); } } if (lastFocus[0] is null || lastFocus[0].isDisposed() || !lastFocus[0].isFocusControl()) { Control currentFocus = display.getFocusControl(); if ( auto frame = cast(OleFrame)currentFocus ) { currentFocus = frame.getCurrentDocument(); } if (lastFocus[0] !is currentFocus) { Event event = new Event(); if (( null !is cast(OleClientSite)lastFocus[0] ) && !lastFocus[0].isDisposed()) { lastFocus[0].notifyListeners (DWT.FocusOut, event); } if (( null !is cast(OleClientSite)currentFocus ) && !currentFocus.isDisposed()) { currentFocus.notifyListeners(DWT.FocusIn, event); } } lastFocus[0] = currentFocus; } display.timerExec(time, this); } }; display_.timerExec(time, timer); } private static void initMsgHook(Display display) { if (display.getData(HHOOK) !is null) return; //final Callback callback = new Callback(OleFrame.class, "getMsgProc", 3); //$NON-NLS-1$ //int address = callback.getAddress(); //if (address is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); int threadId = OS.GetCurrentThreadId(); auto hHook_ = OS.SetWindowsHookEx(OS.WH_GETMESSAGE, &getMsgProc, null, threadId); if (hHook_ is null) { //callback.dispose(); return; } display.setData(HHOOK, new ValueWrapperT!(void*)(hHook_)); display.setData(HHOOKMSG, new ValueWrapperT!(MSG*)(new MSG())); display.disposeExec(new class(hHook_) Runnable { void* hHook; this( void* hHook ){ this.hHook = hHook; } public void run() { if (hHook !is null) OS.UnhookWindowsHookEx(hHook); //if (callback !is null) callback.dispose(); } }); } static extern(Windows) int getMsgProc(int code, uint wParam, int lParam) { Display display = Display.getCurrent(); if (display is null) return 0; auto hHook = cast(ValueWrapperT!(void*))display.getData(HHOOK); if (hHook is null) return 0; if (code < 0) { return OS.CallNextHookEx(hHook.value, code, wParam, lParam); } MSG* msg = cast(MSG*)(cast(ValueWrapperT!(MSG*))display.getData(HHOOKMSG)).value; OS.MoveMemory(msg, lParam, MSG.sizeof); int message = msg.message; if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) { if (display !is null) { Widget widget = null; auto hwnd = msg.hwnd; while (hwnd !is null) { widget = display.findWidget (hwnd); if (widget !is null) break; hwnd = OS.GetParent (hwnd); } if (widget !is null && (null !is cast(OleClientSite)widget )) { OleClientSite site = cast(OleClientSite)widget; if (site.handle is hwnd) { bool consumed = false; /* Allow activeX control to translate accelerators except when a menu is active. */ int thread = OS.GetWindowThreadProcessId(msg.hwnd, null); GUITHREADINFO* lpgui = new GUITHREADINFO(); lpgui.cbSize = GUITHREADINFO.sizeof; bool rc = cast(bool) OS.GetGUIThreadInfo(thread, lpgui); int mask = OS.GUI_INMENUMODE | OS.GUI_INMOVESIZE | OS.GUI_POPUPMENUMODE | OS.GUI_SYSTEMMENUMODE; if (!rc || (lpgui.flags & mask) is 0) { OleFrame frame = site.frame; frame.setData(CONSUME_KEY, null); consumed = frame.translateOleAccelerator(msg); if (frame.getData(CONSUME_KEY) !is null) consumed = false; frame.setData(CONSUME_KEY, null); } bool accentKey = false; switch (msg.message) { case OS.WM_KEYDOWN: case OS.WM_SYSKEYDOWN: { static if (!OS.IsWinCE) { switch (msg.wParam) { case OS.VK_SHIFT: case OS.VK_MENU: case OS.VK_CONTROL: case OS.VK_CAPITAL: case OS.VK_NUMLOCK: case OS.VK_SCROLL: break; default: { /* * Bug in Windows. The high bit in the result of MapVirtualKey() on * Windows NT is bit 32 while the high bit on Windows 95 is bit 16. * They should both be bit 32. The fix is to test the right bit. */ int mapKey = OS.MapVirtualKey (msg.wParam, 2); if (mapKey !is 0) { accentKey = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) !is 0; if (!accentKey) { for (int i=0; i<ACCENTS.length; i++) { int value = OS.VkKeyScan (ACCENTS [i]); if (value !is -1 && (value & 0xFF) is msg.wParam) { int state = value >> 8; if ((OS.GetKeyState (OS.VK_SHIFT) < 0) is ((state & 0x1) !is 0) && (OS.GetKeyState (OS.VK_CONTROL) < 0) is ((state & 0x2) !is 0) && (OS.GetKeyState (OS.VK_MENU) < 0) is ((state & 0x4) !is 0)) { if ((state & 0x7) !is 0) accentKey = true; break; } } } } } break; } } } break; } default: } /* Allow OleClientSite to process key events before activeX control */ if (!consumed && !accentKey && !ignoreNextKey) { auto hwndOld = msg.hwnd; msg.hwnd = site.handle; consumed = OS.DispatchMessage (msg) is 1; msg.hwnd = hwndOld; } switch (msg.message) { case OS.WM_KEYDOWN: case OS.WM_SYSKEYDOWN: { switch (msg.wParam) { case OS.VK_SHIFT: case OS.VK_MENU: case OS.VK_CONTROL: case OS.VK_CAPITAL: case OS.VK_NUMLOCK: case OS.VK_SCROLL: break; default: { ignoreNextKey = accentKey; break; } } } default: } if (consumed) { // 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 = msg.lParam = 0; OS.MoveMemory(lParam, msg, MSG.sizeof); return 0; } } } } } return OS.CallNextHookEx( hHook.value, 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() { iOleInPlaceFrame = new _IOleInPlaceFrameImpl(this); } private void disposeCOMInterfaces () { iOleInPlaceFrame = null; } private HRESULT GetBorder(LPRECT 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 is null) return COM.E_INVALIDARG; RECT* rectBorder = new RECT(); // Coordinates must be relative to the window OS.GetClientRect(handle, lprectBorder); 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; } IOleInPlaceFrame getIOleInPlaceFrame() { return iOleInPlaceFrame; } private int getMenuItemID(HMENU hMenu, int index) { int id = 0; MENUITEMINFO lpmii; 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) is OS.MF_POPUP) { id = cast(int)lpmii.hSubMenu; } else { id = lpmii.wID; } return id; } private int GetWindow(HWND* phwnd) { if (phwnd !is null) { *phwnd = handle; } 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. * */ public MenuItem[] getWindowMenus(){ return windowMenuItems; } private HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths ) { // locate menu bar Menu menubar = getShell().getMenuBar(); if (menubar is null || menubar.isDisposed()) { int temp = 0; COM.MoveMemory(lpMenuWidths, &temp, 4); return COM.S_OK; } HMENU 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; auto hHeap = OS.GetProcessHeap(); int cch = 128; int byteCount = cch * TCHAR.sizeof; auto pszText = cast(TCHAR*) 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 !is null) { for (int i = 0; i < this.fileMenuItems.length; i++) { MenuItem item = this.fileMenuItems[i]; if (item !is 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, &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 !is null) { for (int i = 0; i < this.containerMenuItems.length; i++) { MenuItem item = this.containerMenuItems[i]; if (item !is 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, &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 !is null) { for (int i = 0; i < this.windowMenuItems.length; i++) { MenuItem item = this.windowMenuItems[i]; if (item !is 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, &windowMenuCount, 4); // free resources used in querying the OS if (pszText !is null) OS.HeapFree(hHeap, 0, pszText); return COM.S_OK; } void onActivate(Event e) { if (objIOleInPlaceActiveObject !is null) { objIOleInPlaceActiveObject.OnFrameWindowActivate(true); } if (objIOleInPlaceActiveObject !is null) { objIOleInPlaceActiveObject.OnDocWindowActivate(true); } } void onDeactivate(Event e) { if (objIOleInPlaceActiveObject !is null) { objIOleInPlaceActiveObject.OnFrameWindowActivate(false); } if (objIOleInPlaceActiveObject !is null) { objIOleInPlaceActiveObject.OnDocWindowActivate(false); } } private void onDispose(Event e) { releaseObjectInterfaces(); currentdoc = null; this.Release(); removeListener(DWT.Activate, listener); removeListener(DWT.Deactivate, listener); removeListener(DWT.Dispose, listener); removeListener(DWT.Resize, listener); removeListener(DWT.Move, listener); } private void onResize(Event e) { if (objIOleInPlaceActiveObject !is null) { RECT lpRect; OS.GetClientRect(handle, &lpRect); objIOleInPlaceActiveObject.ResizeBorder(&lpRect, iOleInPlaceFrame, true); } } private HRESULT QueryInterface(REFIID riid, void** ppvObject) { // implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow if (riid is null || ppvObject is null) return COM.E_INVALIDARG; if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIOleInPlaceFrame) ) { *ppvObject = cast(void*)iOleInPlaceFrame; AddRef(); return COM.S_OK; } *ppvObject = null; return COM.E_NOINTERFACE; } /** * Decrement the count of references to this instance * * @return the current reference count */ int Release() { refCount--; if (refCount is 0){ disposeCOMInterfaces(); COM.CoFreeUnusedLibraries(); } return refCount; } private void releaseObjectInterfaces() { if (objIOleInPlaceActiveObject !is null) { objIOleInPlaceActiveObject.Release(); } objIOleInPlaceActiveObject = null; } private int RemoveMenus(HMENU hmenuShared) { Menu menubar = getShell().getMenuBar(); if (menubar is null || menubar.isDisposed()) return COM.S_FALSE; auto hMenu = menubar.handle; int[] ids; if (this.fileMenuItems !is null) { for (int i = 0; i < this.fileMenuItems.length; i++) { MenuItem item = this.fileMenuItems[i]; if (item !is null && !item.isDisposed()) { int index = item.getParent().indexOf(item); // get Id from original menubar int id = getMenuItemID(hMenu, index); ids ~= id; } } } if (this.containerMenuItems !is null) { for (int i = 0; i < this.containerMenuItems.length; i++) { MenuItem item = this.containerMenuItems[i]; if (item !is null && !item.isDisposed()) { int index = item.getParent().indexOf(item); int id = getMenuItemID(hMenu, index); ids ~= id; } } } if (this.windowMenuItems !is null) { for (int i = 0; i < this.windowMenuItems.length; i++) { MenuItem item = this.windowMenuItems[i]; if (item !is null && !item.isDisposed()) { int index = item.getParent().indexOf(item); int id = getMenuItemID(hMenu, index); ids ~= id; } } } int index = OS.GetMenuItemCount(hmenuShared) - 1; for (int i = index; i >= 0; i--) { int id = getMenuItemID(hmenuShared, i); if ( ids.contains(id)){ OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION); } } return COM.S_OK; } private int RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) { return COM.S_OK; } HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName ) { if (objIOleInPlaceActiveObject !is null) { objIOleInPlaceActiveObject.Release(); objIOleInPlaceActiveObject = null; } if (pActiveObject !is null) { objIOleInPlaceActiveObject = pActiveObject; objIOleInPlaceActiveObject.AddRef(); } return COM.S_OK; } private HRESULT SetBorderSpace( LPCBORDERWIDTHS 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 is null) return COM.S_OK; RECT* borderwidth = new RECT(); if (pborderwidths is null || currentdoc is 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. * * <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. * * <p>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 !is null && objIOleInPlaceActiveObject !is null) { RECT lpRect; OS.GetClientRect(handle, &lpRect); objIOleInPlaceActiveObject.ResizeBorder(&lpRect, iOleInPlaceFrame, true); } } /** * * Specify the menu items that should 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. * * <p>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; } HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject ) { IOleInPlaceActiveObject inPlaceActiveObject; if (objIOleInPlaceActiveObject !is null) inPlaceActiveObject = objIOleInPlaceActiveObject; Menu menubar = getShell().getMenuBar(); if (menubar is null || menubar.isDisposed()){ return COM.OleSetMenuDescriptor(null, getShell().handle, hwndActiveObject, iOleInPlaceFrame, inPlaceActiveObject); } HWND handle = menubar.getShell().handle; if (hmenuShared is null && holemenu is null) { // re-instate the original menu - this occurs on deactivation hmenuShared = menubar.handle; } if (hmenuShared is null) return COM.E_FAIL; OS.SetMenu(handle, hmenuShared); OS.DrawMenuBar(handle); return COM.OleSetMenuDescriptor(holemenu, handle, hwndActiveObject, iOleInPlaceFrame, inPlaceActiveObject); } /** * * Set the menu items that should 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. * * <p>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 bool translateOleAccelerator(MSG* msg) { if (objIOleInPlaceActiveObject is null) return false; int result = objIOleInPlaceActiveObject.TranslateAccelerator(msg); return (result != COM.S_FALSE && result != COM.E_NOTIMPL); } HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID ){ Menu menubar = getShell().getMenuBar(); if (menubar is null || menubar.isDisposed() || !menubar.isEnabled()) return COM.S_FALSE; if (wID < 0) return COM.S_FALSE; Shell shell = menubar.getShell(); HWND hwnd = shell.handle; HACCEL hAccel = cast(HACCEL)OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0); if (hAccel is null) return COM.S_FALSE; MSG msg = *lpmsg; int result = OS.TranslateAccelerator(hwnd, hAccel, &msg); return result == 0 ? COM.S_FALSE : COM.S_OK; } } // implements IOleInPlaceFrame, IOleInPlaceUIWindow, IOleWindow, IUnknown class _IOleInPlaceFrameImpl : IOleInPlaceFrame { OleFrame parent; this(OleFrame p) { parent = p; } extern (Windows) : // interface of IUnknown HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); } ULONG AddRef() { return parent.AddRef(); } ULONG Release() { return parent.Release(); } // interface IOleWindow HRESULT GetWindow( HWND * phwnd ) { return parent.GetWindow(phwnd); } HRESULT ContextSensitiveHelp( BOOL fEnterMode ){ return COM.S_OK; } //interface IOleInPlaceUIWindow HRESULT GetBorder( LPRECT lprectBorder ) { return parent.GetBorder(lprectBorder); } HRESULT RequestBorderSpace( LPCBORDERWIDTHS pborderwidths ){ return COM.S_OK; } HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths ) { return parent.SetBorderSpace(pborderwidths); } HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName ) { return parent.SetActiveObject(pActiveObject, pszObjName); } // interface IOleInPlaceFrame : IOleInPlaceUIWindow HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths ){ return parent.InsertMenus(hmenuShared, lpMenuWidths); } HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject ){ return parent.SetMenu(hmenuShared, holemenu, hwndActiveObject); } HRESULT RemoveMenus( HMENU hmenuShared ) { return parent.RemoveMenus(hmenuShared); } HRESULT SetStatusText( LPCOLESTR pszStatusText ) { return COM.E_NOTIMPL; } HRESULT EnableModeless( BOOL fEnable ) { return COM.E_NOTIMPL; } HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID ) { return parent.TranslateAccelerator(lpmsg, wID); } }