status_icon_win.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/status_icons/status_icon_win.h" 6 7#include "base/sys_string_conversions.h" 8#include "third_party/skia/include/core/SkBitmap.h" 9#include "ui/gfx/icon_util.h" 10#include "ui/gfx/point.h" 11#include "views/controls/menu/menu_2.h" 12 13StatusIconWin::StatusIconWin(UINT id, HWND window, UINT message) 14 : icon_id_(id), 15 window_(window), 16 message_id_(message) { 17 NOTIFYICONDATA icon_data; 18 InitIconData(&icon_data); 19 icon_data.uFlags = NIF_MESSAGE; 20 icon_data.uCallbackMessage = message_id_; 21 BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data); 22 // This can happen if the explorer process isn't running when we try to 23 // create the icon for some reason (for example, at startup). 24 if (!result) 25 LOG(WARNING) << "Unable to create status tray icon."; 26} 27 28StatusIconWin::~StatusIconWin() { 29 // Remove our icon. 30 NOTIFYICONDATA icon_data; 31 InitIconData(&icon_data); 32 Shell_NotifyIcon(NIM_DELETE, &icon_data); 33} 34 35void StatusIconWin::SetImage(const SkBitmap& image) { 36 // Create the icon. 37 NOTIFYICONDATA icon_data; 38 InitIconData(&icon_data); 39 icon_data.uFlags = NIF_ICON; 40 icon_.Set(IconUtil::CreateHICONFromSkBitmap(image)); 41 icon_data.hIcon = icon_.Get(); 42 BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data); 43 if (!result) 44 LOG(WARNING) << "Error setting status tray icon image"; 45} 46 47void StatusIconWin::ResetIcon() { 48 NOTIFYICONDATA icon_data; 49 InitIconData(&icon_data); 50 // Delete any previously existing icon. 51 Shell_NotifyIcon(NIM_DELETE, &icon_data); 52 InitIconData(&icon_data); 53 icon_data.uFlags = NIF_MESSAGE; 54 icon_data.uCallbackMessage = message_id_; 55 icon_data.hIcon = icon_.Get(); 56 // If we have an image, then set the NIF_ICON flag, which tells 57 // Shell_NotifyIcon() to set the image for the status icon it creates. 58 if (icon_data.hIcon) 59 icon_data.uFlags |= NIF_ICON; 60 // Re-add our icon. 61 BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data); 62 if (!result) 63 LOG(WARNING) << "Unable to re-create status tray icon."; 64} 65 66void StatusIconWin::SetPressedImage(const SkBitmap& image) { 67 // Ignore pressed images, since the standard on Windows is to not highlight 68 // pressed status icons. 69} 70 71void StatusIconWin::SetToolTip(const string16& tool_tip) { 72 // Create the icon. 73 NOTIFYICONDATA icon_data; 74 InitIconData(&icon_data); 75 icon_data.uFlags = NIF_TIP; 76 wcscpy_s(icon_data.szTip, tool_tip.c_str()); 77 BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data); 78 if (!result) 79 LOG(WARNING) << "Unable to set tooltip for status tray icon"; 80} 81 82void StatusIconWin::InitIconData(NOTIFYICONDATA* icon_data) { 83 icon_data->cbSize = sizeof(icon_data); 84 icon_data->hWnd = window_; 85 icon_data->uID = icon_id_; 86} 87 88void StatusIconWin::UpdatePlatformContextMenu(ui::MenuModel* menu) { 89 // If no items are passed, blow away our context menu. 90 if (!menu) { 91 context_menu_.reset(); 92 return; 93 } 94 95 // Create context menu with the new contents. 96 context_menu_.reset(new views::Menu2(menu)); 97} 98 99void StatusIconWin::HandleClickEvent(int x, int y, bool left_mouse_click) { 100 // Pass to the observer if appropriate. 101 if (left_mouse_click && HasObservers()) { 102 DispatchClickEvent(); 103 return; 104 } 105 106 // Event not sent to the observer, so display the context menu if one exists. 107 if (context_menu_.get()) { 108 // Set our window as the foreground window, so the context menu closes when 109 // we click away from it. 110 SetForegroundWindow(window_); 111 context_menu_->RunContextMenuAt(gfx::Point(x, y)); 112 } 113} 114