]> git.saurik.com Git - wxWidgets.git/blob - src/msw/wince/menuce.cpp
Define ACO_AUTOAPPEND for MinGW/Cygwin.
[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 // Licence: 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 wxDELETE(m_menu);
58 }
59
60 void wxTopLevelWindowMSW::SetLeftMenu(int id, const wxString& label, wxMenu *subMenu)
61 {
62 m_LeftButton.SetButton(id, label, subMenu);
63 ReloadAllButtons();
64 }
65
66 void wxTopLevelWindowMSW::SetRightMenu(int id, const wxString& label, wxMenu *subMenu)
67 {
68 m_RightButton.SetButton(id, label, subMenu);
69 ReloadAllButtons();
70 }
71
72 void wxTopLevelWindowMSW::ButtonMenu::SetButton(int id, const wxString& label, wxMenu *subMenu)
73 {
74 m_assigned = true;
75 m_id = id;
76 if(label.empty() && wxIsStockID(id))
77 m_label = wxGetStockLabel(id, wxSTOCK_NOFLAGS);
78 else
79 m_label = label;
80 m_menu = subMenu;
81 }
82
83 wxMenu *wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(wxMenu *menu)
84 {
85 // This is required in case of converting wxMenuBar to wxMenu in wxFrame::SetMenuBar.
86 // All submenus has to be recreated because of new owner.
87
88 wxMenu *duplication = new wxMenu;
89
90 if (menu)
91 {
92 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
93 while (node)
94 {
95 wxMenuItem *item = node->GetData();
96 if (item)
97 {
98 wxMenu *submenu = NULL;
99
100 if(item->IsSubMenu())
101 submenu = DuplicateMenu( item->GetSubMenu() );
102 else
103 submenu = NULL;
104
105 wxMenuItem *new_item = wxMenuItem::New(duplication, item->GetId(), item->GetLabel(), item->GetHelp(), item->GetKind(), submenu);
106
107 if( item->IsCheckable() )
108 new_item->Check(item->IsChecked());
109
110 new_item->Enable( item->IsEnabled() );
111
112 duplication->Append(new_item);
113 }
114 node = node->GetNext();
115 }
116
117 }
118
119 return duplication;
120 }
121
122 void wxMenuToHMenu(wxMenu* in, HMENU hMenu)
123 {
124 if(!in) return;
125
126 wxChar buf[256];
127
128 wxMenuItemList::compatibility_iterator node = in->GetMenuItems().GetFirst();
129 while ( node )
130 {
131 wxMenuItem *item = node->GetData();
132
133 UINT uFlags = 0;
134 UINT uIDNewItem;
135 LPCTSTR lpNewItem;
136
137 if( item->IsSeparator() )
138 {
139 uFlags |= MF_SEPARATOR;
140 uIDNewItem = (unsigned)wxID_ANY;
141 lpNewItem = NULL;
142 }
143 else
144 {
145 // label
146 uFlags |= MF_STRING;
147 wxStrcpy(buf, item->GetLabel().c_str());
148 lpNewItem = buf;
149
150 // state
151 uFlags |= ( item->IsEnabled() ? MF_ENABLED : MF_GRAYED );
152
153 // checked
154 uFlags |= ( item->IsChecked() ? MF_CHECKED : MF_UNCHECKED );
155
156 if( item->IsSubMenu() )
157 {
158 uFlags |= MF_POPUP;
159 HMENU hSubMenu = CreatePopupMenu();
160 wxMenuToHMenu(item->GetSubMenu(), hSubMenu);
161 uIDNewItem = (UINT) hSubMenu;
162 }
163 else
164 {
165 uIDNewItem = item->GetId();
166 }
167 }
168
169 AppendMenu(hMenu, uFlags, uIDNewItem, lpNewItem);
170
171 node = node->GetNext();
172 }
173 }
174
175 void wxTopLevelWindowMSW::ReloadButton(ButtonMenu& button, UINT menuID)
176 {
177 TBBUTTONINFO button_info;
178 wxChar buf[256];
179
180 // set button name
181 memset (&button_info, 0, sizeof (TBBUTTONINFO));
182 button_info.cbSize = sizeof(TBBUTTONINFO);
183 button_info.dwMask = TBIF_TEXT | TBIF_STATE;
184 button_info.fsState = TBSTATE_ENABLED;
185 wxStrcpy(buf, button.GetLabel().c_str());
186 button_info.pszText = buf;
187 ::SendMessage(m_MenuBarHWND, TB_SETBUTTONINFO, menuID, (LPARAM) &button_info);
188
189 if(button.IsMenu())
190 {
191 HMENU hPopupMenu = (HMENU) ::SendMessage(m_MenuBarHWND, SHCMBM_GETSUBMENU, 0, menuID);
192 RemoveMenu(hPopupMenu, 0, MF_BYPOSITION);
193 wxMenuToHMenu(button.GetMenu(), hPopupMenu);
194 }
195 }
196
197 void wxTopLevelWindowMSW::ReloadAllButtons()
198 {
199 // first reaload only after initialization of both buttons
200 // it should is done at the end of Create() of wxTLW
201 if(!m_LeftButton.IsAssigned() || !m_RightButton.IsAssigned())
202 return;
203
204 SHMENUBARINFO menu_bar;
205 wxString label;
206
207 memset (&menu_bar, 0, sizeof (SHMENUBARINFO));
208 menu_bar.cbSize = sizeof (SHMENUBARINFO);
209 menu_bar.hwndParent = (HWND) GetHWND();
210
211 if(m_LeftButton.IsMenu() && m_RightButton.IsMenu())
212 menu_bar.nToolBarId = IDR_MENUBAR_BOTH_MENUS;
213 else if(m_LeftButton.IsMenu())
214 menu_bar.nToolBarId = IDR_MENUBAR_LEFT_MENU;
215 else if(m_RightButton.IsMenu())
216 menu_bar.nToolBarId = IDR_MENUBAR_RIGHT_MENU;
217 else
218 menu_bar.nToolBarId = IDR_MENUBAR_ONE_BUTTON;
219
220 menu_bar.hInstRes = wxGetInstance();
221
222 if (!SHCreateMenuBar(&menu_bar))
223 {
224 wxFAIL_MSG( wxT("SHCreateMenuBar failed") );
225 return;
226 }
227
228 HWND prev_MenuBar = m_MenuBarHWND;
229 m_MenuBarHWND = menu_bar.hwndMB;
230
231 ReloadButton(m_LeftButton, IDM_LEFT);
232 ReloadButton(m_RightButton, IDM_RIGHT);
233
234 // hide previous and show new menubar
235 if ( prev_MenuBar )
236 ::ShowWindow( prev_MenuBar, SW_HIDE );
237 ::ShowWindow( m_MenuBarHWND, SW_SHOW );
238
239 // Setup backspace key handling
240 SendMessage(m_MenuBarHWND, SHCMBM_OVERRIDEKEY, VK_TBACK,
241 MAKELPARAM( SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
242 SHMBOF_NODEFAULT | SHMBOF_NOTIFY ));
243 }
244
245 bool wxTopLevelWindowMSW::HandleCommand(WXWORD id, WXWORD WXUNUSED(cmd), WXHWND WXUNUSED(control))
246 {
247 // handle here commands from Smartphone menu bar
248 if ( id == IDM_LEFT || id == IDM_RIGHT )
249 {
250 int menuId = id == IDM_LEFT ? m_LeftButton.GetId() : m_RightButton.GetId() ;
251 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, menuId);
252 commandEvent.SetEventObject(this);
253 GetEventHandler()->ProcessEvent(commandEvent);
254 return true;
255 }
256 return false;
257 }
258
259 bool wxTopLevelWindowMSW::MSWShouldPreProcessMessage(WXMSG* pMsg)
260 {
261 MSG *msg = (MSG *)pMsg;
262
263 // Process back key to be like backspace.
264 if (msg->message == WM_HOTKEY)
265 {
266 if (HIWORD(msg->lParam) == VK_TBACK)
267 SHSendBackToFocusWindow(msg->message, msg->wParam, msg->lParam);
268 }
269
270 return wxTopLevelWindowBase::MSWShouldPreProcessMessage(pMsg);
271 }
272
273 #endif // __SMARTPHONE__ && __WXWINCE__