Index: base/popup_menu.cc |
diff --git a/base/popup_menu.cc b/base/popup_menu.cc |
deleted file mode 100644 |
index bfb15e5c260888a710d88b9a1712747ce4727e5c..0000000000000000000000000000000000000000 |
--- a/base/popup_menu.cc |
+++ /dev/null |
@@ -1,464 +0,0 @@ |
-// Copyright 2005-2009 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
-// ======================================================================== |
- |
-#include "omaha/base/popup_menu.h" |
- |
-#include <windows.h> |
-#include "omaha/base/debug.h" |
-#include "omaha/base/error.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/string.h" |
-#include "omaha/base/utils.h" |
- |
-namespace omaha { |
- |
-// Hold owner draw data |
-struct OwnerDrawData { |
- HFONT font; |
- CString text; |
- HICON icon; |
- |
- OwnerDrawData(HFONT f, const TCHAR* t, HICON i) { |
- font = f; |
- text = t; |
- icon = i; |
- } |
-}; |
- |
- |
-// Default constructor |
-PopupMenu::PopupMenu() |
- : wnd_(NULL) { |
- reset(menu_, ::CreatePopupMenu()); |
- ASSERT1(menu_); |
-} |
- |
-// Constructor |
-PopupMenu::PopupMenu(HINSTANCE inst, const TCHAR* name) |
- : wnd_(NULL) { |
- LoadFromResource(inst, name); |
- ASSERT1(menu_); |
-} |
- |
-// Destructor |
-PopupMenu::~PopupMenu() { |
-} |
- |
-// Load from resource |
-bool PopupMenu::LoadFromResource(HINSTANCE inst, const TCHAR* name) { |
- reset(menu_, GetSubMenu(reinterpret_cast<HMENU>(::LoadMenu(inst, name)), 0)); |
- return get(menu_) != NULL; |
-} |
- |
-// Append menu item |
-bool PopupMenu::AppendMenuItem(int menu_item_id, const TCHAR* text) { |
- return AppendMenuItem(menu_item_id, text, NULL); |
-} |
- |
-// Append menu item |
-bool PopupMenu::AppendMenuItem(int menu_item_id, |
- const TCHAR* text, |
- const MenuItemDrawStyle* style) { |
- int count = ::GetMenuItemCount(get(menu_)); |
- if (count == -1) |
- return false; |
- |
- return InsertMenuItem(menu_item_id, count, true, text, style); |
-} |
- |
-// Append separator |
-bool PopupMenu::AppendSeparator() { |
- return AppendMenuItem(-1, NULL, NULL); |
-} |
- |
-// Insert menu item |
-bool PopupMenu::InsertMenuItem(int menu_item_id, |
- int before_item, |
- bool by_pos, |
- const TCHAR* text) { |
- return InsertMenuItem(menu_item_id, before_item, by_pos, text, NULL); |
-} |
- |
-// Helper function that populates the MENUITEMINFO structure and sets |
-// accelerator keys for OWNERDRAW menu items |
-MENUITEMINFO PopupMenu::PrepareMenuItemInfo(int menu_item_id, const TCHAR* text, |
- const MenuItemDrawStyle* style) { |
- // Fill in the MENUITEMINFO structure |
- MENUITEMINFO menuitem_info; |
- SetZero(menuitem_info); |
- menuitem_info.cbSize = sizeof(MENUITEMINFO); |
- menuitem_info.wID = menu_item_id; |
- if (text == NULL) { |
- menuitem_info.fMask = MIIM_FTYPE | MIIM_ID; |
- menuitem_info.fType = MFT_SEPARATOR; |
- } else { |
- if (!style) { |
- menuitem_info.fMask = MIIM_STRING | MIIM_ID; |
- menuitem_info.fType = MFT_STRING; |
- menuitem_info.dwTypeData = const_cast<TCHAR*>(text); |
- } else { |
- // Handle bold font style |
- HFONT font = NULL; |
- if (style->is_bold) { |
- font = GetBoldFont(); |
- } |
- |
- // Remove '&' if it is there |
- CString text_str(text); |
- int pos = String_FindChar(text_str, _T('&')); |
- if (pos != -1) { |
- if (pos + 1 < text_str.GetLength()) { |
- accelerator_keys_.Add(Char_ToLower(text_str[pos + 1]), menu_item_id); |
- } |
- ReplaceCString(text_str, _T("&"), _T("")); |
- } |
- |
- // Set owner-draw related properties |
- OwnerDrawData* data = new OwnerDrawData(font, text_str, style->icon); |
- menuitem_info.fMask = MIIM_FTYPE | MIIM_DATA | MIIM_ID; |
- menuitem_info.fType = MFT_OWNERDRAW; |
- menuitem_info.dwItemData = reinterpret_cast<ULONG_PTR>(data); |
- } |
- } |
- |
- return menuitem_info; |
-} |
- |
-// Insert menu item |
-bool PopupMenu::InsertMenuItem(int menu_item_id, |
- int before_item, |
- bool by_pos, |
- const TCHAR* text, |
- const MenuItemDrawStyle* style) { |
- MENUITEMINFO menuitem_info = PrepareMenuItemInfo(menu_item_id, text, style); |
- if (!::InsertMenuItem(get(menu_), before_item, by_pos, &menuitem_info)) |
- return false; |
- |
- return Redraw(); |
-} |
- |
-// Insert separator |
-bool PopupMenu::InsertSeparator(int before_item, bool by_pos) { |
- return InsertMenuItem(-1, before_item, by_pos, NULL, NULL); |
-} |
- |
-// Modify a given menu item |
-bool PopupMenu::ModifyMenuItem(int menu_item, bool by_pos, const TCHAR* text, |
- const MenuItemDrawStyle* style) { |
- // Get OWNERDRAW data for later deletion |
- MENUITEMINFO menuitem_info; |
- SetZero(menuitem_info); |
- menuitem_info.cbSize = sizeof(MENUITEMINFO); |
- menuitem_info.fMask = MIIM_FTYPE | MIIM_DATA; |
- if (!::GetMenuItemInfo(get(menu_), menu_item, by_pos, &menuitem_info)) { |
- return false; |
- } |
- |
- OwnerDrawData* old_owner_data = NULL; |
- if ((menuitem_info.fType | MFT_OWNERDRAW) && menuitem_info.dwItemData) { |
- old_owner_data = |
- reinterpret_cast<OwnerDrawData *>(menuitem_info.dwItemData); |
- } |
- |
- // Remove old accelerator mapping |
- int menu_item_id = by_pos ? ::GetMenuItemID(get(menu_), menu_item) : |
- menu_item; |
- int key_pos = accelerator_keys_.FindVal(menu_item_id); |
- if (key_pos != -1) { |
- accelerator_keys_.RemoveAt(key_pos); |
- } |
- |
- // Set new menu item info |
- menuitem_info = PrepareMenuItemInfo(menu_item_id, text, style); |
- if (!::SetMenuItemInfo(get(menu_), menu_item, by_pos, &menuitem_info)) { |
- return false; |
- } |
- |
- // Delete old owner draw data |
- if (old_owner_data) { |
- delete old_owner_data; |
- } |
- |
- // Redraw |
- return Redraw(); |
-} |
- |
-// Remove a menu item |
-bool PopupMenu::RemoveMenuItem(int menu_item, bool by_pos) { |
- // Get OWNERDRAW data for later deletion |
- MENUITEMINFO menuitem_info; |
- SetZero(menuitem_info); |
- menuitem_info.cbSize = sizeof(MENUITEMINFO); |
- menuitem_info.fMask = MIIM_FTYPE | MIIM_DATA; |
- if (!::GetMenuItemInfo(get(menu_), menu_item, by_pos, &menuitem_info)) { |
- return false; |
- } |
- |
- OwnerDrawData* old_owner_data = NULL; |
- if ((menuitem_info.fType | MFT_OWNERDRAW) && menuitem_info.dwItemData) { |
- old_owner_data = |
- reinterpret_cast<OwnerDrawData *>(menuitem_info.dwItemData); |
- } |
- |
- // Remove the menu item |
- if (!::RemoveMenu(get(menu_), menu_item, by_pos ? MF_BYPOSITION : |
- MF_BYCOMMAND)) { |
- return false; |
- } |
- |
- // Remove old accelerator mapping |
- int menu_item_id = by_pos ? ::GetMenuItemID(get(menu_), menu_item) : |
- menu_item; |
- int key_pos = accelerator_keys_.FindVal(menu_item_id); |
- if (key_pos != -1) { |
- accelerator_keys_.RemoveAt(key_pos); |
- } |
- |
- // Delete old owner draw data |
- if (old_owner_data) { |
- delete old_owner_data; |
- } |
- |
- // Redraw |
- return Redraw(); |
-} |
- |
-// Enable menu item |
-bool PopupMenu::EnableMenuItem(int menu_item, bool by_pos, bool enabled) { |
- if (::EnableMenuItem(get(menu_), menu_item, |
- (by_pos ? MF_BYPOSITION : MF_BYCOMMAND) | |
- (enabled ? MF_ENABLED : MF_GRAYED)) == -1) |
- return false; |
- |
- return Redraw(); |
-} |
- |
-// Get menu state |
-bool PopupMenu::GetMenuState(int menu_item, bool by_pos, int* menu_state) { |
- int state = ::GetMenuState(get(menu_), |
- menu_item, by_pos ? MF_BYPOSITION : MF_BYCOMMAND); |
- if (menu_state) |
- *menu_state = state; |
- return state != -1; |
-} |
- |
-// Exists a menu item |
-bool PopupMenu::ExistsMenuItem(int menu_item_id) { |
- return GetMenuState(menu_item_id, false, NULL); |
-} |
- |
-// Redraw menu |
-bool PopupMenu::Redraw() { |
- if (!wnd_) |
- return true; |
- |
- return ::DrawMenuBar(wnd_) == TRUE; |
-} |
- |
-// Track menu |
-bool PopupMenu::Track() { |
- ASSERT1(wnd_); |
- |
- // If we don't set it to be foreground, it will not stop tracking even |
- // if we click outside of menu. |
- ::SetForegroundWindow(wnd_); |
- |
- POINT point = {0, 0}; |
- VERIFY(::GetCursorPos(&point), (_T(""))); |
- |
- uint32 kFlags = TPM_LEFTALIGN | |
- TPM_RETURNCMD | |
- TPM_NONOTIFY | |
- TPM_LEFTBUTTON | |
- TPM_VERTICAL; |
- int command = ::TrackPopupMenuEx(get(menu_), |
- kFlags, |
- point.x, point.y, wnd_, NULL); |
- |
- if (command != 0) |
- ::SendMessage(wnd_, WM_COMMAND, command, 0); |
- |
- return true; |
-} |
- |
-// Handle WM_MEASUREITEM message |
-bool PopupMenu::OnMeasureItem(MEASUREITEMSTRUCT* mi) { |
- ASSERT1(wnd_); |
- |
- // Get owner draw data |
- ASSERT1(mi->itemData); |
- OwnerDrawData* data = reinterpret_cast<OwnerDrawData*>(mi->itemData); |
- |
- // Get the DC |
- scoped_hdc dc; |
- reset(dc, ::GetDC(wnd_)); |
- |
- // Select the font |
- HFONT old_font = reinterpret_cast<HFONT>(::SelectObject(get(dc), data->font)); |
- if (!old_font) |
- return false; |
- |
- // compute the size of the text |
- SIZE size = {0, 0}; |
- bool success = ::GetTextExtentPoint32(get(dc), |
- data->text.GetString(), |
- data->text.GetLength(), |
- &size) != 0; |
- if (success) { |
- mi->itemWidth = size.cx; |
- mi->itemHeight = size.cy; |
- } |
- |
- // deselect the title font |
- ::SelectObject(get(dc), old_font); |
- |
- return success; |
-} |
- |
-// Handle WM_MDRAWITEM message |
-bool PopupMenu::OnDrawItem(DRAWITEMSTRUCT* di) { |
- ASSERT1(di); |
- |
- // Get owner draw data |
- ASSERT1(di->itemData); |
- OwnerDrawData* data = reinterpret_cast<OwnerDrawData*>(di->itemData); |
- |
- // Select the font |
- HFONT prev_font = NULL; |
- if (data->font) { |
- prev_font = reinterpret_cast<HFONT>(::SelectObject(di->hDC, data->font)); |
- if (!prev_font) { |
- return false; |
- } |
- } |
- |
- // Draw the text per the menuitem state |
- int fg_color_idx = |
- (di->itemState & ODS_DISABLED) ? |
- COLOR_GRAYTEXT : |
- ((di->itemState & ODS_SELECTED) ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT); |
- |
- int bg_color_idx = |
- (di->itemState & ODS_SELECTED) ? COLOR_HIGHLIGHT : COLOR_MENU; |
- |
- bool success = DrawText(data->text, di, fg_color_idx, bg_color_idx); |
- |
- // Restore the original font |
- if (prev_font) { |
- ::SelectObject(di->hDC, prev_font); |
- } |
- |
- // Compute the width and height |
- int height = di->rcItem.bottom - di->rcItem.top + 1; |
- int width = static_cast<int>(::GetSystemMetrics(SM_CXMENUCHECK) * |
- (static_cast<double>(height) / ::GetSystemMetrics(SM_CYMENUCHECK))); |
- |
- // Draw the icon |
- // TODO(omaha): Draw a grayed icon when the menuitem is disabled |
- if (success && data->icon) { |
- success = ::DrawIconEx(di->hDC, |
- di->rcItem.left, |
- di->rcItem.top, |
- data->icon, |
- width, |
- height, |
- 0, |
- NULL, |
- DI_NORMAL) != 0; |
- } |
- |
- return success; |
-} |
- |
-// Draw the text |
-bool PopupMenu::DrawText(const CString& text, |
- DRAWITEMSTRUCT* di, |
- int fg_color_idx, |
- int bg_color_idx) { |
- // Set the appropriate foreground and background colors |
- COLORREF prev_fg_color = 0, prev_bg_color = 0; |
- prev_fg_color = ::SetTextColor(di->hDC, ::GetSysColor(fg_color_idx)); |
- if (prev_fg_color == CLR_INVALID) { |
- return false; |
- } |
- prev_bg_color = ::SetBkColor(di->hDC, ::GetSysColor(bg_color_idx)); |
- if (prev_bg_color == CLR_INVALID) { |
- return false; |
- } |
- |
- // Draw the text |
- bool success = ::ExtTextOut( |
- di->hDC, |
- di->rcItem.left + ::GetSystemMetrics(SM_CXMENUCHECK) + 4, |
- di->rcItem.top, |
- ETO_OPAQUE, |
- &di->rcItem, |
- text.GetString(), |
- text.GetLength(), |
- NULL) == TRUE; |
- |
- // Restore the original colors |
- ::SetTextColor(di->hDC, prev_fg_color); |
- ::SetBkColor(di->hDC, prev_bg_color); |
- |
- return success; |
-} |
- |
-// Handle WM_MENUCHAR message |
-int PopupMenu::OnMenuChar(TCHAR key) { |
- int pos = accelerator_keys_.FindKey(Char_ToLower(key)); |
- if (pos != -1) |
- return GetMenuPosFromID(accelerator_keys_.GetValueAt(pos)); |
- else |
- return -1; |
-} |
- |
-HFONT PopupMenu::GetBoldFont() { |
- if (!bold_font_) { |
- NONCLIENTMETRICS ncm; |
- SetZero(ncm); |
- ncm.cbSize = sizeof(NONCLIENTMETRICS); |
- if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) { |
- ncm.lfMenuFont.lfWeight = FW_BOLD; |
- reset(bold_font_, ::CreateFontIndirect(&ncm.lfMenuFont)); |
- } else { |
- UTIL_LOG(LEVEL_ERROR, (_T("[PopupMenu::GetBoldFont]") |
- _T("[failed to get system menu font][0x%x]"), |
- HRESULTFromLastError())); |
- } |
- } |
- |
- ASSERT1(bold_font_); |
- |
- return get(bold_font_); |
-} |
- |
-// Get menu pos from ID |
-int PopupMenu::GetMenuPosFromID(int id) { |
- ASSERT1(id >= 0); |
- int count = ::GetMenuItemCount(get(menu_)); |
- if (count > 0) { |
- for (int pos = 0; pos < count; ++pos) { |
- if (::GetMenuItemID(get(menu_), pos) == static_cast<UINT>(id)) { |
- return pos; |
- } |
- } |
- } |
- |
- return -1; |
-} |
- |
-} // namespace omaha |
- |