001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.ole.win32;
011:
012: import org.eclipse.swt.*;
013: import org.eclipse.swt.internal.ole.win32.*;
014: import org.eclipse.swt.widgets.*;
015: import org.eclipse.swt.internal.win32.*;
016: import org.eclipse.swt.internal.*;
017: import java.util.Vector;
018:
019: /**
020: *
021: * OleFrame is an OLE Container's top level frame.
022: *
023: * <p>This object implements the OLE Interfaces IUnknown and IOleInPlaceFrame
024: *
025: * <p>OleFrame allows the container to do the following: <ul>
026: * <li>position and size the ActiveX Control or OLE Document within the application
027: * <li>insert menu items from the application into the OLE Document's menu
028: * <li>activate and deactivate the OLE Document's menus
029: * <li>position the OLE Document's menu in the application
030: * <li>translate accelerator keystrokes intended for the container's frame</ul>
031: *
032: * <dl>
033: * <dt><b>Styles</b> <dd>BORDER
034: * <dt><b>Events</b> <dd>Dispose, Move, Resize
035: * </dl>
036: *
037: */
038: final public class OleFrame extends Composite {
039: // Interfaces for this Ole Client Container
040: private COMObject iUnknown;
041: private COMObject iOleInPlaceFrame;
042:
043: // Access to the embedded/linked Ole Object
044: private IOleInPlaceActiveObject objIOleInPlaceActiveObject;
045:
046: private OleClientSite currentdoc;
047:
048: private int refCount = 0;
049:
050: private MenuItem[] fileMenuItems;
051: private MenuItem[] containerMenuItems;
052: private MenuItem[] windowMenuItems;
053:
054: private Listener listener;
055:
056: private static String CHECK_FOCUS = "OLE_CHECK_FOCUS"; //$NON-NLS-1$
057: private static String HHOOK = "OLE_HHOOK"; //$NON-NLS-1$
058: private static String HHOOKMSG = "OLE_HHOOK_MSG"; //$NON-NLS-1$
059:
060: private static boolean ignoreNextKey;
061: private static final short[] ACCENTS = new short[] { '~', '`',
062: '\'', '^', '"' };
063:
064: private static final String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
065:
066: /**
067: * Create an OleFrame child widget using style bits
068: * to select a particular look or set of properties.
069: *
070: * @param parent a composite widget (cannot be null)
071: * @param style the bitwise OR'ing of widget styles
072: *
073: * @exception IllegalArgumentException <ul>
074: * <li>ERROR_NULL_ARGUMENT when the parent is null
075: * </ul>
076: * @exception SWTException <ul>
077: * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
078: * </ul>
079: *
080: */
081: public OleFrame(Composite parent, int style) {
082: super (parent, style);
083:
084: createCOMInterfaces();
085:
086: // setup cleanup proc
087: listener = new Listener() {
088: public void handleEvent(Event e) {
089: switch (e.type) {
090: case SWT.Activate:
091: onActivate(e);
092: break;
093: case SWT.Deactivate:
094: onDeactivate(e);
095: break;
096: case SWT.Dispose:
097: onDispose(e);
098: break;
099: case SWT.Resize:
100: case SWT.Move:
101: onResize(e);
102: break;
103: default:
104: OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
105: }
106: }
107: };
108:
109: addListener(SWT.Activate, listener);
110: addListener(SWT.Deactivate, listener);
111: addListener(SWT.Dispose, listener);
112:
113: // inform inplaceactiveobject whenever frame resizes
114: addListener(SWT.Resize, listener);
115:
116: // inform inplaceactiveobject whenever frame moves
117: addListener(SWT.Move, listener);
118:
119: // Maintain a reference to yourself so that when
120: // ClientSites close, they don't take the frame away
121: // with them.
122: this .AddRef();
123:
124: // Check for focus change
125: Display display = getDisplay();
126: initCheckFocus(display);
127: initMsgHook(display);
128: }
129:
130: private static void initCheckFocus(final Display display) {
131: if (display.getData(CHECK_FOCUS) != null)
132: return;
133: display.setData(CHECK_FOCUS, CHECK_FOCUS);
134: final int time = 50;
135: final Runnable[] timer = new Runnable[1];
136: final Control[] lastFocus = new Control[1];
137: timer[0] = new Runnable() {
138: public void run() {
139: if (lastFocus[0] instanceof OleClientSite
140: && !lastFocus[0].isDisposed()) {
141: // ignore popup menus and dialogs
142: int /*long*/hwnd = OS.GetFocus();
143: while (hwnd != 0) {
144: int /*long*/ownerHwnd = OS.GetWindow(hwnd,
145: OS.GW_OWNER);
146: if (ownerHwnd != 0) {
147: display.timerExec(time, timer[0]);
148: return;
149: }
150: hwnd = OS.GetParent(hwnd);
151: }
152: }
153: if (lastFocus[0] == null || lastFocus[0].isDisposed()
154: || !lastFocus[0].isFocusControl()) {
155: Control currentFocus = display.getFocusControl();
156: if (currentFocus instanceof OleFrame) {
157: OleFrame frame = (OleFrame) currentFocus;
158: currentFocus = frame.getCurrentDocument();
159: }
160: if (lastFocus[0] != currentFocus) {
161: Event event = new Event();
162: if (lastFocus[0] instanceof OleClientSite
163: && !lastFocus[0].isDisposed()) {
164: lastFocus[0].notifyListeners(SWT.FocusOut,
165: event);
166: }
167: if (currentFocus instanceof OleClientSite
168: && !currentFocus.isDisposed()) {
169: currentFocus.notifyListeners(SWT.FocusIn,
170: event);
171: }
172: }
173: lastFocus[0] = currentFocus;
174: }
175: display.timerExec(time, timer[0]);
176: }
177: };
178: display.timerExec(time, timer[0]);
179: }
180:
181: private static void initMsgHook(Display display) {
182: if (display.getData(HHOOK) != null)
183: return;
184: final Callback callback = new Callback(OleFrame.class,
185: "getMsgProc", 3); //$NON-NLS-1$
186: int /*long*/address = callback.getAddress();
187: if (address == 0)
188: SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
189: int threadId = OS.GetCurrentThreadId();
190: final int /*long*/hHook = OS.SetWindowsHookEx(
191: OS.WH_GETMESSAGE, address, 0, threadId);
192: if (hHook == 0) {
193: callback.dispose();
194: return;
195: }
196: display.setData(HHOOK, new LONG(hHook));
197: display.setData(HHOOKMSG, new MSG());
198: display.disposeExec(new Runnable() {
199: public void run() {
200: if (hHook != 0)
201: OS.UnhookWindowsHookEx(hHook);
202: if (callback != null)
203: callback.dispose();
204: }
205: });
206: }
207:
208: static int /*long*/getMsgProc(int /*long*/code,
209: int /*long*/wParam, int /*long*/lParam) {
210: Display display = Display.getCurrent();
211: if (display == null)
212: return 0;
213: LONG hHook = (LONG) display.getData(HHOOK);
214: if (hHook == null)
215: return 0;
216: if (code < 0) {
217: return OS.CallNextHookEx(hHook.value, (int) /*64*/code,
218: wParam, lParam);
219: }
220: MSG msg = (MSG) display.getData(HHOOKMSG);
221: OS.MoveMemory(msg, lParam, MSG.sizeof);
222: int message = msg.message;
223: if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
224: if (display != null) {
225: Widget widget = null;
226: int /*long*/hwnd = msg.hwnd;
227: while (hwnd != 0) {
228: widget = display.findWidget(hwnd);
229: if (widget != null)
230: break;
231: hwnd = OS.GetParent(hwnd);
232: }
233: if (widget != null && widget instanceof OleClientSite) {
234: OleClientSite site = (OleClientSite) widget;
235: if (site.handle == hwnd) {
236: boolean consumed = false;
237: /* Allow activeX control to translate accelerators except when a menu is active. */
238: int thread = OS.GetWindowThreadProcessId(
239: msg.hwnd, null);
240: GUITHREADINFO lpgui = new GUITHREADINFO();
241: lpgui.cbSize = GUITHREADINFO.sizeof;
242: boolean rc = OS.GetGUIThreadInfo(thread, lpgui);
243: int mask = OS.GUI_INMENUMODE
244: | OS.GUI_INMOVESIZE
245: | OS.GUI_POPUPMENUMODE
246: | OS.GUI_SYSTEMMENUMODE;
247: if (!rc || (lpgui.flags & mask) == 0) {
248: OleFrame frame = site.frame;
249: frame.setData(CONSUME_KEY, null);
250: consumed = frame
251: .translateOleAccelerator(msg);
252: if (frame.getData(CONSUME_KEY) != null)
253: consumed = false;
254: frame.setData(CONSUME_KEY, null);
255: }
256: boolean accentKey = false;
257: switch (msg.message) {
258: case OS.WM_KEYDOWN:
259: case OS.WM_SYSKEYDOWN: {
260: if (!OS.IsWinCE) {
261: switch ((int) /*64*/msg.wParam) {
262: case OS.VK_SHIFT:
263: case OS.VK_MENU:
264: case OS.VK_CONTROL:
265: case OS.VK_CAPITAL:
266: case OS.VK_NUMLOCK:
267: case OS.VK_SCROLL:
268: break;
269: default: {
270: /*
271: * Bug in Windows. The high bit in the result of MapVirtualKey() on
272: * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
273: * They should both be bit 32. The fix is to test the right bit.
274: */
275: int mapKey = OS.MapVirtualKey(
276: (int) /*64*/msg.wParam, 2);
277: if (mapKey != 0) {
278: accentKey = (mapKey & (OS.IsWinNT ? 0x80000000
279: : 0x8000)) != 0;
280: if (!accentKey) {
281: for (int i = 0; i < ACCENTS.length; i++) {
282: int value = OS
283: .VkKeyScan(ACCENTS[i]);
284: if (value != -1
285: && (value & 0xFF) == msg.wParam) {
286: int state = value >> 8;
287: if ((OS
288: .GetKeyState(OS.VK_SHIFT) < 0) == ((state & 0x1) != 0)
289: && (OS
290: .GetKeyState(OS.VK_CONTROL) < 0) == ((state & 0x2) != 0)
291: && (OS
292: .GetKeyState(OS.VK_MENU) < 0) == ((state & 0x4) != 0)) {
293: if ((state & 0x7) != 0)
294: accentKey = true;
295: break;
296: }
297: }
298: }
299: }
300: }
301: break;
302: }
303: }
304: }
305: break;
306: }
307: }
308: /* Allow OleClientSite to process key events before activeX control */
309: if (!consumed && !accentKey && !ignoreNextKey) {
310: int /*long*/hwndOld = msg.hwnd;
311: msg.hwnd = site.handle;
312: consumed = OS.DispatchMessage(msg) == 1;
313: msg.hwnd = hwndOld;
314: }
315: switch (msg.message) {
316: case OS.WM_KEYDOWN:
317: case OS.WM_SYSKEYDOWN: {
318: switch ((int) /*64*/msg.wParam) {
319: case OS.VK_SHIFT:
320: case OS.VK_MENU:
321: case OS.VK_CONTROL:
322: case OS.VK_CAPITAL:
323: case OS.VK_NUMLOCK:
324: case OS.VK_SCROLL:
325: break;
326: default: {
327: ignoreNextKey = accentKey;
328: break;
329: }
330: }
331: }
332: }
333:
334: if (consumed) {
335: // In order to prevent this message from also being processed
336: // by the application, zero out message, wParam and lParam
337: msg.message = OS.WM_NULL;
338: msg.wParam = msg.lParam = 0;
339: OS.MoveMemory(lParam, msg, MSG.sizeof);
340: return 0;
341: }
342: }
343: }
344: }
345: }
346: return OS.CallNextHookEx(hHook.value, (int) /*64*/code,
347: wParam, lParam);
348: }
349:
350: /**
351: * Increment the count of references to this instance
352: *
353: * @return the current reference count
354: */
355: int AddRef() {
356: refCount++;
357: return refCount;
358: }
359:
360: private int ContextSensitiveHelp(int fEnterMode) {
361: return COM.S_OK;
362: }
363:
364: private void createCOMInterfaces() {
365: // Create each of the interfaces that this object implements
366: iUnknown = new COMObject(new int[] { 2, 0, 0 }) {
367: public int /*long*/method0(int /*long*/[] args) {
368: return QueryInterface(args[0], args[1]);
369: }
370:
371: public int /*long*/method1(int /*long*/[] args) {
372: return AddRef();
373: }
374:
375: public int /*long*/method2(int /*long*/[] args) {
376: return Release();
377: }
378: };
379:
380: iOleInPlaceFrame = new COMObject(new int[] { 2, 0, 0, 1, 1, 1,
381: 1, 1, 2, 2, 3, 1, 1, 1, 2 }) {
382: public int /*long*/method0(int /*long*/[] args) {
383: return QueryInterface(args[0], args[1]);
384: }
385:
386: public int /*long*/method1(int /*long*/[] args) {
387: return AddRef();
388: }
389:
390: public int /*long*/method2(int /*long*/[] args) {
391: return Release();
392: }
393:
394: public int /*long*/method3(int /*long*/[] args) {
395: return GetWindow(args[0]);
396: }
397:
398: public int /*long*/method4(int /*long*/[] args) {
399: return ContextSensitiveHelp((int) /*64*/args[0]);
400: }
401:
402: public int /*long*/method5(int /*long*/[] args) {
403: return GetBorder(args[0]);
404: }
405:
406: public int /*long*/method6(int /*long*/[] args) {
407: return RequestBorderSpace(args[0]);
408: }
409:
410: public int /*long*/method7(int /*long*/[] args) {
411: return SetBorderSpace(args[0]);
412: }
413:
414: public int /*long*/method8(int /*long*/[] args) {
415: return SetActiveObject(args[0], args[1]);
416: }
417:
418: public int /*long*/method9(int /*long*/[] args) {
419: return InsertMenus(args[0], args[1]);
420: }
421:
422: public int /*long*/method10(int /*long*/[] args) {
423: return SetMenu(args[0], args[1], args[2]);
424: }
425:
426: public int /*long*/method11(int /*long*/[] args) {
427: return RemoveMenus(args[0]);
428: }
429:
430: // method12 SetStatusText - not implemented
431: // method13 EnableModeless - not implemented
432: public int /*long*/method14(int /*long*/[] args) {
433: return TranslateAccelerator(args[0],
434: (int) /*64*/args[1]);
435: }
436: };
437: }
438:
439: private void disposeCOMInterfaces() {
440:
441: if (iUnknown != null)
442: iUnknown.dispose();
443: iUnknown = null;
444:
445: if (iOleInPlaceFrame != null)
446: iOleInPlaceFrame.dispose();
447: iOleInPlaceFrame = null;
448: }
449:
450: private int GetBorder(int /*long*/lprectBorder) {
451: /*
452: The IOleInPlaceUIWindow::GetBorder function, when called on a document or frame window
453: object, returns the outer rectangle (relative to the window) where the object can put
454: toolbars or similar controls.
455: */
456: if (lprectBorder == 0)
457: return COM.E_INVALIDARG;
458: RECT rectBorder = new RECT();
459: // Coordinates must be relative to the window
460: OS.GetClientRect(handle, rectBorder);
461: OS.MoveMemory(lprectBorder, rectBorder, RECT.sizeof);
462: return COM.S_OK;
463: }
464:
465: /**
466: *
467: * Returns the application menu items that will appear in the Container location when an OLE Document
468: * is in-place activated.
469: *
470: * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
471: * is given the opportunity to merge some of its menus into the menubar. The application
472: * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
473: * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
474: * menu locations. Note that an application can insert more than one menu into a single location.
475: *
476: * @return the application menu items that will appear in the Container location when an OLE Document
477: * is in-place activated.
478: *
479: */
480: public MenuItem[] getContainerMenus() {
481: return containerMenuItems;
482: }
483:
484: /**
485: *
486: * Returns the application menu items that will appear in the File location when an OLE Document
487: * is in-place activated.
488: *
489: * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
490: * is given the opportunity to merge some of its menus into the menubar. The application
491: * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
492: * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
493: * menu locations. Note that an application can insert more than one menu into a single location.
494: *
495: * @return the application menu items that will appear in the File location when an OLE Document
496: * is in-place activated.
497: *
498: */
499: public MenuItem[] getFileMenus() {
500: return fileMenuItems;
501: }
502:
503: int /*long*/getIOleInPlaceFrame() {
504: return iOleInPlaceFrame.getAddress();
505: }
506:
507: private int /*long*/getMenuItemID(int /*long*/hMenu, int index) {
508: int /*long*/id = 0;
509: MENUITEMINFO lpmii = new MENUITEMINFO();
510: lpmii.cbSize = MENUITEMINFO.sizeof;
511: lpmii.fMask = OS.MIIM_STATE | OS.MIIM_SUBMENU | OS.MIIM_ID;
512: OS.GetMenuItemInfo(hMenu, index, true, lpmii);
513: if ((lpmii.fState & OS.MF_POPUP) == OS.MF_POPUP) {
514: id = lpmii.hSubMenu;
515: } else {
516: id = lpmii.wID;
517: }
518: return id;
519: }
520:
521: private int GetWindow(int /*long*/phwnd) {
522: if (phwnd != 0) {
523: COM.MoveMemory(phwnd, new int /*long*/[] { handle },
524: OS.PTR_SIZEOF);
525: }
526: return COM.S_OK;
527: }
528:
529: /**
530: *
531: * Returns the application menu items that will appear in the Window location when an OLE Document
532: * is in-place activated.
533: *
534: * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
535: * is given the opportunity to merge some of its menus into the menubar. The application
536: * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
537: * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
538: * menu locations. Note that an application can insert more than one menu into a single location.
539: *
540: * @return the application menu items that will appear in the Window location when an OLE Document
541: * is in-place activated.
542: *
543: */
544: public MenuItem[] getWindowMenus() {
545: return windowMenuItems;
546: }
547:
548: private int InsertMenus(int /*long*/hmenuShared,
549: int /*long*/lpMenuWidths) {
550: // locate menu bar
551: Menu menubar = getShell().getMenuBar();
552: if (menubar == null || menubar.isDisposed()) {
553: COM.MoveMemory(lpMenuWidths, new int[] { 0 }, 4);
554: return COM.S_OK;
555: }
556: int /*long*/hMenu = menubar.handle;
557:
558: // Create a holder for menu information. This will be passed down to
559: // the OS and the OS will fill in the requested information for each menu.
560: MENUITEMINFO lpmii = new MENUITEMINFO();
561: int /*long*/hHeap = OS.GetProcessHeap();
562: int cch = 128;
563: int byteCount = cch * TCHAR.sizeof;
564: int /*long*/pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY,
565: byteCount);
566: lpmii.cbSize = MENUITEMINFO.sizeof;
567: lpmii.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE
568: | OS.MIIM_SUBMENU | OS.MIIM_DATA;
569: lpmii.dwTypeData = pszText;
570: lpmii.cch = cch;
571:
572: // Loop over all "File-like" menus in the menubar and get information about the
573: // item from the OS.
574: int fileMenuCount = 0;
575: int newindex = 0;
576: if (this .fileMenuItems != null) {
577: for (int i = 0; i < this .fileMenuItems.length; i++) {
578: MenuItem item = this .fileMenuItems[i];
579: if (item != null) {
580: int index = item.getParent().indexOf(item);
581: lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
582: // exact number of characters in name. Reset it to our max size
583: // before each call.
584: if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) {
585: if (OS.InsertMenuItem(hmenuShared, newindex,
586: true, lpmii)) {
587: // keep track of the number of items
588: fileMenuCount++;
589: newindex++;
590: }
591: }
592: }
593: }
594: }
595:
596: // copy the menu item count information to the pointer
597: COM.MoveMemory(lpMenuWidths, new int[] { fileMenuCount }, 4);
598:
599: // Loop over all "Container-like" menus in the menubar and get information about the
600: // item from the OS.
601: int containerMenuCount = 0;
602: if (this .containerMenuItems != null) {
603: for (int i = 0; i < this .containerMenuItems.length; i++) {
604: MenuItem item = this .containerMenuItems[i];
605: if (item != null) {
606: int index = item.getParent().indexOf(item);
607: lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
608: // exact number of characters in name. Reset it to a large number
609: // before each call.
610: if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) {
611: if (OS.InsertMenuItem(hmenuShared, newindex,
612: true, lpmii)) {
613: // keep track of the number of items
614: containerMenuCount++;
615: newindex++;
616: }
617: }
618: }
619: }
620: }
621:
622: // copy the menu item count information to the pointer
623: COM.MoveMemory(lpMenuWidths + 8,
624: new int[] { containerMenuCount }, 4);
625:
626: // Loop over all "Window-like" menus in the menubar and get information about the
627: // item from the OS.
628: int windowMenuCount = 0;
629: if (this .windowMenuItems != null) {
630: for (int i = 0; i < this .windowMenuItems.length; i++) {
631: MenuItem item = this .windowMenuItems[i];
632: if (item != null) {
633: int index = item.getParent().indexOf(item);
634: lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
635: // exact number of characters in name. Reset it to a large number
636: // before each call.
637: if (OS.GetMenuItemInfo(hMenu, index, true, lpmii)) {
638: if (OS.InsertMenuItem(hmenuShared, newindex,
639: true, lpmii)) {
640: // keep track of the number of items
641: windowMenuCount++;
642: newindex++;
643: }
644: }
645: }
646: }
647: }
648:
649: // copy the menu item count information to the pointer
650: COM.MoveMemory(lpMenuWidths + 16,
651: new int[] { windowMenuCount }, 4);
652:
653: // free resources used in querying the OS
654: if (pszText != 0)
655: OS.HeapFree(hHeap, 0, pszText);
656: return COM.S_OK;
657: }
658:
659: void onActivate(Event e) {
660: if (objIOleInPlaceActiveObject != null) {
661: objIOleInPlaceActiveObject.OnFrameWindowActivate(true);
662: }
663: if (objIOleInPlaceActiveObject != null) {
664: objIOleInPlaceActiveObject.OnDocWindowActivate(true);
665: }
666: }
667:
668: void onDeactivate(Event e) {
669: if (objIOleInPlaceActiveObject != null) {
670: objIOleInPlaceActiveObject.OnFrameWindowActivate(false);
671: }
672: if (objIOleInPlaceActiveObject != null) {
673: objIOleInPlaceActiveObject.OnDocWindowActivate(false);
674: }
675: }
676:
677: private void onDispose(Event e) {
678:
679: releaseObjectInterfaces();
680: currentdoc = null;
681:
682: this .Release();
683: removeListener(SWT.Activate, listener);
684: removeListener(SWT.Deactivate, listener);
685: removeListener(SWT.Dispose, listener);
686: removeListener(SWT.Resize, listener);
687: removeListener(SWT.Move, listener);
688: }
689:
690: private void onResize(Event e) {
691: if (objIOleInPlaceActiveObject != null) {
692: RECT lpRect = new RECT();
693: OS.GetClientRect(handle, lpRect);
694: objIOleInPlaceActiveObject.ResizeBorder(lpRect,
695: iOleInPlaceFrame.getAddress(), true);
696: }
697: }
698:
699: private int QueryInterface(int /*long*/riid,
700: int /*long*/ppvObject) {
701: // implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow
702: if (riid == 0 || ppvObject == 0)
703: return COM.E_INVALIDARG;
704: GUID guid = new GUID();
705: COM.MoveMemory(guid, riid, GUID.sizeof);
706: if (COM.IsEqualGUID(guid, COM.IIDIUnknown)
707: || COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame)) {
708: COM
709: .MoveMemory(ppvObject,
710: new int /*long*/[] { iOleInPlaceFrame
711: .getAddress() }, OS.PTR_SIZEOF);
712: AddRef();
713: return COM.S_OK;
714: }
715:
716: COM.MoveMemory(ppvObject, new int /*long*/[] { 0 },
717: OS.PTR_SIZEOF);
718: return COM.E_NOINTERFACE;
719: }
720:
721: /**
722: * Decrement the count of references to this instance
723: *
724: * @return the current reference count
725: */
726: int Release() {
727: refCount--;
728: if (refCount == 0) {
729: disposeCOMInterfaces();
730: COM.CoFreeUnusedLibraries();
731: }
732: return refCount;
733: }
734:
735: private void releaseObjectInterfaces() {
736: if (objIOleInPlaceActiveObject != null) {
737: objIOleInPlaceActiveObject.Release();
738: }
739: objIOleInPlaceActiveObject = null;
740: }
741:
742: private int RemoveMenus(int /*long*/hmenuShared) {
743:
744: Menu menubar = getShell().getMenuBar();
745: if (menubar == null || menubar.isDisposed())
746: return COM.S_FALSE;
747:
748: int /*long*/hMenu = menubar.handle;
749:
750: Vector ids = new Vector();
751: if (this .fileMenuItems != null) {
752: for (int i = 0; i < this .fileMenuItems.length; i++) {
753: MenuItem item = this .fileMenuItems[i];
754: if (item != null && !item.isDisposed()) {
755: int index = item.getParent().indexOf(item);
756: // get Id from original menubar
757: int /*long*/id = getMenuItemID(hMenu, index);
758: ids.addElement(new LONG(id));
759: }
760: }
761: }
762: if (this .containerMenuItems != null) {
763: for (int i = 0; i < this .containerMenuItems.length; i++) {
764: MenuItem item = this .containerMenuItems[i];
765: if (item != null && !item.isDisposed()) {
766: int index = item.getParent().indexOf(item);
767: int /*long*/id = getMenuItemID(hMenu, index);
768: ids.addElement(new LONG(id));
769: }
770: }
771: }
772: if (this .windowMenuItems != null) {
773: for (int i = 0; i < this .windowMenuItems.length; i++) {
774: MenuItem item = this .windowMenuItems[i];
775: if (item != null && !item.isDisposed()) {
776: int index = item.getParent().indexOf(item);
777: int /*long*/id = getMenuItemID(hMenu, index);
778: ids.addElement(new LONG(id));
779: }
780: }
781: }
782: int index = OS.GetMenuItemCount(hmenuShared) - 1;
783: for (int i = index; i >= 0; i--) {
784: int /*long*/id = getMenuItemID(hmenuShared, i);
785: if (ids.contains(new LONG(id))) {
786: OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION);
787: }
788: }
789: return COM.S_OK;
790: }
791:
792: private int RequestBorderSpace(int /*long*/pborderwidths) {
793: return COM.S_OK;
794: }
795:
796: int SetActiveObject(int /*long*/pActiveObject,
797: int /*long*/pszObjName) {
798: if (objIOleInPlaceActiveObject != null) {
799: objIOleInPlaceActiveObject.Release();
800: objIOleInPlaceActiveObject = null;
801: }
802: if (pActiveObject != 0) {
803: objIOleInPlaceActiveObject = new IOleInPlaceActiveObject(
804: pActiveObject);
805: objIOleInPlaceActiveObject.AddRef();
806: }
807:
808: return COM.S_OK;
809: }
810:
811: private int SetBorderSpace(int /*long*/pborderwidths) {
812: // A Control/Document can :
813: // Use its own toolbars, requesting border space of a specific size, or,
814: // Use no toolbars, but force the container to remove its toolbars by passing a
815: // valid BORDERWIDTHS structure containing nothing but zeros in the pborderwidths parameter, or,
816: // Use no toolbars but allow the in-place container to leave its toolbars up by
817: // passing NULL as the pborderwidths parameter.
818: if (objIOleInPlaceActiveObject == null)
819: return COM.S_OK;
820: RECT borderwidth = new RECT();
821: if (pborderwidths == 0 || currentdoc == null)
822: return COM.S_OK;
823:
824: COM.MoveMemory(borderwidth, pborderwidths, RECT.sizeof);
825: currentdoc.setBorderSpace(borderwidth);
826:
827: return COM.S_OK;
828: }
829:
830: /**
831: *
832: * Specify the menu items that should appear in the Container location when an OLE Document
833: * is in-place activated.
834: *
835: * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
836: * is given the opportunity to merge some of its menus into the menubar. The application
837: * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
838: * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
839: * menu locations. Note that an application can insert more than one menu into a single location.
840: *
841: * <p>This method must be called before in place activation of the OLE Document. After the Document
842: * is activated, the menu bar will not be modified until a subsequent activation.
843: *
844: * @param containerMenus an array of top level MenuItems to be inserted into the Container location of
845: * the menubar
846: */
847: public void setContainerMenus(MenuItem[] containerMenus) {
848: containerMenuItems = containerMenus;
849: }
850:
851: OleClientSite getCurrentDocument() {
852: return currentdoc;
853: }
854:
855: void setCurrentDocument(OleClientSite doc) {
856: currentdoc = doc;
857:
858: if (currentdoc != null && objIOleInPlaceActiveObject != null) {
859: RECT lpRect = new RECT();
860: OS.GetClientRect(handle, lpRect);
861: objIOleInPlaceActiveObject.ResizeBorder(lpRect,
862: iOleInPlaceFrame.getAddress(), true);
863: }
864: }
865:
866: /**
867: *
868: * Specify the menu items that should appear in the File location when an OLE Document
869: * is in-place activated.
870: *
871: * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
872: * is given the opportunity to merge some of its menus into the menubar. The application
873: * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
874: * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
875: * menu locations. Note that an application can insert more than one menu into a single location.
876: *
877: * <p>This method must be called before in place activation of the OLE Document. After the Document
878: * is activated, the menu bar will not be modified until a subsequent activation.
879: *
880: * @param fileMenus an array of top level MenuItems to be inserted into the File location of
881: * the menubar
882: */
883: public void setFileMenus(MenuItem[] fileMenus) {
884: fileMenuItems = fileMenus;
885: }
886:
887: private int SetMenu(int /*long*/hmenuShared,
888: int /*long*/holemenu, int /*long*/hwndActiveObject) {
889: int /*long*/inPlaceActiveObject = 0;
890: if (objIOleInPlaceActiveObject != null)
891: inPlaceActiveObject = objIOleInPlaceActiveObject
892: .getAddress();
893:
894: Menu menubar = getShell().getMenuBar();
895: if (menubar == null || menubar.isDisposed()) {
896: return COM.OleSetMenuDescriptor(0, getShell().handle,
897: hwndActiveObject, iOleInPlaceFrame.getAddress(),
898: inPlaceActiveObject);
899: }
900:
901: int /*long*/handle = menubar.getShell().handle;
902:
903: if (hmenuShared == 0 && holemenu == 0) {
904: // re-instate the original menu - this occurs on deactivation
905: hmenuShared = menubar.handle;
906: }
907: if (hmenuShared == 0)
908: return COM.E_FAIL;
909:
910: OS.SetMenu(handle, hmenuShared);
911: OS.DrawMenuBar(handle);
912:
913: return COM.OleSetMenuDescriptor(holemenu, handle,
914: hwndActiveObject, iOleInPlaceFrame.getAddress(),
915: inPlaceActiveObject);
916: }
917:
918: /**
919: *
920: * Set the menu items that should appear in the Window location when an OLE Document
921: * is in-place activated.
922: *
923: * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
924: * is given the opportunity to merge some of its menus into the menubar. The application
925: * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
926: * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
927: * menu locations. Note that an application can insert more than one menu into a single location.
928: *
929: * <p>This method must be called before in place activation of the OLE Document. After the Document
930: * is activated, the menu bar will not be modified until a subsequent activation.
931: *
932: * @param windowMenus an array of top level MenuItems to be inserted into the Window location of
933: * the menubar
934: */
935: public void setWindowMenus(MenuItem[] windowMenus) {
936: windowMenuItems = windowMenus;
937: }
938:
939: private boolean translateOleAccelerator(MSG msg) {
940: if (objIOleInPlaceActiveObject == null)
941: return false;
942: int result = objIOleInPlaceActiveObject
943: .TranslateAccelerator(msg);
944: return (result != COM.S_FALSE && result != COM.E_NOTIMPL);
945: }
946:
947: private int TranslateAccelerator(int /*long*/lpmsg, int wID) {
948: Menu menubar = getShell().getMenuBar();
949: if (menubar == null || menubar.isDisposed()
950: || !menubar.isEnabled())
951: return COM.S_FALSE;
952: if (wID < 0)
953: return COM.S_FALSE;
954:
955: Shell shell = menubar.getShell();
956: int /*long*/hwnd = shell.handle;
957: int /*long*/hAccel = OS.SendMessage(hwnd, OS.WM_APP + 1, 0, 0);
958: if (hAccel == 0)
959: return COM.S_FALSE;
960:
961: MSG msg = new MSG();
962: OS.MoveMemory(msg, lpmsg, MSG.sizeof);
963: int result = OS.TranslateAccelerator(hwnd, hAccel, msg);
964: return result == 0 ? COM.S_FALSE : COM.S_OK;
965: }
966: }
|