📄 taskbar.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/taskbar.cpp
// Purpose: wxTaskBarIcon
// Author: Ryan Norton
// Modified by:
// Created: 09/25/2004
// RCS-ID: $Id: taskbar.cpp,v 1.33 2006/05/21 21:45:30 ABX Exp $
// Copyright: (c) 2004 Ryan Norton
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#ifdef wxHAS_TASK_BAR_ICON
#include "wx/taskbar.h"
#ifndef WX_PRECOMP
#include "wx/dcmemory.h"
#include "wx/menu.h"
#include "wx/toplevel.h"
#include "wx/icon.h"
#endif
#include "wx/mac/private.h"
class wxTaskBarIconImpl
{
public:
wxTaskBarIconImpl(wxTaskBarIcon* parent);
virtual ~wxTaskBarIconImpl();
virtual bool IsIconInstalled() const = 0;
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip) = 0;
virtual bool RemoveIcon() = 0;
virtual bool PopupMenu(wxMenu *menu) = 0;
wxMenu * CreatePopupMenu()
{ return m_parent->CreatePopupMenu(); }
wxTaskBarIcon *m_parent;
class wxTaskBarIconWindow *m_menuEventWindow;
DECLARE_NO_COPY_CLASS(wxTaskBarIconImpl)
};
//-----------------------------------------------------------------------------
//
// wxTaskBarIconWindow
//
// Event handler for menus
// NB: Since wxWindows in Mac HAVE to have parents we need this to be
// a top level window...
//-----------------------------------------------------------------------------
class wxTaskBarIconWindow : public wxTopLevelWindow
{
public:
wxTaskBarIconWindow(wxTaskBarIconImpl *impl)
: wxTopLevelWindow(NULL, wxID_ANY, wxEmptyString), m_impl(impl)
{
Connect(
-1, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(wxTaskBarIconWindow::OnMenuEvent) );
}
void OnMenuEvent(wxCommandEvent& event)
{
m_impl->m_parent->ProcessEvent(event);
}
private:
wxTaskBarIconImpl *m_impl;
};
class wxDockTaskBarIcon : public wxTaskBarIconImpl
{
public:
wxDockTaskBarIcon(wxTaskBarIcon* parent);
virtual ~wxDockTaskBarIcon();
virtual bool IsIconInstalled() const;
virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip);
virtual bool RemoveIcon();
virtual bool PopupMenu(wxMenu *menu);
wxMenu* DoCreatePopupMenu();
EventHandlerRef m_eventHandlerRef;
EventHandlerUPP m_eventupp;
wxWindow *m_eventWindow;
wxMenu *m_pMenu;
MenuRef m_theLastMenu;
bool m_iconAdded;
};
// Forward declarations for utility functions for dock implementation
pascal OSStatus wxDockEventHandler(
EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData );
wxMenu * wxDeepCopyMenu( wxMenu *menu );
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxTaskBarIconImpl
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wxTaskBarIconImpl::wxTaskBarIconImpl(wxTaskBarIcon* parent)
: m_parent(parent), m_menuEventWindow(new wxTaskBarIconWindow(this))
{
}
wxTaskBarIconImpl::~wxTaskBarIconImpl()
{
delete m_menuEventWindow;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxDockTaskBarIcon
//
// OS X Dock implementation of wxTaskBarIcon using Carbon
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//-----------------------------------------------------------------------------
// wxDockEventHandler
//
// This is the global Mac/Carbon event handler for the dock.
// We need this for two reasons:
// 1) To handle wxTaskBarIcon menu events (see below for why)
// 2) To handle events from the dock when it requests a menu
//-----------------------------------------------------------------------------
pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void *pData )
{
// Get the parameters we want from the event
wxDockTaskBarIcon* pTB = (wxDockTaskBarIcon*) pData;
const UInt32 eventClass = GetEventClass(inEvent);
const UInt32 eventKind = GetEventKind(inEvent);
// Handle wxTaskBar menu events (note that this is a global event handler
// so it will actually get called by all commands/menus)
if ((eventClass == kEventClassCommand) && (eventKind == kEventCommandProcess))
{
// if we have no taskbar menu quickly pass it back to wxApp
if (pTB->m_pMenu == NULL)
return eventNotHandledErr;
// This is the real reason why we need this. Normally menus
// get handled in wxMacAppEventHandler
//
// pascal OSStatus wxMacAppEventHandler(EventHandlerCallRef handler,
// EventRef event, void *data)
//
// However, in the case of a taskbar menu call
// command.menu.menuRef IS NULL!
// Which causes the wxApp handler just to skip it.
MenuRef taskbarMenuRef = MAC_WXHMENU(pTB->m_pMenu->GetHMenu());
OSStatus err;
// get the HICommand from the event
HICommand command;
err = GetEventParameter(
inEvent, kEventParamDirectObject,
typeHICommand, NULL,
sizeof(HICommand), NULL, &command );
if (err == noErr)
{
// Obtain the REAL menuRef and the menuItemIndex in the real menuRef
//
// NOTE: menuRef is generally used here for submenus, as
// GetMenuItemRefCon could give an incorrect wxMenuItem if we pass
// just the top level wxTaskBar menu
MenuItemIndex menuItemIndex;
MenuRef menuRef;
err = GetIndMenuItemWithCommandID(
taskbarMenuRef,
command.commandID,
1, &menuRef, &menuItemIndex );
if (err == noErr)
{
MenuCommand id = command.commandID;
wxMenuItem *item = NULL;
if (id != 0) // get the wxMenuItem reference from the MenuRef
GetMenuItemRefCon( menuRef, menuItemIndex, (UInt32*) &item );
if (item)
{
// Handle items that are checkable
// FIXME: Doesn't work (at least on 10.2)!
if (item->IsCheckable())
item->Check( !item->IsChecked() );
// send the wxEvent to the wxMenu
item->GetMenu()->SendEvent( id, item->IsCheckable() ? item->IsChecked() : -1 );
// successfully handled the event
err = noErr;
}
}
} //end if noErr on getting HICommand from event
// return whether we handled the event or not
return err;
}
// We better have a kEventClassApplication/kEventAppGetDockTileMenu combo here,
// otherwise something is truly funky
wxASSERT(eventClass == kEventClassApplication &&
eventKind == kEventAppGetDockTileMenu);
// process the right click events
// NB: This may result in double or even triple-creation of the menus
// We need to do this for 2.4 compat, however
wxTaskBarIconEvent downevt(wxEVT_TASKBAR_RIGHT_DOWN, NULL);
pTB->m_parent->ProcessEvent(downevt);
wxTaskBarIconEvent upevt(wxEVT_TASKBAR_RIGHT_UP, NULL);
pTB->m_parent->ProcessEvent(upevt);
// create popup menu
wxMenu* menu = pTB->DoCreatePopupMenu();
OSStatus err = eventNotHandledErr;
if (menu != NULL)
{
// note to self - a MenuRef *is* a MenuHandle
MenuRef hMenu = MAC_WXHMENU(menu->GetHMenu());
// When SetEventParameter is called it will decrement
// the reference count of the menu - we need to make
// sure it stays around in the wxMenu class here
RetainMenu(hMenu);
// set the actual dock menu
err = SetEventParameter(
inEvent, kEventParamMenuRef,
typeMenuRef, sizeof(MenuRef), &hMenu );
verify_noerr( err );
}
return err;
}
//-----------------------------------------------------------------------------
// wxDeepCopyMenu
//
// Performs a top-to-bottom copy of the input menu and all of its
// submenus.
//
// This is mostly needed for 2.4 compatability. However wxPython and others
// still use this way of setting the taskbarmenu.
//-----------------------------------------------------------------------------
wxMenu * wxDeepCopyMenu( wxMenu *menu )
{
if (menu == NULL)
return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -