1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/wince/tbarwce.cpp
3 // Purpose: wxToolBar for Windows CE
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "tbarwce.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
35 #include "wx/dynarray.h"
36 #include "wx/settings.h"
37 #include "wx/bitmap.h"
38 #include "wx/dcmemory.h"
39 #include "wx/control.h"
42 // Use the WinCE-specific toolbar only if we're either compiling
43 // with a WinCE earlier than 4, or we wish to emulate a PocketPC-style UI
44 #if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE && (_WIN32_WCE < 400 || defined(__POCKETPC__) || defined(__SMARTPHONE__))
46 #include "wx/toolbar.h"
48 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
52 #include "wx/msw/private.h"
59 #if defined(WINCE_WITHOUT_COMMANDBAR)
62 #include "wx/msw/wince/missing.h"
64 #include "wx/msw/winundef.h"
66 #if !defined(__SMARTPHONE__)
68 ///////////// This implementation is for PocketPC.
69 ///////////// See later for the Smartphone dummy toolbar class.
71 // ----------------------------------------------------------------------------
73 // ----------------------------------------------------------------------------
75 IMPLEMENT_DYNAMIC_CLASS(wxToolMenuBar
, wxToolBar
)
77 BEGIN_EVENT_TABLE(wxToolMenuBar
, wxToolBar
)
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
84 class wxToolMenuBarTool
: public wxToolBarToolBase
87 wxToolMenuBarTool(wxToolBar
*tbar
,
89 const wxString
& label
,
90 const wxBitmap
& bmpNormal
,
91 const wxBitmap
& bmpDisabled
,
94 const wxString
& shortHelp
,
95 const wxString
& longHelp
)
96 : wxToolBarToolBase(tbar
, id
, label
, bmpNormal
, bmpDisabled
, kind
,
97 clientData
, shortHelp
, longHelp
)
103 wxToolMenuBarTool(wxToolBar
*tbar
, wxControl
*control
)
104 : wxToolBarToolBase(tbar
, control
)
110 virtual void SetLabel(const wxString
& label
)
112 if ( label
== m_label
)
115 wxToolBarToolBase::SetLabel(label
);
117 // we need to update the label shown in the toolbar because it has a
118 // pointer to the internal buffer of the old label
120 // TODO: use TB_SETBUTTONINFO
123 // set/get the number of separators which we use to cover the space used by
124 // a control in the toolbar
125 void SetSeparatorsCount(size_t count
) { m_nSepCount
= count
; }
126 size_t GetSeparatorsCount() const { return m_nSepCount
; }
128 void SetBitmapIndex(int idx
) { m_bitmapIndex
= idx
; }
129 int GetBitmapIndex() const { return m_bitmapIndex
; }
137 // ============================================================================
139 // ============================================================================
141 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
145 wxToolBarToolBase
*wxToolMenuBar::CreateTool(int id
,
146 const wxString
& label
,
147 const wxBitmap
& bmpNormal
,
148 const wxBitmap
& bmpDisabled
,
150 wxObject
*clientData
,
151 const wxString
& shortHelp
,
152 const wxString
& longHelp
)
154 return new wxToolMenuBarTool(this, id
, label
, bmpNormal
, bmpDisabled
, kind
,
155 clientData
, shortHelp
, longHelp
);
158 wxToolBarToolBase
*wxToolMenuBar::CreateTool(wxControl
*control
)
160 return new wxToolMenuBarTool(this, control
);
163 // ----------------------------------------------------------------------------
164 // wxToolBar construction
165 // ----------------------------------------------------------------------------
167 void wxToolMenuBar::Init()
175 bool wxToolMenuBar::Create(wxWindow
*parent
,
180 const wxString
& name
,
183 // common initialisation
184 if ( !CreateControl(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
187 // MSW-specific initialisation
188 if ( !MSWCreateToolbar(pos
, size
, menuBar
) )
191 // set up the colors and fonts
192 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR
));
193 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
198 bool wxToolMenuBar::MSWCreateToolbar(const wxPoint
& WXUNUSED(pos
), const wxSize
& WXUNUSED(size
), wxMenuBar
* menuBar
)
202 m_menuBar
->SetToolBar(this);
204 #if defined(WINCE_WITHOUT_COMMANDBAR)
205 // Create the menubar.
208 memset (&mbi
, 0, sizeof (SHMENUBARINFO
));
209 mbi
.cbSize
= sizeof (SHMENUBARINFO
);
210 mbi
.hwndParent
= (HWND
) GetParent()->GetHWND();
211 #ifdef __SMARTPHONE__
212 mbi
.nToolBarId
= 5002;
214 mbi
.nToolBarId
= 5000;
218 mbi
.dwFlags
= 0 ; // SHCMBF_EMPTYBAR;
219 mbi
.hInstRes
= wxGetInstance();
221 if (!SHCreateMenuBar(&mbi
))
223 wxFAIL_MSG( _T("SHCreateMenuBar failed") );
227 SetHWND((WXHWND
) mbi
.hwndMB
);
229 HWND hWnd
= CommandBar_Create(wxGetInstance(), (HWND
) GetParent()->GetHWND(), GetId());
230 SetHWND((WXHWND
) hWnd
);
233 // install wxWidgets window proc for this window
242 void wxToolMenuBar::Recreate()
247 wxToolMenuBar::~wxToolMenuBar()
250 GetMenuBar()->SetToolBar(NULL
);
253 // Return HMENU for the menu associated with the commandbar
254 WXHMENU
wxToolMenuBar::GetHMenu()
256 #if defined(__HANDHELDPC__)
261 return (WXHMENU
) (HMENU
)::SendMessage((HWND
) GetHWND(), SHCMBM_GETMENU
, (WPARAM
)0, (LPARAM
)0);
268 // ----------------------------------------------------------------------------
269 // adding/removing tools
270 // ----------------------------------------------------------------------------
272 bool wxToolMenuBar::DoInsertTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
274 // nothing special to do here - we really create the toolbar buttons in
281 bool wxToolMenuBar::DoDeleteTool(size_t pos
, wxToolBarToolBase
*tool
)
283 // the main difficulty we have here is with the controls in the toolbars:
284 // as we (sometimes) use several separators to cover up the space used by
285 // them, the indices are not the same for us and the toolbar
287 // first determine the position of the first button to delete: it may be
288 // different from pos if we use several separators to cover the space used
290 wxToolBarToolsList::compatibility_iterator node
;
291 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
293 wxToolBarToolBase
*tool2
= node
->GetData();
296 // let node point to the next node in the list
297 node
= node
->GetNext();
302 if ( tool2
->IsControl() )
304 pos
+= ((wxToolMenuBarTool
*)tool2
)->GetSeparatorsCount() - 1;
308 // now determine the number of buttons to delete and the area taken by them
309 size_t nButtonsToDelete
= 1;
311 // get the size of the button we're going to delete
313 if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT
, pos
, (LPARAM
)&r
) )
315 wxLogLastError(_T("TB_GETITEMRECT"));
318 int width
= r
.right
- r
.left
;
320 if ( tool
->IsControl() )
322 nButtonsToDelete
= ((wxToolMenuBarTool
*)tool
)->GetSeparatorsCount();
324 width
*= nButtonsToDelete
;
327 // do delete all buttons
328 m_nButtons
-= nButtonsToDelete
;
329 while ( nButtonsToDelete
-- > 0 )
331 if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON
, pos
, 0) )
333 wxLogLastError(wxT("TB_DELETEBUTTON"));
341 // and finally reposition all the controls after this button (the toolbar
342 // takes care of all normal items)
343 for ( /* node -> first after deleted */ ; node
; node
= node
->GetNext() )
345 wxToolBarToolBase
*tool2
= node
->GetData();
346 if ( tool2
->IsControl() )
349 wxControl
*control
= tool2
->GetControl();
350 control
->GetPosition(&x
, NULL
);
351 control
->Move(x
- width
, wxDefaultCoord
);
358 bool wxToolMenuBar::Realize()
360 const size_t nTools
= GetToolsCount();
368 // delete all old buttons, if any
369 for ( size_t pos
= 0; pos
< m_nButtons
; pos
++ )
371 if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON
, 0, 0) )
373 wxLogDebug(wxT("TB_DELETEBUTTON failed"));
378 bool lastWasRadio
= false;
379 wxToolBarToolsList::Node
* node
;
380 for ( node
= m_tools
.GetFirst(); node
; node
= node
->GetNext() )
382 wxToolMenuBarTool
*tool
= (wxToolMenuBarTool
*) node
->GetData();
384 TBBUTTON buttons
[1] ;
386 TBBUTTON
& button
= buttons
[0];
388 wxZeroMemory(button
);
390 bool isRadio
= false;
391 switch ( tool
->GetStyle() )
393 case wxTOOL_STYLE_CONTROL
:
394 button
.idCommand
= tool
->GetId();
395 // fall through: create just a separator too
396 // TODO: controls are not yet supported on wxToolMenuBar.
398 case wxTOOL_STYLE_SEPARATOR
:
399 button
.fsState
= TBSTATE_ENABLED
;
400 button
.fsStyle
= TBSTYLE_SEP
;
403 case wxTOOL_STYLE_BUTTON
:
405 if ( HasFlag(wxTB_TEXT
) )
407 const wxString
& label
= tool
->GetLabel();
408 if ( !label
.empty() )
410 button
.iString
= (int)label
.c_str();
414 const wxBitmap
& bmp
= tool
->GetNormalBitmap();
416 wxBitmap bmpToUse
= bmp
;
418 if (bmp
.GetWidth() < 16 || bmp
.GetHeight() < 16 || bmp
.GetMask() != NULL
)
422 memDC
.SelectObject(b
);
423 wxColour col
= wxColour(192,192,192);
424 memDC
.SetBackground(wxBrush(col
));
426 int x
= (16 - bmp
.GetWidth())/2;
427 int y
= (16 - bmp
.GetHeight())/2;
428 memDC
.DrawBitmap(bmp
, x
, y
, true);
429 memDC
.SelectObject(wxNullBitmap
);
432 tool
->SetNormalBitmap(b
);
438 n
= ::CommandBar_AddBitmap( (HWND
) GetHWND(), NULL
, (int) (HBITMAP
) bmpToUse
.GetHBITMAP(),
442 button
.idCommand
= tool
->GetId();
445 if ( tool
->IsEnabled() )
446 button
.fsState
|= TBSTATE_ENABLED
;
447 if ( tool
->IsToggled() )
448 button
.fsState
|= TBSTATE_CHECKED
;
450 switch ( tool
->GetKind() )
453 button
.fsStyle
= TBSTYLE_CHECKGROUP
;
457 // the first item in the radio group is checked by
458 // default to be consistent with wxGTK and the menu
460 button
.fsState
|= TBSTATE_CHECKED
;
469 button
.fsStyle
= TBSTYLE_CHECK
;
473 wxFAIL_MSG( _T("unexpected toolbar button kind") );
477 button
.fsStyle
= TBSTYLE_BUTTON
;
482 if ( !::CommandBar_AddButtons( (HWND
) GetHWND(), 1, buttons
) )
484 wxFAIL_MSG( wxT("Could not add toolbar button."));
487 lastWasRadio
= isRadio
;
493 bool wxToolMenuBar::MSWCommand(WXUINT
WXUNUSED(cmd
), WXWORD id
)
495 wxToolBarToolBase
*tool
= FindById((int)id
);
498 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
499 event
.SetEventObject(this);
503 return GetEventHandler()->ProcessEvent(event
);
506 if ( tool
->CanBeToggled() )
508 LRESULT state
= ::SendMessage(GetHwnd(), TB_GETSTATE
, id
, 0);
509 tool
->Toggle((state
& TBSTATE_CHECKED
) != 0);
512 bool toggled
= tool
->IsToggled();
514 // avoid sending the event when a radio button is released, this is not
516 if ( !tool
->CanBeToggled() || tool
->GetKind() != wxITEM_RADIO
|| toggled
)
518 // OnLeftClick() can veto the button state change - for buttons which
519 // may be toggled only, of couse
520 if ( !OnLeftClick((int)id
, toggled
) && tool
->CanBeToggled() )
524 tool
->SetToggle(toggled
);
526 ::SendMessage(GetHwnd(), TB_CHECKBUTTON
, id
, MAKELONG(toggled
, 0));
533 WXLRESULT
wxToolMenuBar::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
541 // we don't handle mouse moves, so always pass the message to
542 // wxControl::MSWWindowProc
543 HandleMouseMove(wParam
, lParam
);
550 return wxControl::MSWWindowProc(nMsg
, wParam
, lParam
);
556 ////////////// For Smartphone
558 // ----------------------------------------------------------------------------
560 // ----------------------------------------------------------------------------
562 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxToolBarBase
)
564 BEGIN_EVENT_TABLE(wxToolBar
, wxToolBarBase
)
567 wxToolBarToolBase
*wxToolBar::CreateTool(int id
,
568 const wxString
& label
,
569 const wxBitmap
& bmpNormal
,
570 const wxBitmap
& bmpDisabled
,
572 wxObject
*clientData
,
573 const wxString
& shortHelp
,
574 const wxString
& longHelp
)
576 return new wxToolBarToolBase(this, id
, label
, bmpNormal
, bmpDisabled
, kind
,
577 clientData
, shortHelp
, longHelp
);
580 wxToolBarToolBase
*wxToolBar::CreateTool(wxControl
*control
)
582 return new wxToolBarToolBase(this, control
);
585 bool wxToolBar::Create(wxWindow
*parent
,
586 wxWindowID
WXUNUSED(id
),
587 const wxPoint
& WXUNUSED(pos
),
588 const wxSize
& WXUNUSED(size
),
590 const wxString
& name
)
592 // TODO: we may need to make this a dummy hidden window to
593 // satisfy other parts of wxWidgets.
595 parent
->AddChild(this);
597 SetWindowStyle(style
);
603 // ----------------------------------------------------------------------------
604 // adding/removing tools
605 // ----------------------------------------------------------------------------
607 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
613 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
619 wxToolBarToolBase
*wxToolBar::FindToolForPosition(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
)) const
624 // ----------------------------------------------------------------------------
626 // ----------------------------------------------------------------------------
628 void wxToolBar::DoEnableTool(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(enable
))
632 void wxToolBar::DoToggleTool(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(toggle
))
636 void wxToolBar::DoSetToggle(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(toggle
))
638 wxFAIL_MSG( _T("not implemented") );
646 #endif // wxUSE_TOOLBAR && Win95