I've created some "stub component", that emulates a menubar, independent from wxFrame. It's my attempt to create a dockable menubar using wxDockIt library, but actually this "component" is independent from this lib. You are all welcome to extend/correct this code, it's my first try to write a wxWidgets component, so please don't be strict to me.
It contains two parts - a wxMenuToolButton class (responsible for showing and hiding the menu) and wxMenuToolBar class (responsible for control an array of wxMenuToolButtons).
menutoolbutton.h
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Name: menutoolbutton.h //
// Purpose: wxMenuToolButton class, shows related wxPopupMenu by clicking //
// Author: Andreas Kaiser, based on pieces of code from mmWX //
// and wxDockIt libraries //
// Modified by: //
// Created: 04/01/05 //
// RCS-ID: //
// Copyright: //
// Licence: wxWindows licence //
////////////////////////////////////////////////////////////////////////////////
#ifndef WX_MENUTOOLBUTTON_H
#define WX_MENUTOOLBUTTON_H
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include <wx/control.h>
#include <wx/dcclient.h>
#include <wx/settings.h>
#include <wx/menu.h>
// ----------------------------------------------------------------------------
// wxMenuToolButton
// ----------------------------------------------------------------------------
class wxMenuToolButton: public wxControl
{
DECLARE_EVENT_TABLE()
public:
// Default constructor
wxMenuToolButton() {
Init();
}
void Init();
// Normal constructor
wxMenuToolButton( wxWindow *parent,
wxWindowID id,
wxString caption,
wxMenu* pMenu = NULL,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxBORDER_NONE,
const wxString& name = wxT("") ) {
Init();
Create( parent, id, pos, size, style, name );
m_menu = pMenu;
SetCaption(caption);
}
bool Create( wxWindow *parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxBORDER_NONE,
const wxString& name = wxT("") );
virtual ~wxMenuToolButton();
void AttachMenu(wxMenu* pMenu);
wxString GetCaption() const {return m_caption;}
void SetCaption(wxString caption);
protected:
void FindBestSize();
void OnErase(wxEraseEvent& event);
void OnPaint(wxPaintEvent& event);
void OnMouse(wxMouseEvent& event);
bool m_pressed;
bool m_hovered;
bool m_menuisopen;
wxString m_caption;
wxMenu* m_menu;
private:
int wholeMargin;
wxPoint captionpos;
DECLARE_DYNAMIC_CLASS( wxMenuToolButton )
};
#endif
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Name: wxMenuToolButton.cpp //
// Purpose: wxMenuToolButton implementation. //
// Author: Andreas Kaiser, based on pieces of code from mmWX //
// and wxDockIt libraries //
// Modified by: //
// Created: 01/04/05 //
// RCS-ID: //
// Copyright: //
// Licence: wxWindows license //
////////////////////////////////////////////////////////////////////////////////
#include "menutoolbutton.h"
// ----------------------------------------------------------------------------
// wxMenuToolButton implementation
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxMenuToolButton, wxControl)
BEGIN_EVENT_TABLE( wxMenuToolButton, wxControl )
EVT_ERASE_BACKGROUND( wxMenuToolButton::OnErase )
EVT_PAINT( wxMenuToolButton::OnPaint )
EVT_MOUSE_EVENTS( wxMenuToolButton::OnMouse)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
bool wxMenuToolButton::Create( wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name ) {
// create the controls
if( !wxControl::Create( parent, id, pos, size, style, wxDefaultValidator, name ) ) {
return false;
}
SetSizeHints(size);
SetBackgroundColour(parent->GetBackgroundColour());
return true;
}
wxMenuToolButton::~wxMenuToolButton()
{
}
void wxMenuToolButton::Init() {
// init.
wholeMargin = 0;
m_pressed = false;
m_hovered = false;
m_menuisopen = false;
m_menu = NULL;
m_caption = "";
captionpos = wxDefaultPosition;
}
void wxMenuToolButton::AttachMenu(wxMenu* pMenu)
{
m_menu = pMenu;
}
void wxMenuToolButton::FindBestSize()
{
wxRect cr = GetClientRect();
int labw=0,labh=0,ext=0;
if (m_caption != "")
GetTextExtent(m_caption,&labw,&labh,&ext);
labh += ext;
cr.width = wxMax(cr.width,labw);
cr.height = labh;
cr.width += 10;
cr.height += 4;
captionpos.x = cr.x + 5;
captionpos.y = cr.y + 2;
((wxWindow*)this)->SetSize(cr.width, cr.height);
((wxWindow*)this)->SetAutoLayout(true);
((wxWindow*)this)->Layout();
}
void wxMenuToolButton::SetCaption(wxString caption)
{
m_caption = caption;
FindBestSize();
}
void wxMenuToolButton::OnErase( wxEraseEvent& event ) {
// skip erase
}
void wxMenuToolButton::OnPaint( wxPaintEvent& event ) {
wxPaintDC dc(this);
wxRect cr = GetClientRect();
dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(),wxSOLID));
dc.Clear();
if(m_hovered || m_pressed){
wxColour raisedColour = wxSystemSettings::GetColour( m_pressed ? wxSYS_COLOUR_3DDKSHADOW : wxSYS_COLOUR_3DHIGHLIGHT );
wxPen raisedPen( raisedColour, 1, 1 );
wxColour shadowColour = wxSystemSettings::GetColour( m_pressed ? wxSYS_COLOUR_3DHIGHLIGHT : wxSYS_COLOUR_3DDKSHADOW );
wxPen shadowPen( shadowColour, 1, 1 );
cr.width--;
cr.height--;
cr.Deflate( wholeMargin, wholeMargin ) ;
// draw top-left
dc.SetPen( raisedPen );
dc.DrawLine( cr.x, cr.y, cr.width, cr.y );
dc.DrawLine( cr.x, cr.y, cr.x, cr.height );
// draw bottom-right
dc.SetPen( shadowPen );
dc.DrawLine( cr.width, cr.y, cr.width, cr.height+1 );
dc.DrawLine( cr.x, cr.height, cr.width+1, cr.height );
}
if( m_hovered & m_pressed ) cr.Offset( 1, 1 );
if(m_caption != ""){
dc.SetFont(GetFont());
if(m_pressed){
captionpos.x++;
captionpos.y++;
}
if (IsEnabled())
{
dc.SetTextForeground(GetForegroundColour());
dc.DrawText(m_caption, captionpos.x, captionpos.y);
}
else
{
dc.SetTextForeground(*wxWHITE);
dc.DrawText(m_caption, captionpos.x+1, captionpos.y+1);
dc.SetTextForeground(wxColour(100,100,100));
dc.DrawText(m_caption, captionpos.x, captionpos.y);
dc.SetTextForeground(*wxBLACK);
}
if(m_pressed){
captionpos.x--;
captionpos.y--;
}
}
}
void wxMenuToolButton::OnMouse(wxMouseEvent& event)
{
bool insideofme = GetClientRect().Inside(event.GetPosition().x, event.GetPosition().y);
if(event.Entering()){
m_hovered = true;
m_pressed = false;
Refresh();
}
else if (event.Leaving()){
m_hovered = false;
if (HasCapture()) ReleaseMouse();
Refresh();
}
else{
if (event.LeftDown() || event.LeftDClick()){
m_pressed = insideofme;
m_hovered = false;
Refresh();
}
if(m_pressed && !m_menuisopen){
if((m_menu) && (m_menu->GetMenuItemCount()>0)){
PopupMenu(m_menu, 0, GetClientSize().y);
m_menuisopen = true;
CaptureMouse();
Refresh();
}
else{
m_pressed = false;
m_hovered = false;
Refresh();
}
}
else
if (HasCapture()) {
m_menuisopen = false;
m_hovered = false;
m_pressed = false;
Refresh();
ReleaseMouse();
}
}
event.Skip();
}
menutoolbar.h
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Name: menutoolbar.h //
// Purpose: wxMenuToolBar class, manages array of wxMenuToolButtons //
// Author: Andreas Kaiser, based on pieces of code from mmWX //
// and wxDockIt libraries //
// Modified by: //
// Created: 04/01/05 //
// RCS-ID: //
// Copyright: //
// Licence: wxWindows licence //
////////////////////////////////////////////////////////////////////////////////
#ifndef WX_MENUTOOLBAR_H
#define WX_MENUTOOLBAR_H
#include <wx/control.h>
#include <wx/settings.h>
#include "menutoolbutton.h"
WX_DECLARE_LIST(wxMenuToolButton, MenuBarButtons);
// ----------------------------------------------------------------------------
// wxMenuToolBar
// ----------------------------------------------------------------------------
class wxMenuToolBar: public wxControl
{
DECLARE_EVENT_TABLE()
public:
// Default constructor
wxMenuToolBar() {
Init();
}
void Init();
// Normal constructor
wxMenuToolBar( wxWindow *parent,
wxWindowID id,
wxString caption,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxNO_BORDER | wxWANTS_CHARS | wxCLIP_CHILDREN,
const wxString& name = wxT("menubar") ) {
Init();
Create( parent, id, pos, size, style, name );
SetCaption(caption);
}
bool Create( wxWindow *parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxBORDER_NONE,
const wxString& name = wxT("") );
virtual ~wxMenuToolBar();
wxString GetCaption() const {return m_caption;}
void SetCaption(wxString caption) { m_caption = caption;}
void AddMenu(wxWindowID id, wxMenu* pMenu, wxString caption);
void InsertMenu(wxWindowID id, wxMenu* pMenu, wxString caption, size_t pos);
void RemoveMenu(size_t pos);
void Enable(wxWindowID id, bool enable = true);
protected:
void FindBestSize();
void OnKey(wxKeyEvent& event);
void OnMouse(wxMouseEvent& event);
wxString m_caption;
private:
MenuBarButtons buttons;
DECLARE_DYNAMIC_CLASS( wxMenuToolBar )
};
#endif
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Name: menutoolbar.h //
// Purpose: wxMenuToolBar class, holds an array of wxMenuToolButtons and //
// emulates a flat menu bar //
// Author: Andreas Kaiser, based on pieces of code from mmWX //
// and wxDockIt libraries //
// Modified by: //
// Created: 04/01/05 //
// RCS-ID: //
// Copyright: //
// Licence: wxWindows licence //
////////////////////////////////////////////////////////////////////////////////
#include <wx/list.h>
#include <wx/listimpl.cpp>
#include "menutoolbar.h"
// ----------------------------------------------------------------------------
// wxMenuToolBar implementation
// ----------------------------------------------------------------------------
WX_DEFINE_LIST(MenuBarButtons);
IMPLEMENT_DYNAMIC_CLASS(wxMenuToolBar, wxControl)
BEGIN_EVENT_TABLE( wxMenuToolBar, wxControl )
EVT_KEY_DOWN(wxMenuToolBar::OnKey)
EVT_CHAR(wxMenuToolBar::OnKey)
EVT_MOUSE_EVENTS( wxMenuToolBar::OnMouse)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
bool wxMenuToolBar::Create( wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name ) {
// create the controls
if( !wxControl::Create( parent, id, pos, size, style, wxDefaultValidator, name ) ) {
return false;
}
buttons.Clear();
SetSizeHints(size);
SetBackgroundColour(parent->GetBackgroundColour());
return true;
}
wxMenuToolBar::~wxMenuToolBar()
{
}
void wxMenuToolBar::Init() {
m_caption = "";
}
void wxMenuToolBar::FindBestSize()
{
wxPoint lastpos(0,0);
wxSize btnsize;
for( MenuBarButtons::Node *node = buttons.GetFirst(); node; node = node->GetNext() )
{
wxMenuToolButton* pButton = node->GetData();
wxASSERT(pButton);
pButton->Move(lastpos);
btnsize = pButton->GetSize();
lastpos.x += btnsize.GetWidth();
}
SetSize(lastpos.x+2, btnsize.y);
}
void wxMenuToolBar::OnKey(wxKeyEvent& event)
{
event.Skip();
}
void wxMenuToolBar::OnMouse(wxMouseEvent& event)
{
event.Skip();
}
void wxMenuToolBar::AddMenu(wxWindowID id, wxMenu* pMenu, wxString caption)
{
wxMenuToolButton* onebtn = new wxMenuToolButton(this, id, caption, pMenu);
buttons.Append(onebtn);
FindBestSize();
}
void wxMenuToolBar::InsertMenu(wxWindowID id, wxMenu* pMenu, wxString caption, size_t pos)
{
wxMenuToolButton* onebtn = new wxMenuToolButton(this, id, caption, pMenu);
buttons.Insert(pos, onebtn);
FindBestSize();
}
void wxMenuToolBar::RemoveMenu(size_t pos)
{
if((buttons.GetCount() > 0) && (buttons.GetCount() > pos)){
buttons.DeleteNode(buttons.Item(pos));
FindBestSize();
}
}
void wxMenuToolBar::Enable(wxWindowID id, bool enable)
{
wxMenuToolButton* pButton = (wxMenuToolButton*)NULL;
for( MenuBarButtons::Node *node = buttons.GetFirst(); node; node = node->GetNext() )
{
pButton = node->GetData();
if((pButton) && (pButton->GetId() == id) && (pButton->IsEnabled() != enable)){
pButton->Enable(enable);
pButton->Refresh();
break;
}
}
}
Howe to use it:
Code: Select all
wxMenu* menu1 = new wxMenu;
wxMenu* menu2 = new wxMenu;
wxMenu* menu3 = new wxMenu;
//menu toolbar
wxMenuToolBar* menutb = new wxMenuToolBar(this, wxID_ANY, wxT("Main menu"));
//this - this is an object of type [wxWindow derived class, e.g. wxControl, wxPanel, wxFrame, wxMiniFrame ...]
m_menutb->AddMenu(ID_MENU1, menu1, wxT("Menu1"));
m_menutb->AddMenu(ID_MENU2, menu2, wxT("Menu2"));
m_menutb->AddMenu(ID_MENU3, menu3, wxT("Menu3"));