summaryrefslogtreecommitdiffstats
path: root/chrome_frame/in_place_menu.h
diff options
context:
space:
mode:
authorslightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-24 05:11:58 +0000
committerslightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-24 05:11:58 +0000
commitf781782dd67077478e117c61dca4ea5eefce3544 (patch)
tree4801f724123cfdcbb69c4e7fe40a565b331723ae /chrome_frame/in_place_menu.h
parent63cf4759efa2373e33436fb5df6849f930081226 (diff)
downloadchromium_src-f781782dd67077478e117c61dca4ea5eefce3544.zip
chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.gz
chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.bz2
Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming in a separate CL.
BUG=None TEST=None Review URL: http://codereview.chromium.org/218019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/in_place_menu.h')
-rw-r--r--chrome_frame/in_place_menu.h231
1 files changed, 231 insertions, 0 deletions
diff --git a/chrome_frame/in_place_menu.h b/chrome_frame/in_place_menu.h
new file mode 100644
index 0000000..9742896
--- /dev/null
+++ b/chrome_frame/in_place_menu.h
@@ -0,0 +1,231 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_FRAME_IN_PLACE_MENU_H_
+#define CHROME_FRAME_IN_PLACE_MENU_H_
+
+// in_place_menu.h : menu merging implementation
+//
+// This file is a modified version of the menu.h file, which is
+// part of the ActiveDoc MSDN sample. The modifications are largely
+// conversions to Google coding guidelines. Below is the original header
+// from the file.
+
+// This is a part of the Active Template Library.
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Active Template Library Reference and related
+// electronic documentation provided with the library.
+// See these sources for detailed information regarding the
+// Active Template Library product.
+
+#include "base/logging.h"
+#include "base/scoped_comptr_win.h"
+
+template <class T>
+class InPlaceMenu {
+ public:
+ InPlaceMenu() : shared_menu_(NULL), ole_menu_(NULL), our_menu_(NULL) {
+ }
+
+ ~InPlaceMenu() {
+ InPlaceMenuDestroy();
+ }
+
+ HRESULT InPlaceMenuCreate(LPCWSTR menu_name) {
+ // We might already have an in-place menu set, because we set menus
+ // IOleDocumentView::UIActivate as well as in
+ // IOleInPlaceActiveObject::OnDocWindowActivate. If we have already
+ // done our work, just return silently
+ if (ole_menu_ || shared_menu_)
+ return S_OK;
+
+ ScopedComPtr<IOleInPlaceFrame> in_place_frame;
+ GetInPlaceFrame(in_place_frame.Receive());
+ // We have no IOleInPlaceFrame, no menu merging possible
+ if (!in_place_frame) {
+ NOTREACHED();
+ return E_FAIL;
+ }
+ // Create a blank menu and ask the container to add
+ // its menus into the OLEMENUGROUPWIDTHS structure
+ shared_menu_ = ::CreateMenu();
+ OLEMENUGROUPWIDTHS mgw = {0};
+ HRESULT hr = in_place_frame->InsertMenus(shared_menu_, &mgw);
+ if (FAILED(hr)) {
+ ::DestroyMenu(shared_menu_);
+ shared_menu_ = NULL;
+ return hr;
+ }
+ // Insert our menus
+ our_menu_ = LoadMenu(_AtlBaseModule.GetResourceInstance(),menu_name);
+ MergeMenus(shared_menu_, our_menu_, &mgw.width[0], 1);
+ // Send the menu to the client
+ ole_menu_ = (HMENU)OleCreateMenuDescriptor(shared_menu_, &mgw);
+ T* t = static_cast<T*>(this);
+ in_place_frame->SetMenu(shared_menu_, ole_menu_, t->m_hWnd);
+ return S_OK;
+ }
+
+ HRESULT InPlaceMenuDestroy() {
+ ScopedComPtr<IOleInPlaceFrame> in_place_frame;
+ GetInPlaceFrame(in_place_frame.Receive());
+ if (in_place_frame) {
+ in_place_frame->RemoveMenus(shared_menu_);
+ in_place_frame->SetMenu(NULL, NULL, NULL);
+ }
+ if (ole_menu_) {
+ OleDestroyMenuDescriptor(ole_menu_);
+ ole_menu_ = NULL;
+ }
+ if (shared_menu_) {
+ UnmergeMenus(shared_menu_, our_menu_);
+ DestroyMenu(shared_menu_);
+ shared_menu_ = NULL;
+ }
+ if (our_menu_) {
+ DestroyMenu(our_menu_);
+ our_menu_ = NULL;
+ }
+ return S_OK;
+ }
+
+ void MergeMenus(HMENU shared_menu, HMENU source_menu, LONG* menu_widths,
+ unsigned int width_index) {
+ // Copy the popups from the source menu
+ // Insert at appropriate spot depending on width_index
+ DCHECK(width_index == 0 || width_index == 1);
+ int position = 0;
+ if (width_index == 1)
+ position = (int)menu_widths[0];
+ int group_width = 0;
+ int menu_items = GetMenuItemCount(source_menu);
+ for (int index = 0; index < menu_items; index++) {
+ // Get the HMENU of the popup
+ HMENU popup_menu = ::GetSubMenu(source_menu, index);
+ // Separators move us to next group
+ UINT state = GetMenuState(source_menu, index, MF_BYPOSITION);
+ if (!popup_menu && (state & MF_SEPARATOR)) {
+ // Servers should not touch past 5
+ DCHECK(width_index <= 5);
+ menu_widths[width_index] = group_width;
+ group_width = 0;
+ if (width_index < 5)
+ position += static_cast<int>(menu_widths[width_index+1]);
+ width_index += 2;
+ } else {
+ // Get the menu item text
+ TCHAR item_text[256] = {0};
+ int text_length = GetMenuString(source_menu, index, item_text,
+ ARRAYSIZE(item_text), MF_BYPOSITION);
+ // Popups are handled differently than normal menu items
+ if (popup_menu) {
+ if (::GetMenuItemCount(popup_menu) != 0) {
+ // Strip the HIBYTE because it contains a count of items
+ state = LOBYTE(state) | MF_POPUP; // Must be popup
+ // Non-empty popup -- add it to the shared menu bar
+ InsertMenu(shared_menu, position, state|MF_BYPOSITION,
+ reinterpret_cast<UINT_PTR>(popup_menu), item_text);
+ ++position;
+ ++group_width;
+ }
+ } else if (text_length > 0) {
+ // only non-empty items are added
+ DCHECK(item_text[0] != 0);
+ // here the state does not contain a count in the HIBYTE
+ InsertMenu(shared_menu, position, state|MF_BYPOSITION,
+ GetMenuItemID(source_menu, index), item_text);
+ ++position;
+ ++group_width;
+ }
+ }
+ }
+ }
+
+ void UnmergeMenus(HMENU shared_menu, HMENU source_menu) {
+ int our_item_count = GetMenuItemCount(source_menu);
+ int shared_item_count = GetMenuItemCount(shared_menu);
+
+ for (int index = shared_item_count - 1; index >= 0; index--) {
+ // Check the popup menus
+ HMENU popup_menu = ::GetSubMenu(shared_menu, index);
+ if (popup_menu) {
+ // If it is one of ours, remove it from the shared menu
+ for (int sub_index = 0; sub_index < our_item_count; sub_index++) {
+ if (::GetSubMenu(source_menu, sub_index) == popup_menu) {
+ // Remove the menu from hMenuShared
+ RemoveMenu(shared_menu, index, MF_BYPOSITION);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ protected:
+ HRESULT GetInPlaceFrame(IOleInPlaceFrame** in_place_frame) {
+ if (!in_place_frame) {
+ NOTREACHED();
+ return E_POINTER;
+ }
+ T* t = static_cast<T*>(this);
+ HRESULT hr = E_FAIL;
+ if (!t->in_place_frame_) {
+ // We weren't given an IOleInPlaceFrame pointer, so
+ // we'll have to get it ourselves.
+ if (t->m_spInPlaceSite) {
+ t->frame_info_.cb = sizeof(OLEINPLACEFRAMEINFO);
+ ScopedComPtr<IOleInPlaceUIWindow> in_place_ui_window;
+ RECT position_rect = {0};
+ RECT clip_rect = {0};
+ hr = t->m_spInPlaceSite->GetWindowContext(in_place_frame,
+ in_place_ui_window.Receive(),
+ &position_rect, &clip_rect,
+ &t->frame_info_);
+ }
+ } else {
+ *in_place_frame = t->in_place_frame_;
+ (*in_place_frame)->AddRef();
+ hr = S_OK;
+ }
+ return hr;
+ }
+
+ protected:
+ // The OLE menu descriptor created by the OleCreateMenuDescriptor
+ HMENU ole_menu_;
+ // The shared menu that we pass to IOleInPlaceFrame::SetMenu
+ HMENU shared_menu_;
+ // Our menu resource that we want to insert
+ HMENU our_menu_;
+};
+
+#endif // CHROME_FRAME_IN_PLACE_MENU_H_
+