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_tray_win.h" 6 7#include "base/win/wrapped_window_proc.h" 8#include "chrome/browser/ui/views/status_icons/status_icon_win.h" 9#include "chrome/common/chrome_constants.h" 10#include "ui/base/win/hwnd_util.h" 11 12static const UINT kStatusIconMessage = WM_APP + 1; 13 14StatusTrayWin::StatusTrayWin() 15 : next_icon_id_(1) { 16 // Register our window class 17 HINSTANCE hinst = GetModuleHandle(NULL); 18 WNDCLASSEX wc = {0}; 19 wc.cbSize = sizeof(wc); 20 wc.lpfnWndProc = base::win::WrappedWindowProc<StatusTrayWin::WndProcStatic>; 21 wc.hInstance = hinst; 22 wc.lpszClassName = chrome::kStatusTrayWindowClass; 23 ATOM clazz = RegisterClassEx(&wc); 24 DCHECK(clazz); 25 26 // If the taskbar is re-created after we start up, we have to rebuild all of 27 // our icons. 28 taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated")); 29 30 // Create an offscreen window for handling messages for the status icons. We 31 // create a hidden WS_POPUP window instead of an HWND_MESSAGE window, because 32 // only top-level windows such as popups can receive broadcast messages like 33 // "TaskbarCreated". 34 window_ = CreateWindow(chrome::kStatusTrayWindowClass, 35 0, WS_POPUP, 0, 0, 0, 0, 0, 0, hinst, 0); 36 ui::CheckWindowCreated(window_); 37 ui::SetWindowUserData(window_, this); 38} 39 40LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd, 41 UINT message, 42 WPARAM wparam, 43 LPARAM lparam) { 44 StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>( 45 GetWindowLongPtr(hwnd, GWLP_USERDATA)); 46 if (msg_wnd) 47 return msg_wnd->WndProc(hwnd, message, wparam, lparam); 48 else 49 return ::DefWindowProc(hwnd, message, wparam, lparam); 50} 51 52LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd, 53 UINT message, 54 WPARAM wparam, 55 LPARAM lparam) { 56 if (message == taskbar_created_message_) { 57 // We need to reset all of our icons because the taskbar went away. 58 for (StatusIconList::const_iterator iter = status_icons().begin(); 59 iter != status_icons().end(); 60 ++iter) { 61 StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter); 62 win_icon->ResetIcon(); 63 } 64 return TRUE; 65 } else if (message == kStatusIconMessage) { 66 switch (lparam) { 67 case WM_LBUTTONDOWN: 68 case WM_RBUTTONDOWN: 69 case WM_CONTEXTMENU: 70 // Walk our icons, find which one was clicked on, and invoke its 71 // HandleClickEvent() method. 72 for (StatusIconList::const_iterator iter = status_icons().begin(); 73 iter != status_icons().end(); 74 ++iter) { 75 StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter); 76 if (win_icon->icon_id() == wparam) { 77 POINT p; 78 GetCursorPos(&p); 79 win_icon->HandleClickEvent(p.x, p.y, lparam == WM_LBUTTONDOWN); 80 } 81 } 82 return TRUE; 83 } 84 } 85 return ::DefWindowProc(hwnd, message, wparam, lparam); 86} 87 88StatusTrayWin::~StatusTrayWin() { 89 if (window_) 90 DestroyWindow(window_); 91 UnregisterClass(chrome::kStatusTrayWindowClass, GetModuleHandle(NULL)); 92} 93 94StatusIcon* StatusTrayWin::CreatePlatformStatusIcon() { 95 return new StatusIconWin(next_icon_id_++, window_, kStatusIconMessage); 96} 97 98StatusTray* StatusTray::Create() { 99 return new StatusTrayWin(); 100} 101