Commited FRM's stockitem patch (empty stock items).
[wxWidgets.git] / src / msw / wince / menuce.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/wince/menuce.cpp
3 // Purpose: Smartphone menus implementation
4 // Author: Wlodzimierz ABX Skiba
5 // Modified by:
6 // Created: 28.05.2004
7 // RCS-ID: $Id$
8 // Copyright: (c) Wlodzimierz Skiba
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if defined(__SMARTPHONE__) && defined(__WXWINCE__)
28
29 #ifndef WX_PRECOMP
30 #include "wx/app.h"
31 #include "wx/toplevel.h"
32 #include "wx/menu.h"
33 #endif //WX_PRECOMP
34
35 #include <windows.h>
36 #include <ole2.h>
37 #include <shellapi.h>
38 #include <aygshell.h>
39 #include <tpcshell.h>
40 #include <tpcuser.h>
41 #include "wx/msw/wince/missing.h"
42
43 #include "wx/msw/wince/resources.h"
44
45 #include "wx/stockitem.h"
46
47 wxTopLevelWindowMSW::ButtonMenu::ButtonMenu()
48 {
49 m_id = wxID_ANY;
50 m_label = wxEmptyString;
51 m_menu = NULL;
52 m_assigned = false;
53 }
54
55 wxTopLevelWindowMSW::ButtonMenu::~ButtonMenu()
56 {
57 if(m_menu)
58 {
59 delete m_menu;
60 m_menu = NULL;
61 };
62 }
63
64 void wxTopLevelWindowMSW::SetLeftMenu(int id, const wxString& label, wxMenu *subMenu)
65 {
66 m_LeftButton.SetButton(id, label, subMenu);
67 ReloadAllButtons();
68 }
69
70 void wxTopLevelWindowMSW::SetRightMenu(int id, const wxString& label, wxMenu *subMenu)
71 {
72 m_RightButton.SetButton(id, label, subMenu);
73 ReloadAllButtons();
74 }
75
76 void wxTopLevelWindowMSW::ButtonMenu::SetButton(int id, const wxString& label, wxMenu *subMenu)
77 {
78 m_assigned = true;
79 m_id = id;
80 if(label.empty() && wxIsStockID(id))
81 m_label = wxGetStockLabel(id, wxSTOCK_NOFLAGS);
82 else
83 m_label = label;
84 m_menu = subMenu;
85 }
86
87 wxMenu *wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(wxMenu *menu)
88 {
89 // This is required in case of converting wxMenuBar to wxMenu in wxFrame::SetMenuBar.
90 // All submenus has to be recreated because of new owner.
91
92 wxMenu *duplication = new wxMenu;
93
94 if (menu)
95 {
96 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
97 while (node)
98 {
99 wxMenuItem *item = node->GetData();
100 if (item)
101 {
102 wxMenu *submenu = NULL;
103
104 if(item->IsSubMenu())
105 submenu = DuplicateMenu( item->GetSubMenu() );
106 else
107 submenu = NULL;
108
109 wxMenuItem *new_item = wxMenuItem::New(duplication, item->GetId(), item->GetLabel(), item->GetHelp(), item->GetKind(), submenu);
110
111 if( item->IsCheckable() )
112 new_item->Check(item->IsChecked());
113
114 new_item->Enable( item->IsEnabled() );
115
116 duplication->Append(new_item);
117 }
118 node = node->GetNext();
119 }
120
121 }
122
123 return duplication;
124 }
125
126 void wxMenuToHMenu(wxMenu* in, HMENU hMenu)
127 {
128 if(!in) return;
129
130 wxChar buf[256];
131
132 wxMenuItemList::compatibility_iterator node = in->GetMenuItems().GetFirst();
133 while ( node )
134 {
135 wxMenuItem *item = node->GetData();
136
137 UINT uFlags = 0;
138 UINT uIDNewItem;
139 LPCTSTR lpNewItem;
140
141 if( item->IsSeparator() )
142 {
143 uFlags |= MF_SEPARATOR;
144 uIDNewItem = (unsigned)wxID_ANY;
145 lpNewItem = NULL;
146 }
147 else
148 {
149 // label
150 uFlags |= MF_STRING;
151 wxStrcpy(buf, item->GetLabel().c_str());
152 lpNewItem = buf;
153
154 // state
155 uFlags |= ( item->IsEnabled() ? MF_ENABLED : MF_GRAYED );
156
157 // checked
158 uFlags |= ( item->IsChecked() ? MF_CHECKED : MF_UNCHECKED );
159
160 if( item->IsSubMenu() )
161 {
162 uFlags |= MF_POPUP;
163 HMENU hSubMenu = CreatePopupMenu();
164 wxMenuToHMenu(item->GetSubMenu(), hSubMenu);
165 uIDNewItem = (UINT) hSubMenu;
166 }
167 else
168 {
169 uIDNewItem = item->GetId();
170 }
171 }
172
173 AppendMenu(hMenu, uFlags, uIDNewItem, lpNewItem);
174
175 node = node->GetNext();
176 }
177 }
178
179 void wxTopLevelWindowMSW::ReloadButton(ButtonMenu& button, UINT menuID)
180 {
181 TBBUTTONINFO button_info;
182 wxChar buf[256];
183
184 // set button name
185 memset (&button_info, 0, sizeof (TBBUTTONINFO));
186 button_info.cbSize = sizeof(TBBUTTONINFO);
187 button_info.dwMask = TBIF_TEXT | TBIF_STATE;
188 button_info.fsState = TBSTATE_ENABLED;
189 wxStrcpy(buf, button.GetLabel().c_str());
190 button_info.pszText = buf;
191 ::SendMessage(m_MenuBarHWND, TB_SETBUTTONINFO, menuID, (LPARAM) &button_info);
192
193 if(button.IsMenu())
194 {
195 HMENU hPopupMenu = (HMENU) ::SendMessage(m_MenuBarHWND, SHCMBM_GETSUBMENU, 0, menuID);
196 RemoveMenu(hPopupMenu, 0, MF_BYPOSITION);
197 wxMenuToHMenu(button.GetMenu(), hPopupMenu);
198 }
199 }
200
201 void wxTopLevelWindowMSW::ReloadAllButtons()
202 {
203 // first reaload only after initialization of both buttons
204 // it should is done at the end of Create() of wxTLW
205 if(!m_LeftButton.IsAssigned() || !m_RightButton.IsAssigned())
206 return;
207
208 SHMENUBARINFO menu_bar;
209 wxString label;
210
211 memset (&menu_bar, 0, sizeof (SHMENUBARINFO));
212 menu_bar.cbSize = sizeof (SHMENUBARINFO);
213 menu_bar.hwndParent = (HWND) GetHWND();
214
215 if(m_LeftButton.IsMenu() && m_RightButton.IsMenu())
216 menu_bar.nToolBarId = IDR_MENUBAR_BOTH_MENUS;
217 else if(m_LeftButton.IsMenu())
218 menu_bar.nToolBarId = IDR_MENUBAR_LEFT_MENU;
219 else if(m_RightButton.IsMenu())
220 menu_bar.nToolBarId = IDR_MENUBAR_RIGHT_MENU;
221 else
222 menu_bar.nToolBarId = IDR_MENUBAR_ONE_BUTTON;
223
224 menu_bar.hInstRes = wxGetInstance();
225
226 if (!SHCreateMenuBar(&menu_bar))
227 {
228 wxFAIL_MSG( _T("SHCreateMenuBar failed") );
229 return;
230 }
231
232 HWND prev_MenuBar = m_MenuBarHWND;
233 m_MenuBarHWND = menu_bar.hwndMB;
234
235 ReloadButton(m_LeftButton, IDM_LEFT);
236 ReloadButton(m_RightButton, IDM_RIGHT);
237
238 // hide previous and show new menubar
239 if ( prev_MenuBar )
240 ::ShowWindow( prev_MenuBar, SW_HIDE );
241 ::ShowWindow( m_MenuBarHWND, SW_SHOW );
242
243 // Setup backspace key handling
244 SendMessage(m_MenuBarHWND, SHCMBM_OVERRIDEKEY, VK_TBACK,
245 MAKELPARAM( SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
246 SHMBOF_NODEFAULT | SHMBOF_NOTIFY ));
247 }
248
249 bool wxTopLevelWindowMSW::HandleCommand(WXWORD id, WXWORD WXUNUSED(cmd), WXHWND WXUNUSED(control))
250 {
251 // handle here commands from Smartphone menu bar
252 if ( id == IDM_LEFT || id == IDM_RIGHT )
253 {
254 int menuId = id == IDM_LEFT ? m_LeftButton.GetId() : m_RightButton.GetId() ;
255 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, menuId);
256 commandEvent.SetEventObject(this);
257 GetEventHandler()->ProcessEvent(commandEvent);
258 return true;
259 }
260 return false;
261 }
262
263 bool wxTopLevelWindowMSW::MSWShouldPreProcessMessage(WXMSG* pMsg)
264 {
265 MSG *msg = (MSG *)pMsg;
266
267 // Process back key to be like backspace.
268 if (msg->message == WM_HOTKEY)
269 {
270 if (HIWORD(msg->lParam) == VK_TBACK)
271 SHSendBackToFocusWindow(msg->message, msg->wParam, msg->lParam);
272 }
273
274 return wxTopLevelWindowBase::MSWShouldPreProcessMessage(pMsg);
275 }
276
277 #endif // __SMARTPHONE__ && __WXWINCE__