From a9a0ceca5b549414a6119e98bc6d868c071a8b1b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 11 May 2007 23:35:49 +0000 Subject: [PATCH] added support for drop down toolbar buttons (patch 1713470) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45987 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/toolbar.tex | 29 +++++++++++++++++++++++++++++ include/wx/defs.h | 1 + include/wx/event.h | 4 ++++ include/wx/tbarbase.h | 17 +++++++++++++++-- samples/toolbar/toolbar.cpp | 22 +++++++++++++++++++++- src/common/event.cpp | 1 + src/common/tbarbase.cpp | 28 +++++++++++++++++++++++++++- src/msw/tbar95.cpp | 36 +++++++++++++++++++++++++++++++++++- 8 files changed, 133 insertions(+), 5 deletions(-) diff --git a/docs/latex/wx/toolbar.tex b/docs/latex/wx/toolbar.tex index 8907395080..9d34c8d5f1 100644 --- a/docs/latex/wx/toolbar.tex +++ b/docs/latex/wx/toolbar.tex @@ -104,6 +104,24 @@ Pass the id of the tool.} for a range of ids. Pass the ids of the tools.} \twocolitem{{\bf EVT\_TOOL\_ENTER(id, func)}}{Process a wxEVT\_COMMAND\_TOOL\_ENTER event. Pass the id of the toolbar itself. The value of wxCommandEvent::GetSelection is the tool id, or -1 if the mouse cursor has moved off a tool.} +\twocolitem{{\bf EVT\_TOOL\_DROPDOWN(id, func)}}{Process a wxEVT\_COMMAND\_TOOL\_DROPDOWN\_CLICKED event. If unhandled, displays the default dropdown menu set using \helpref{wxToolBar::SetDropdownMenu}{wxtoolbarsetdropdownmenu}.} +\end{twocollist} + +\wxheading{wxItemKind} + +There are several different types of tools you can add to a toolbar. These +types are controlled by the wxItemKind enumeration which has the following +values: +\twocolwidtha{5cm} +\begin{twocollist}\itemsep=0pt +\twocolitem{{\bf wxITEM\_NORMAL}}{Normal tool button} +\twocolitem{{\bf wxITEM\_CHECK}}{Check (or toggle) tool button.} +\twocolitem{{\bf wxITEM\_NORMAL}}{Radio tool button. See \helpref{wxToolBar::AddRadioTool}{wxtoolbaraddradiotool} for details} +\twocolitem{{\bf wxITEM\_DROPDOWN}}{Normal tool button with a dropdown arrow +next to it. Clicking the dropdown arrow sends a wxEVT\_COMMAND\_TOOL\_DROPDOWN\_CLICKED +event and may also display the menu previously associated with the item with +\helpref{wxToolBar::SetDropdownMenu}{wxtoolbarsetdropdownmenu}. Currently this +type of tools is only supported under MSW.} \end{twocollist} \wxheading{See also} @@ -738,6 +756,17 @@ default (zero-size) margins are to be overridden. \helpref{wxToolBar::GetMargins}{wxtoolbargetmargins}, \helpref{wxSize}{wxsize} +\membersection{wxToolBar::SetDropdownMenu}\label{wxtoolbarsetdropdownmenu} + +\func{bool}{SetDropdownMenu}{\param{int }{id}, \param{wxMenu* }{menu}} + +Sets the dropdown menu for the tool given by its \arg{id}. The tool itself will +delete the menu when it's no longer needed. + +If you define a EVT\_TOOL\_DROPDOWN handler in your program, you must call +\helpref{wxEvent::Skip()}{wxeventskip} from it or the menu won't be displayed. + + \membersection{wxToolBar::SetToolBitmapSize}\label{wxtoolbarsettoolbitmapsize} \func{void}{SetToolBitmapSize}{\param{const wxSize\&}{ size}} diff --git a/include/wx/defs.h b/include/wx/defs.h index 17f206fc89..d5fc6c3c56 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -1862,6 +1862,7 @@ enum wxItemKind wxITEM_NORMAL, wxITEM_CHECK, wxITEM_RADIO, + wxITEM_DROPDOWN, wxITEM_MAX }; diff --git a/include/wx/event.h b/include/wx/event.h index 3a9feb32c6..dc932bc91d 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -155,6 +155,9 @@ BEGIN_DECLARE_EVENT_TYPES() DECLARE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER, 17) DECLARE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED, 18) + // Toolbar dropdown arrows + DECLARE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, 19) + // Sockets and timers send events, too DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEVT_SOCKET, 50) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEVT_TIMER , 80) @@ -2988,6 +2991,7 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent& #define EVT_VLBOX(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_VLBOX_SELECTED, winid, wxCommandEventHandler(func)) #define EVT_COMBOBOX(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_COMBOBOX_SELECTED, winid, wxCommandEventHandler(func)) #define EVT_TOOL(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TOOL_CLICKED, winid, wxCommandEventHandler(func)) +#define EVT_TOOL_DROPDOWN(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, winid, wxCommandEventHandler(func)) #define EVT_TOOL_RANGE(id1, id2, func) wx__DECLARE_EVT2(wxEVT_COMMAND_TOOL_CLICKED, id1, id2, wxCommandEventHandler(func)) #define EVT_TOOL_RCLICKED(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TOOL_RCLICKED, winid, wxCommandEventHandler(func)) #define EVT_TOOL_RCLICKED_RANGE(id1, id2, func) wx__DECLARE_EVT2(wxEVT_COMMAND_TOOL_RCLICKED, id1, id2, wxCommandEventHandler(func)) diff --git a/include/wx/tbarbase.h b/include/wx/tbarbase.h index fb221036f6..96920150b9 100644 --- a/include/wx/tbarbase.h +++ b/include/wx/tbarbase.h @@ -71,7 +71,8 @@ public: const wxString& longHelpString = wxEmptyString) : m_label(label), m_shortHelpString(shortHelpString), - m_longHelpString(longHelpString) + m_longHelpString(longHelpString), + m_dropdownMenu(NULL) { m_tbar = tbar; m_id = toolid; @@ -106,9 +107,11 @@ public: m_toggled = false; m_toolStyle = wxTOOL_STYLE_CONTROL; + + m_dropdownMenu = 0; } - virtual ~wxToolBarToolBase(){} + virtual ~wxToolBarToolBase(); // accessors // --------- @@ -197,6 +200,11 @@ public: virtual void Detach() { m_tbar = (wxToolBarBase *)NULL; } virtual void Attach(wxToolBarBase *tbar) { m_tbar = tbar; } + // these methods are only for tools of wxITEM_DROPDOWN kind (but even such + // tools can have a NULL associated menu) + void SetDropdownMenu(wxMenu *menu); + wxMenu *GetDropdownMenu() const { return m_dropdownMenu; } + protected: wxToolBarBase *m_tbar; // the toolbar to which we belong (may be NULL) @@ -227,6 +235,8 @@ protected: wxString m_shortHelpString; wxString m_longHelpString; + wxMenu *m_dropdownMenu; + DECLARE_DYNAMIC_CLASS_NO_COPY(wxToolBarToolBase) }; @@ -525,6 +535,9 @@ public: // don't want toolbars to accept the focus virtual bool AcceptsFocus() const { return false; } + // Set dropdown menu + bool SetDropdownMenu(int toolid, wxMenu *menu); + protected: // to implement in derived classes // ------------------------------- diff --git a/samples/toolbar/toolbar.cpp b/samples/toolbar/toolbar.cpp index 99bd1fe665..4a98612c16 100644 --- a/samples/toolbar/toolbar.cpp +++ b/samples/toolbar/toolbar.cpp @@ -125,6 +125,7 @@ public: void OnToolLeftClick(wxCommandEvent& event); void OnToolRightClick(wxCommandEvent& event); + void OnToolDropdown(wxCommandEvent& event); void OnCombo(wxCommandEvent& event); @@ -245,6 +246,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_TOOL_RCLICKED(wxID_ANY, MyFrame::OnToolRightClick) + EVT_TOOL_DROPDOWN(wxID_ANY, MyFrame::OnToolDropdown) + EVT_UPDATE_UI(wxID_COPY, MyFrame::OnUpdateCopyAndCut) EVT_UPDATE_UI(wxID_CUT, MyFrame::OnUpdateCopyAndCut) @@ -385,8 +388,16 @@ void MyFrame::RecreateToolbar() toolBar->SetToolBitmapSize(wxSize(w, h)); toolBar->AddTool(wxID_NEW, _T("New"), - toolBarBitmaps[Tool_new], wxNullBitmap, wxITEM_NORMAL, + toolBarBitmaps[Tool_new], wxNullBitmap, wxITEM_DROPDOWN, _T("New file"), _T("This is help for new file tool")); + + wxMenu* menu = new wxMenu; + menu->Append(wxID_ANY, _T("&First dummy item")); + menu->Append(wxID_ANY, _T("&Second dummy item")); + menu->AppendSeparator(); + menu->Append(wxID_EXIT, _T("Exit")); + toolBar->SetDropdownMenu(wxID_NEW, menu); + toolBar->AddTool(wxID_OPEN, _T("Open"), toolBarBitmaps[Tool_open], wxNullBitmap, wxITEM_NORMAL, _T("Open file"), _T("This is help for open file tool")); @@ -868,3 +879,12 @@ void MyFrame::OnToggleRadioBtn(wxCommandEvent& event) event.GetId() - IDM_TOOLBAR_TOGGLERADIOBTN1, true); } } + +void MyFrame::OnToolDropdown(wxCommandEvent& event) +{ + wxString str; + str.Printf( _T("Dropdown on tool %d\n"), event.GetId()); + m_textWindow->WriteText( str ); + + event.Skip(); +} diff --git a/src/common/event.cpp b/src/common/event.cpp index e04611b837..3acfaa7efd 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -173,6 +173,7 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_COMBOBOX_SELECTED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER) DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED) // Mouse event types DEFINE_EVENT_TYPE(wxEVT_LEFT_DOWN) diff --git a/src/common/tbarbase.cpp b/src/common/tbarbase.cpp index 1e427b825f..071dac26d3 100644 --- a/src/common/tbarbase.cpp +++ b/src/common/tbarbase.cpp @@ -35,6 +35,7 @@ #if WXWIN_COMPATIBILITY_2_8 #include "wx/image.h" #endif // WXWIN_COMPATIBILITY_2_8 + #include "wx/menu.h" #endif // ---------------------------------------------------------------------------- @@ -58,6 +59,12 @@ WX_DEFINE_LIST(wxToolBarToolsList) IMPLEMENT_DYNAMIC_CLASS(wxToolBarToolBase, wxObject) +wxToolBarToolBase::~wxToolBarToolBase() +{ + delete m_dropdownMenu; +} + + bool wxToolBarToolBase::Enable(bool enable) { if ( m_enabled == enable ) @@ -111,6 +118,13 @@ bool wxToolBarToolBase::SetLongHelp(const wxString& help) return true; } + +void wxToolBarToolBase::SetDropdownMenu(wxMenu* menu) +{ + delete m_dropdownMenu; + m_dropdownMenu = menu; +} + // ---------------------------------------------------------------------------- // wxToolBarBase adding/deleting items // ---------------------------------------------------------------------------- @@ -690,6 +704,19 @@ void wxToolBarBase::UpdateWindowUI(long flags) } } +bool wxToolBarBase::SetDropdownMenu(int toolid, wxMenu* menu) +{ + wxToolBarToolBase * const tool = FindById(toolid); + wxCHECK_MSG( tool, false, _T("invalid tool id") ); + + wxCHECK_MSG( tool->GetKind() == wxITEM_DROPDOWN, false, + _T("menu can be only associated with drop down tools") ); + + tool->SetDropdownMenu(menu); + + return true; +} + #if WXWIN_COMPATIBILITY_2_8 bool wxCreateGreyedImage(const wxImage& in, wxImage& out) @@ -699,7 +726,6 @@ bool wxCreateGreyedImage(const wxImage& in, wxImage& out) if ( out.Ok() ) return true; #endif // wxUSE_IMAGE - return false; } diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index f2c24ec171..cb2c515656 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -303,6 +303,9 @@ bool wxToolBar::MSWCreateToolbar(const wxPoint& pos, const wxSize& size) // toolbar-specific post initialisation ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + if ( wxApp::GetComCtl32Version() >= 471 ) + ::SendMessage(GetHwnd(), TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS); + return true; } @@ -958,6 +961,10 @@ bool wxToolBar::Realize() button.fsStyle = TBSTYLE_BUTTON; break; + case wxITEM_DROPDOWN: + button.fsStyle = TBSTYLE_DROPDOWN; + break; + default: wxFAIL_MSG( _T("unexpected toolbar button kind") ); button.fsStyle = TBSTYLE_BUTTON; @@ -1200,11 +1207,38 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *WXUNUSED(result)) { + LPNMHDR hdr = (LPNMHDR)lParam; + if ( hdr->code == TBN_DROPDOWN ) + { + LPNMTOOLBAR tbhdr = (LPNMTOOLBAR)lParam; + + wxCommandEvent evt(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, tbhdr->iItem); + if ( GetEventHandler()->ProcessEvent(evt) ) + { + // Event got handled, don't display default popup menu + return false; + } + + const wxToolBarToolBase * const tool = FindById(tbhdr->iItem); + wxCHECK_MSG( tool, false, _T("drop down message for unknown tool") ); + + wxMenu * const menu = tool->GetDropdownMenu(); + if ( !menu ) + return false; + + // Display popup menu below button + RECT r; + if (::SendMessage(GetHwnd(), TB_GETITEMRECT, GetToolPos(tbhdr->iItem), (LPARAM)&r)) + PopupMenu(menu, r.left, r.bottom); + + return true; + } + + if( !HasFlag(wxTB_NO_TOOLTIPS) ) { #if wxUSE_TOOLTIPS // First check if this applies to us - NMHDR *hdr = (NMHDR *)lParam; // the tooltips control created by the toolbar is sometimes Unicode, even // in an ANSI application - this seems to be a bug in comctl32.dll v5 -- 2.45.2