1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/msw/wince/tbarwce.cpp
3
// Purpose: wxToolBar for Windows CE
4
// Author: Julian Smart
7
// Copyright: (c) Julian Smart
8
// Licence: wxWindows licence
9
/////////////////////////////////////////////////////////////////////////////
11
// ============================================================================
13
// ============================================================================
15
// ----------------------------------------------------------------------------
17
// ----------------------------------------------------------------------------
19
// For compilers that support precompilation, includes "wx.h".
20
#include "wx/wxprec.h"
26
// Use the WinCE-specific toolbar only if we're either compiling
27
// with a WinCE earlier than 4, or we wish to emulate a PocketPC-style UI
28
#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE && (_WIN32_WCE < 400 || defined(__POCKETPC__) || defined(__SMARTPHONE__))
30
#include "wx/toolbar.h"
33
#include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
34
#include "wx/dynarray.h"
38
#include "wx/settings.h"
39
#include "wx/bitmap.h"
40
#include "wx/dcmemory.h"
41
#include "wx/control.h"
44
#if !defined(__GNUWIN32__)
48
#include "wx/msw/private.h"
54
#if defined(WINCE_WITHOUT_COMMANDBAR)
56
#include "wx/msw/wince/resources.h"
58
#include "wx/msw/wince/missing.h"
60
#include "wx/msw/winundef.h"
62
#if !defined(__SMARTPHONE__)
64
///////////// This implementation is for PocketPC.
65
///////////// See later for the Smartphone dummy toolbar class.
67
// ----------------------------------------------------------------------------
69
// ----------------------------------------------------------------------------
71
IMPLEMENT_DYNAMIC_CLASS(wxToolMenuBar, wxToolBar)
73
BEGIN_EVENT_TABLE(wxToolMenuBar, wxToolBar)
76
// ----------------------------------------------------------------------------
78
// ----------------------------------------------------------------------------
80
class wxToolMenuBarTool : public wxToolBarToolBase
83
wxToolMenuBarTool(wxToolBar *tbar,
85
const wxString& label,
86
const wxBitmap& bmpNormal,
87
const wxBitmap& bmpDisabled,
90
const wxString& shortHelp,
91
const wxString& longHelp)
92
: wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
93
clientData, shortHelp, longHelp)
99
wxToolMenuBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
100
: wxToolBarToolBase(tbar, control, label)
106
virtual void SetLabel(const wxString& label)
108
if ( label == m_label )
111
wxToolBarToolBase::SetLabel(label);
113
// we need to update the label shown in the toolbar because it has a
114
// pointer to the internal buffer of the old label
116
// TODO: use TB_SETBUTTONINFO
119
// set/get the number of separators which we use to cover the space used by
120
// a control in the toolbar
121
void SetSeparatorsCount(size_t count) { m_nSepCount = count; }
122
size_t GetSeparatorsCount() const { return m_nSepCount; }
124
void SetBitmapIndex(int idx) { m_bitmapIndex = idx; }
125
int GetBitmapIndex() const { return m_bitmapIndex; }
133
// ============================================================================
135
// ============================================================================
137
// ----------------------------------------------------------------------------
139
// ----------------------------------------------------------------------------
141
wxToolBarToolBase *wxToolMenuBar::CreateTool(int id,
142
const wxString& label,
143
const wxBitmap& bmpNormal,
144
const wxBitmap& bmpDisabled,
146
wxObject *clientData,
147
const wxString& shortHelp,
148
const wxString& longHelp)
150
return new wxToolMenuBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
151
clientData, shortHelp, longHelp);
155
wxToolMenuBar::CreateTool(wxControl *control, const wxString& label)
157
return new wxToolMenuBarTool(this, control, label);
160
// ----------------------------------------------------------------------------
161
// wxToolBar construction
162
// ----------------------------------------------------------------------------
164
void wxToolMenuBar::Init()
172
bool wxToolMenuBar::Create(wxWindow *parent,
177
const wxString& name,
180
// common initialisation
181
if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) )
184
// MSW-specific initialisation
185
if ( !MSWCreateToolbar(pos, size, menuBar) )
188
// set up the colors and fonts
189
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
190
SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
195
bool wxToolMenuBar::MSWCreateToolbar(const wxPoint& WXUNUSED(pos),
196
const wxSize& WXUNUSED(size),
201
m_menuBar->SetToolBar(this);
203
HWND hwndParent = GetHwndOf(GetParent());
204
wxCHECK_MSG( hwndParent, false, wxT("should have valid parent HWND") );
206
#if defined(WINCE_WITHOUT_COMMANDBAR)
207
// create the menubar.
208
WinStruct<SHMENUBARINFO> mbi;
210
mbi.hwndParent = hwndParent;
211
mbi.nToolBarId = wxIDM_SHMENU;
212
mbi.hInstRes = wxGetInstance();
214
if ( !SHCreateMenuBar(&mbi) )
216
wxFAIL_MSG( wxT("SHCreateMenuBar failed") );
220
SetHWND((WXHWND) mbi.hwndMB);
222
HWND hWnd = CommandBar_Create(wxGetInstance(), hwndParent, GetId());
223
SetHWND((WXHWND) hWnd);
226
// install wxWidgets window proc for this window
235
void wxToolMenuBar::Recreate()
240
wxToolMenuBar::~wxToolMenuBar()
243
GetMenuBar()->SetToolBar(NULL);
246
// Return HMENU for the menu associated with the commandbar
247
WXHMENU wxToolMenuBar::GetHMenu()
249
#if !defined(__HANDHELDPC__)
252
return (WXHMENU)::SendMessage(GetHwnd(), SHCMBM_GETMENU, 0, 0);
259
// ----------------------------------------------------------------------------
260
// adding/removing tools
261
// ----------------------------------------------------------------------------
263
bool wxToolMenuBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
265
// nothing special to do here - we really create the toolbar buttons in
272
bool wxToolMenuBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
274
// Skip over the menus
276
pos += GetMenuBar()->GetMenuCount();
278
// the main difficulty we have here is with the controls in the toolbars:
279
// as we (sometimes) use several separators to cover up the space used by
280
// them, the indices are not the same for us and the toolbar
282
// first determine the position of the first button to delete: it may be
283
// different from pos if we use several separators to cover the space used
285
wxToolBarToolsList::compatibility_iterator node;
286
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
288
wxToolBarToolBase *tool2 = node->GetData();
291
// let node point to the next node in the list
292
node = node->GetNext();
297
if ( tool2->IsControl() )
299
pos += ((wxToolMenuBarTool *)tool2)->GetSeparatorsCount() - 1;
303
// now determine the number of buttons to delete and the area taken by them
304
size_t nButtonsToDelete = 1;
306
// get the size of the button we're going to delete
308
if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) )
310
wxLogLastError(wxT("TB_GETITEMRECT"));
313
int width = r.right - r.left;
315
if ( tool->IsControl() )
317
nButtonsToDelete = ((wxToolMenuBarTool *)tool)->GetSeparatorsCount();
319
width *= nButtonsToDelete;
322
// do delete all buttons
323
m_nButtons -= nButtonsToDelete;
324
while ( nButtonsToDelete-- > 0 )
326
if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) )
328
wxLogLastError(wxT("TB_DELETEBUTTON"));
336
// and finally reposition all the controls after this button (the toolbar
337
// takes care of all normal items)
338
for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
340
wxToolBarToolBase *tool2 = node->GetData();
341
if ( tool2->IsControl() )
344
wxControl *control = tool2->GetControl();
345
control->GetPosition(&x, NULL);
346
control->Move(x - width, wxDefaultCoord);
353
bool wxToolMenuBar::Realize()
355
const size_t nTools = GetToolsCount();
363
// delete all old buttons, if any
364
for ( size_t pos = 0; pos < m_nButtons; pos++ )
366
if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) )
368
wxLogDebug(wxT("TB_DELETEBUTTON failed"));
373
bool lastWasRadio = false;
374
wxToolBarToolsList::compatibility_iterator node;
375
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
377
wxToolMenuBarTool *tool = (wxToolMenuBarTool*) node->GetData();
379
TBBUTTON buttons[1] ;
381
TBBUTTON& button = buttons[0];
383
wxZeroMemory(button);
385
bool isRadio = false;
386
switch ( tool->GetStyle() )
388
case wxTOOL_STYLE_CONTROL:
389
button.idCommand = tool->GetId();
390
// fall through: create just a separator too
391
// TODO: controls are not yet supported on wxToolMenuBar.
393
case wxTOOL_STYLE_SEPARATOR:
394
button.fsState = TBSTATE_ENABLED;
395
button.fsStyle = TBSTYLE_SEP;
398
case wxTOOL_STYLE_BUTTON:
400
if ( HasFlag(wxTB_TEXT) )
402
const wxString& label = tool->GetLabel();
403
if ( !label.empty() )
405
button.iString = (int) wxMSW_CONV_LPCTSTR(label);
409
const wxBitmap& bmp = tool->GetNormalBitmap();
411
wxBitmap bmpToUse = bmp;
413
if (bmp.GetWidth() < 16 || bmp.GetHeight() < 16 || bmp.GetMask() != NULL)
417
memDC.SelectObject(b);
418
wxColour col = wxColour(192,192,192);
419
memDC.SetBackground(wxBrush(col));
421
int x = (16 - bmp.GetWidth())/2;
422
int y = (16 - bmp.GetHeight())/2;
423
memDC.DrawBitmap(bmp, x, y, true);
424
memDC.SelectObject(wxNullBitmap);
427
tool->SetNormalBitmap(b);
431
if ( bmpToUse.IsOk() )
433
n = ::CommandBar_AddBitmap( (HWND) GetHWND(), NULL, (int) (HBITMAP) bmpToUse.GetHBITMAP(),
437
button.idCommand = tool->GetId();
440
if ( tool->IsEnabled() )
441
button.fsState |= TBSTATE_ENABLED;
442
if ( tool->IsToggled() )
443
button.fsState |= TBSTATE_CHECKED;
445
switch ( tool->GetKind() )
448
button.fsStyle = TBSTYLE_CHECKGROUP;
452
// the first item in the radio group is checked by
453
// default to be consistent with wxGTK and the menu
455
button.fsState |= TBSTATE_CHECKED;
464
button.fsStyle = TBSTYLE_CHECK;
468
wxFAIL_MSG( wxT("unexpected toolbar button kind") );
472
button.fsStyle = TBSTYLE_BUTTON;
477
if ( !::CommandBar_AddButtons( (HWND) GetHWND(), 1, buttons ) )
479
wxFAIL_MSG( wxT("Could not add toolbar button."));
482
lastWasRadio = isRadio;
488
bool wxToolMenuBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id_)
490
const int id = (signed short)id_;
492
wxToolBarToolBase *tool = FindById(id);
495
bool checked = false;
498
wxMenuItem *item = m_menuBar->FindItem(id);
499
if ( item && item->IsCheckable() )
502
checked = item->IsChecked();
506
wxCommandEvent event(wxEVT_MENU);
507
event.SetEventObject(this);
509
event.SetInt(checked);
511
return GetEventHandler()->ProcessEvent(event);
514
if ( tool->CanBeToggled() )
516
LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0);
517
tool->Toggle((state & TBSTATE_CHECKED) != 0);
520
bool toggled = tool->IsToggled();
522
// avoid sending the event when a radio button is released, this is not
524
if ( !tool->CanBeToggled() || tool->GetKind() != wxITEM_RADIO || toggled )
526
// OnLeftClick() can veto the button state change - for buttons which
527
// may be toggled only, of course.
528
if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() )
532
tool->SetToggle(toggled);
534
::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(toggled, 0));
541
WXLRESULT wxToolMenuBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
549
// we don't handle mouse moves, so always pass the message to
550
// wxControl::MSWWindowProc
551
HandleMouseMove(wParam, lParam);
558
return MSWDefWindowProc(nMsg, wParam, lParam);
564
////////////// For Smartphone
566
// ----------------------------------------------------------------------------
568
// ----------------------------------------------------------------------------
570
IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
572
BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
575
wxToolBarToolBase *wxToolBar::CreateTool(int id,
576
const wxString& label,
577
const wxBitmap& bmpNormal,
578
const wxBitmap& bmpDisabled,
580
wxObject *clientData,
581
const wxString& shortHelp,
582
const wxString& longHelp)
584
return new wxToolBarToolBase(this, id, label, bmpNormal, bmpDisabled, kind,
585
clientData, shortHelp, longHelp);
588
wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
590
return new wxToolBarToolBase(this, control);
593
bool wxToolBar::Create(wxWindow *parent,
594
wxWindowID WXUNUSED(id),
595
const wxPoint& WXUNUSED(pos),
596
const wxSize& WXUNUSED(size),
598
const wxString& name)
600
// TODO: we may need to make this a dummy hidden window to
601
// satisfy other parts of wxWidgets.
603
parent->AddChild(this);
605
SetWindowStyle(style);
611
// ----------------------------------------------------------------------------
612
// adding/removing tools
613
// ----------------------------------------------------------------------------
615
bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
621
bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
627
wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y)) const
632
// ----------------------------------------------------------------------------
634
// ----------------------------------------------------------------------------
636
void wxToolBar::DoEnableTool(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(enable))
640
void wxToolBar::DoToggleTool(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
644
void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
646
wxFAIL_MSG( wxT("not implemented") );
652
#endif // wxUSE_TOOLBAR