1 /*******************************************************************************
2 * Copyright (c) 2000, 2019 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.ole.win32;
17 import java.util.List;
19 import org.eclipse.swt.*;
20 import org.eclipse.swt.internal.*;
21 import org.eclipse.swt.internal.ole.win32.*;
22 import org.eclipse.swt.internal.win32.*;
23 import org.eclipse.swt.widgets.*;
27 * OleFrame is an OLE Container's top level frame.
29 * <p>This object implements the OLE Interfaces IUnknown and IOleInPlaceFrame
31 * <p>OleFrame allows the container to do the following: <ul>
32 * <li>position and size the ActiveX Control or OLE Document within the application
33 * <li>insert menu items from the application into the OLE Document's menu
34 * <li>activate and deactivate the OLE Document's menus
35 * <li>position the OLE Document's menu in the application
36 * <li>translate accelerator keystrokes intended for the container's frame</ul>
39 * <dt><b>Styles</b> <dd>BORDER
40 * <dt><b>Events</b> <dd>Dispose, Move, Resize
43 * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
44 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
46 final public class OleFrame extends Composite
48 // Interfaces for this Ole Client Container
49 private COMObject iOleInPlaceFrame;
51 // Access to the embedded/linked Ole Object
52 private IOleInPlaceActiveObject objIOleInPlaceActiveObject;
54 private OleClientSite currentdoc;
56 private int refCount = 0;
58 private MenuItem[] fileMenuItems;
59 private MenuItem[] containerMenuItems;
60 private MenuItem[] windowMenuItems;
62 private Listener listener;
64 private long shellHandle;
65 private long oldMenuHandle;
66 private long newMenuHandle;
67 private static long lastActivatedMenuHandle;
69 private static String CHECK_FOCUS = "OLE_CHECK_FOCUS"; //$NON-NLS-1$
70 private static String HHOOK = "OLE_HHOOK"; //$NON-NLS-1$
71 private static String HHOOKMSG = "OLE_HHOOK_MSG"; //$NON-NLS-1$
73 private static boolean ignoreNextKey;
74 private static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
76 private static final String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
77 private static final String ACCEL_KEY_HIT = "org.eclipse.swt.internal.win32.accelKeyHit"; //$NON-NLS-1$
80 * Create an OleFrame child widget using style bits
81 * to select a particular look or set of properties.
83 * @param parent a composite widget (cannot be null)
84 * @param style the bitwise OR'ing of widget styles
86 * @exception IllegalArgumentException <ul>
87 * <li>ERROR_NULL_ARGUMENT when the parent is null
89 * @exception SWTException <ul>
90 * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
94 public OleFrame(Composite parent, int style) {
97 createCOMInterfaces();
102 case SWT.Activate : onActivate(e); break;
103 case SWT.Deactivate : onDeactivate(e); break;
104 case SWT.Dispose : onDispose(e); break;
106 case SWT.Move : onResize(e); break;
108 OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
113 addListener(SWT.Activate, listener);
114 addListener(SWT.Deactivate, listener);
115 addListener(SWT.Dispose, listener);
117 // inform inplaceactiveobject whenever frame resizes
118 addListener(SWT.Resize, listener);
120 // inform inplaceactiveobject whenever frame moves
121 addListener(SWT.Move, listener);
123 // Maintain a reference to yourself so that when
124 // ClientSites close, they don't take the frame away
128 // Check for focus change
129 Display display = getDisplay();
130 initCheckFocus(display);
131 initMsgHook(display);
133 private static void initCheckFocus (final Display display) {
134 if (display.getData(CHECK_FOCUS) != null) return;
135 display.setData(CHECK_FOCUS, CHECK_FOCUS);
137 final Runnable[] timer = new Runnable[1];
138 final Control[] lastFocus = new Control[1];
140 if (lastFocus[0] instanceof OleClientSite && !lastFocus[0].isDisposed()) {
141 // ignore popup menus and dialogs
142 long hwnd = OS.GetFocus();
144 long ownerHwnd = OS.GetWindow(hwnd, OS.GW_OWNER);
145 if (ownerHwnd != 0) {
146 display.timerExec(time, timer[0]);
149 hwnd = OS.GetParent(hwnd);
152 if (lastFocus[0] == null || lastFocus[0].isDisposed() || !lastFocus[0].isFocusControl()) {
153 Control currentFocus = display.getFocusControl();
154 if (currentFocus instanceof OleFrame) {
155 OleFrame frame = (OleFrame) currentFocus;
156 currentFocus = frame.getCurrentDocument();
158 if (lastFocus[0] != currentFocus) {
159 Event event = new Event();
160 if (lastFocus[0] instanceof OleClientSite && !lastFocus[0].isDisposed()) {
161 lastFocus[0].notifyListeners (SWT.FocusOut, event);
163 if (currentFocus instanceof OleClientSite && !currentFocus.isDisposed()) {
164 currentFocus.notifyListeners(SWT.FocusIn, event);
167 lastFocus[0] = currentFocus;
169 display.timerExec(time, timer[0]);
171 display.timerExec(time, timer[0]);
173 private static void initMsgHook(Display display) {
174 if (display.getData(HHOOK) != null) return;
175 final Callback callback = new Callback(OleFrame.class, "getMsgProc", 3); //$NON-NLS-1$
176 long address = callback.getAddress();
177 if (address == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
178 int threadId = OS.GetCurrentThreadId();
179 final long hHook = OS.SetWindowsHookEx(OS.WH_GETMESSAGE, address, 0, threadId);
184 display.setData(HHOOK, new LONG(hHook));
185 display.setData(HHOOKMSG, new MSG());
186 display.disposeExec(() -> {
187 if (hHook != 0) OS.UnhookWindowsHookEx(hHook);
188 if (callback != null) callback.dispose();
191 static long getMsgProc(long code, long wParam, long lParam) {
192 Display display = Display.getCurrent();
193 if (display == null) return 0;
194 LONG hHook = (LONG)display.getData(HHOOK);
195 if (hHook == null) return 0;
196 if (code < 0 || (wParam & OS.PM_REMOVE) == 0) {
197 return OS.CallNextHookEx(hHook.value, (int)code, wParam, lParam);
199 MSG msg = (MSG)display.getData(HHOOKMSG);
200 OS.MoveMemory(msg, lParam, MSG.sizeof);
201 int message = msg.message;
202 if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
203 if (display != null) {
204 Widget widget = null;
205 long hwnd = msg.hwnd;
207 widget = display.findWidget (hwnd);
208 if (widget != null) break;
209 hwnd = OS.GetParent (hwnd);
211 if (widget != null && widget instanceof OleClientSite) {
212 OleClientSite site = (OleClientSite)widget;
213 if (site.handle == hwnd) {
214 boolean consumed = false;
215 /* Allow activeX control to translate accelerators except when a menu is active. */
216 int thread = OS.GetWindowThreadProcessId(msg.hwnd, null);
217 GUITHREADINFO lpgui = new GUITHREADINFO();
218 lpgui.cbSize = GUITHREADINFO.sizeof;
219 boolean rc = OS.GetGUIThreadInfo(thread, lpgui);
220 int mask = OS.GUI_INMENUMODE | OS.GUI_INMOVESIZE | OS.GUI_POPUPMENUMODE | OS.GUI_SYSTEMMENUMODE;
221 if (!rc || (lpgui.flags & mask) == 0) {
222 OleFrame frame = site.frame;
223 frame.setData(CONSUME_KEY, null);
224 display.setData(ACCEL_KEY_HIT, Boolean.TRUE);
225 consumed = frame.translateOleAccelerator(msg);
226 /* translateOleAccelerator() may send client events, ensure that the frame and display are still valid */
227 if (display.isDisposed()) return 0;
228 display.setData(ACCEL_KEY_HIT, Boolean.FALSE);
229 if (frame.isDisposed()) return 0;
230 String value = (String)frame.getData(CONSUME_KEY);
231 if (value != null) consumed = value.equals("true"); //$NON-NLS-1$
232 frame.setData(CONSUME_KEY, null);
234 boolean accentKey = false;
235 switch (msg.message) {
237 case OS.WM_SYSKEYDOWN: {
238 switch ((int)msg.wParam) {
247 int mapKey = OS.MapVirtualKey ((int)msg.wParam, 2);
249 accentKey = (mapKey & 0x80000000) != 0;
251 for (int i=0; i<ACCENTS.length; i++) {
252 int value = OS.VkKeyScan (ACCENTS [i]);
253 if (value != -1 && (value & 0xFF) == msg.wParam) {
254 int state = value >> 8;
255 if ((OS.GetKeyState (OS.VK_SHIFT) < 0) == ((state & 0x1) != 0) &&
256 (OS.GetKeyState (OS.VK_CONTROL) < 0) == ((state & 0x2) != 0) &&
257 (OS.GetKeyState (OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
258 if ((state & 0x7) != 0) accentKey = true;
271 /* Allow OleClientSite to process key events before activeX control */
272 if (!consumed && !accentKey && !ignoreNextKey) {
273 long hwndOld = msg.hwnd;
274 msg.hwnd = site.handle;
275 consumed = OS.DispatchMessage (msg) == 1;
278 switch (msg.message) {
280 case OS.WM_SYSKEYDOWN: {
281 switch ((int)msg.wParam) {
290 ignoreNextKey = accentKey;
298 // In order to prevent this message from also being processed
299 // by the application, zero out message, wParam and lParam
300 msg.message = OS.WM_NULL;
301 msg.wParam = msg.lParam = 0;
302 OS.MoveMemory(lParam, msg, MSG.sizeof);
309 return OS.CallNextHookEx(hHook.value, (int)code, wParam, lParam);
312 * Increment the count of references to this instance
314 * @return the current reference count
320 private int ContextSensitiveHelp(int fEnterMode) {
323 private void createCOMInterfaces() {
324 iOleInPlaceFrame = new COMObject(new int[]{2, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 1, 1, 1, 2}){
326 public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
328 public long method1(long[] args) {return AddRef();}
330 public long method2(long[] args) {return Release();}
332 public long method3(long[] args) {return GetWindow(args[0]);}
334 public long method4(long[] args) {return ContextSensitiveHelp((int)args[0]);}
336 public long method5(long[] args) {return GetBorder(args[0]);}
338 public long method6(long[] args) {return RequestBorderSpace(args[0]);}
340 public long method7(long[] args) {return SetBorderSpace(args[0]);}
342 public long method8(long[] args) {return SetActiveObject(args[0], args[1]);}
344 public long method9(long[] args) {return InsertMenus(args[0], args[1]);}
346 public long method10(long[] args) {return SetMenu(args[0], args[1], args[2]);}
348 public long method11(long[] args) {return RemoveMenus(args[0]);}
349 // method12 SetStatusText - not implemented
350 // method13 EnableModeless - not implemented
352 public long method14(long[] args) {return TranslateAccelerator(args[0], (int)args[1]);}
355 private void disposeCOMInterfaces () {
356 if (iOleInPlaceFrame != null)
357 iOleInPlaceFrame.dispose();
358 iOleInPlaceFrame = null;
360 private int GetBorder(long lprectBorder) {
362 The IOleInPlaceUIWindow::GetBorder function, when called on a document or frame window
363 object, returns the outer rectangle (relative to the window) where the object can put
364 toolbars or similar controls.
366 if (lprectBorder == 0) return COM.E_INVALIDARG;
367 RECT rectBorder = new RECT();
368 // Coordinates must be relative to the window
369 OS.GetClientRect(handle, rectBorder);
370 OS.MoveMemory(lprectBorder, rectBorder, RECT.sizeof);
375 * Returns the application menu items that will appear in the Container location when an OLE Document
376 * is in-place activated.
378 * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
379 * is given the opportunity to merge some of its menus into the menubar. The application
380 * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
381 * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
382 * menu locations. Note that an application can insert more than one menu into a single location.
384 * @return the application menu items that will appear in the Container location when an OLE Document
385 * is in-place activated.
388 public MenuItem[] getContainerMenus(){
389 return containerMenuItems;
393 * Returns the application menu items that will appear in the File location when an OLE Document
394 * is in-place activated.
396 * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
397 * is given the opportunity to merge some of its menus into the menubar. The application
398 * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
399 * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
400 * menu locations. Note that an application can insert more than one menu into a single location.
402 * @return the application menu items that will appear in the File location when an OLE Document
403 * is in-place activated.
406 public MenuItem[] getFileMenus(){
407 return fileMenuItems;
409 long getIOleInPlaceFrame() {
410 return iOleInPlaceFrame.getAddress();
412 private long getMenuItemID(long hMenu, int index) {
414 MENUITEMINFO lpmii = new MENUITEMINFO();
415 lpmii.cbSize = MENUITEMINFO.sizeof;
416 lpmii.fMask = OS.MIIM_STATE | OS.MIIM_SUBMENU | OS.MIIM_ID;
417 OS.GetMenuItemInfo(hMenu, index, true, lpmii);
418 if ((lpmii.fState & OS.MF_POPUP) == OS.MF_POPUP) {
425 private int GetWindow(long phwnd) {
427 OS.MoveMemory(phwnd, new long[] {handle}, C.PTR_SIZEOF);
433 * Returns the application menu items that will appear in the Window location when an OLE Document
434 * is in-place activated.
436 * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
437 * is given the opportunity to merge some of its menus into the menubar. The application
438 * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
439 * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
440 * menu locations. Note that an application can insert more than one menu into a single location.
442 * @return the application menu items that will appear in the Window location when an OLE Document
443 * is in-place activated.
446 public MenuItem[] getWindowMenus(){
447 return windowMenuItems;
449 private int InsertMenus(long hmenuShared, long lpMenuWidths) {
451 Menu menubar = getShell().getMenuBar();
452 if (menubar == null || menubar.isDisposed()) {
453 OS.MoveMemory(lpMenuWidths, new int[] {0}, 4);
456 long hMenu = menubar.handle;
458 // Create a holder for menu information. This will be passed down to
459 // the OS and the OS will fill in the requested information for each menu.
460 MENUITEMINFO lpmii = new MENUITEMINFO();
461 long hHeap = OS.GetProcessHeap();
463 int byteCount = cch * TCHAR.sizeof;
464 long pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
465 lpmii.cbSize = MENUITEMINFO.sizeof;
466 lpmii.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_SUBMENU | OS.MIIM_DATA;
467 lpmii.dwTypeData = pszText;
470 // Loop over all "File-like" menus in the menubar and get information about the
472 int fileMenuCount = 0;
474 if (this.fileMenuItems != null) {
475 for (int i = 0; i < this.fileMenuItems.length; i++) {
476 MenuItem item = this.fileMenuItems[i];
478 int index = item.getParent().indexOf(item);
479 lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
480 // exact number of characters in name. Reset it to our max size
482 if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) {
483 if (OS.InsertMenuItem(hmenuShared, newindex, true, lpmii)) {
484 // keep track of the number of items
493 // copy the menu item count information to the pointer
494 OS.MoveMemory(lpMenuWidths, new int[] {fileMenuCount}, 4);
496 // Loop over all "Container-like" menus in the menubar and get information about the
498 int containerMenuCount = 0;
499 if (this.containerMenuItems != null) {
500 for (int i = 0; i < this.containerMenuItems.length; i++) {
501 MenuItem item = this.containerMenuItems[i];
503 int index = item.getParent().indexOf(item);
504 lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
505 // exact number of characters in name. Reset it to a large number
507 if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) {
508 if (OS.InsertMenuItem(hmenuShared, newindex, true, lpmii)) {
509 // keep track of the number of items
510 containerMenuCount++;
518 // copy the menu item count information to the pointer
519 OS.MoveMemory(lpMenuWidths + 8, new int[] {containerMenuCount}, 4);
521 // Loop over all "Window-like" menus in the menubar and get information about the
523 int windowMenuCount = 0;
524 if (this.windowMenuItems != null) {
525 for (int i = 0; i < this.windowMenuItems.length; i++) {
526 MenuItem item = this.windowMenuItems[i];
528 int index = item.getParent().indexOf(item);
529 lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
530 // exact number of characters in name. Reset it to a large number
532 if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) {
533 if (OS.InsertMenuItem(hmenuShared, newindex, true, lpmii)) {
534 // keep track of the number of items
543 // copy the menu item count information to the pointer
544 OS.MoveMemory(lpMenuWidths + 16, new int[] {windowMenuCount}, 4);
546 // free resources used in querying the OS
548 OS.HeapFree(hHeap, 0, pszText);
551 void onActivate(Event e) {
552 if (objIOleInPlaceActiveObject != null) {
553 objIOleInPlaceActiveObject.OnFrameWindowActivate(true);
556 void onDeactivate(Event e) {
557 if (objIOleInPlaceActiveObject != null) {
558 objIOleInPlaceActiveObject.OnFrameWindowActivate(false);
561 private void onDispose(Event e) {
563 releaseObjectInterfaces();
567 removeListener(SWT.Activate, listener);
568 removeListener(SWT.Deactivate, listener);
569 removeListener(SWT.Dispose, listener);
570 removeListener(SWT.Resize, listener);
571 removeListener(SWT.Move, listener);
573 void onFocusIn(Event e) {
574 if (lastActivatedMenuHandle != newMenuHandle)
575 currentdoc.doVerb(OLE.OLEIVERB_SHOW);
576 if (OS.GetMenu(shellHandle) != newMenuHandle)
577 OS.SetMenu(shellHandle, newMenuHandle);
579 void onFocusOut(Event e) {
580 Control control = getDisplay().getFocusControl();
581 if (OS.GetMenu(shellHandle) != oldMenuHandle && control != null && control.handle != shellHandle)
582 OS.SetMenu(shellHandle, oldMenuHandle);
584 private void onResize(Event e) {
585 if (objIOleInPlaceActiveObject != null) {
586 RECT lpRect = new RECT();
587 OS.GetClientRect(handle, lpRect);
588 objIOleInPlaceActiveObject.ResizeBorder(lpRect, iOleInPlaceFrame.getAddress(), true);
591 private int QueryInterface(long riid, long ppvObject) {
592 // implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow
593 if (riid == 0 || ppvObject == 0)
594 return COM.E_INVALIDARG;
595 GUID guid = new GUID();
596 COM.MoveMemory(guid, riid, GUID.sizeof);
597 if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame) ) {
598 OS.MoveMemory(ppvObject, new long [] {iOleInPlaceFrame.getAddress()}, C.PTR_SIZEOF);
603 OS.MoveMemory(ppvObject, new long [] {0}, C.PTR_SIZEOF);
604 return COM.E_NOINTERFACE;
607 * Decrement the count of references to this instance
609 * @return the current reference count
614 disposeCOMInterfaces();
615 if (COM.FreeUnusedLibraries) {
616 COM.CoFreeUnusedLibraries();
621 private void releaseObjectInterfaces() {
622 if (objIOleInPlaceActiveObject != null) {
623 objIOleInPlaceActiveObject.Release();
625 objIOleInPlaceActiveObject = null;
627 private int RemoveMenus(long hmenuShared) {
629 Menu menubar = getShell().getMenuBar();
630 if (menubar == null || menubar.isDisposed()) return COM.S_FALSE;
632 long hMenu = menubar.handle;
634 List<LONG> ids = new ArrayList<>();
635 if (this.fileMenuItems != null) {
636 for (int i = 0; i < this.fileMenuItems.length; i++) {
637 MenuItem item = this.fileMenuItems[i];
638 if (item != null && !item.isDisposed()) {
639 int index = item.getParent().indexOf(item);
640 // get Id from original menubar
641 long id = getMenuItemID(hMenu, index);
642 ids.add(new LONG(id));
646 if (this.containerMenuItems != null) {
647 for (int i = 0; i < this.containerMenuItems.length; i++) {
648 MenuItem item = this.containerMenuItems[i];
649 if (item != null && !item.isDisposed()) {
650 int index = item.getParent().indexOf(item);
651 long id = getMenuItemID(hMenu, index);
652 ids.add(new LONG(id));
656 if (this.windowMenuItems != null) {
657 for (int i = 0; i < this.windowMenuItems.length; i++) {
658 MenuItem item = this.windowMenuItems[i];
659 if (item != null && !item.isDisposed()) {
660 int index = item.getParent().indexOf(item);
661 long id = getMenuItemID(hMenu, index);
662 ids.add(new LONG(id));
666 int index = OS.GetMenuItemCount(hmenuShared) - 1;
667 for (int i = index; i >= 0; i--) {
668 long id = getMenuItemID(hmenuShared, i);
669 if (ids.contains(new LONG(id))){
670 OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION);
675 private int RequestBorderSpace(long pborderwidths) {
678 int SetActiveObject(long pActiveObject, long pszObjName) {
679 if (objIOleInPlaceActiveObject != null) {
680 objIOleInPlaceActiveObject.Release();
681 objIOleInPlaceActiveObject = null;
683 if (pActiveObject != 0) {
684 objIOleInPlaceActiveObject = new IOleInPlaceActiveObject(pActiveObject);
685 objIOleInPlaceActiveObject.AddRef();
690 private int SetBorderSpace(long pborderwidths) {
691 // A Control/Document can :
692 // Use its own toolbars, requesting border space of a specific size, or,
693 // Use no toolbars, but force the container to remove its toolbars by passing a
694 // valid BORDERWIDTHS structure containing nothing but zeros in the pborderwidths parameter, or,
695 // Use no toolbars but allow the in-place container to leave its toolbars up by
696 // passing NULL as the pborderwidths parameter.
697 if (objIOleInPlaceActiveObject == null) return COM.S_OK;
698 RECT borderwidth = new RECT();
699 if (pborderwidths == 0 || currentdoc == null ) return COM.S_OK;
701 COM.MoveMemory(borderwidth, pborderwidths, RECT.sizeof);
702 currentdoc.setBorderSpace(borderwidth);
708 * Specify the menu items that should appear in the Container location when an OLE Document
709 * is in-place activated.
711 * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
712 * is given the opportunity to merge some of its menus into the menubar. The application
713 * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
714 * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
715 * menu locations. Note that an application can insert more than one menu into a single location.
717 * <p>This method must be called before in place activation of the OLE Document. After the Document
718 * is activated, the menu bar will not be modified until a subsequent activation.
720 * @param containerMenus an array of top level MenuItems to be inserted into the Container location of
723 public void setContainerMenus(MenuItem[] containerMenus){
724 containerMenuItems = containerMenus;
726 OleClientSite getCurrentDocument() {
729 void setCurrentDocument(OleClientSite doc) {
732 if (currentdoc != null && objIOleInPlaceActiveObject != null) {
733 RECT lpRect = new RECT();
734 OS.GetClientRect(handle, lpRect);
735 objIOleInPlaceActiveObject.ResizeBorder(lpRect, iOleInPlaceFrame.getAddress(), true);
740 * Specify the menu items that should appear in the File location when an OLE Document
741 * is in-place activated.
743 * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
744 * is given the opportunity to merge some of its menus into the menubar. The application
745 * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
746 * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
747 * menu locations. Note that an application can insert more than one menu into a single location.
749 * <p>This method must be called before in place activation of the OLE Document. After the Document
750 * is activated, the menu bar will not be modified until a subsequent activation.
752 * @param fileMenus an array of top level MenuItems to be inserted into the File location of
755 public void setFileMenus(MenuItem[] fileMenus){
756 fileMenuItems = fileMenus;
758 private int SetMenu(long hmenuShared, long holemenu, long hwndActiveObject) {
759 long inPlaceActiveObject = 0;
760 if (objIOleInPlaceActiveObject != null)
761 inPlaceActiveObject = objIOleInPlaceActiveObject.getAddress();
763 Menu menubar = getShell().getMenuBar();
764 if (menubar == null || menubar.isDisposed()){
765 return COM.OleSetMenuDescriptor(0, getShell().handle, hwndActiveObject, iOleInPlaceFrame.getAddress(), inPlaceActiveObject);
768 long handle = menubar.getShell().handle;
770 if (hmenuShared == 0 && holemenu == 0) {
771 // re-instate the original menu - this occurs on deactivation
772 hmenuShared = menubar.handle;
774 if (hmenuShared == 0) return COM.E_FAIL;
776 shellHandle = handle;
777 oldMenuHandle = menubar.handle;
778 newMenuHandle = hmenuShared;
779 lastActivatedMenuHandle = newMenuHandle;
781 return COM.OleSetMenuDescriptor(holemenu, handle, hwndActiveObject, iOleInPlaceFrame.getAddress(), inPlaceActiveObject);
785 * Set the menu items that should appear in the Window location when an OLE Document
786 * is in-place activated.
788 * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
789 * is given the opportunity to merge some of its menus into the menubar. The application
790 * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
791 * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
792 * menu locations. Note that an application can insert more than one menu into a single location.
794 * <p>This method must be called before in place activation of the OLE Document. After the Document
795 * is activated, the menu bar will not be modified until a subsequent activation.
797 * @param windowMenus an array of top level MenuItems to be inserted into the Window location of
800 public void setWindowMenus(MenuItem[] windowMenus){
801 windowMenuItems = windowMenus;
803 private boolean translateOleAccelerator(MSG msg) {
804 if (objIOleInPlaceActiveObject == null) return false;
805 int result = objIOleInPlaceActiveObject.TranslateAccelerator(msg);
806 return (result != COM.S_FALSE && result != COM.E_NOTIMPL);
808 private int TranslateAccelerator(long lpmsg, int wID){
809 Menu menubar = getShell().getMenuBar();
810 if (menubar == null || menubar.isDisposed() || !menubar.isEnabled()) return COM.S_FALSE;
811 if (wID < 0) return COM.S_FALSE;
813 Shell shell = menubar.getShell();
814 long hwnd = shell.handle;
815 long hAccel = OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
816 if (hAccel == 0) return COM.S_FALSE;
819 OS.MoveMemory(msg, lpmsg, MSG.sizeof);
820 int result = OS.TranslateAccelerator(hwnd, hAccel, msg);
821 return result == 0 ? COM.S_FALSE : COM.S_OK;