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