]> git.saurik.com Git - wxWidgets.git/blame - src/msw/wince/menuce.cpp
fix crash which happened if you called SetAttr(NULL) followed by SetAttr(attr) (...
[wxWidgets.git] / src / msw / wince / menuce.cpp
CommitLineData
fb8a56b7
WS
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
fb8a56b7
WS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
96dcd41a 27#if defined(__SMARTPHONE__) && defined(__WXWINCE__)
fb8a56b7
WS
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
fb8a56b7
WS
35#include <windows.h>
36#include <ole2.h>
37#include <shellapi.h>
38#include <aygshell.h>
96dcd41a 39#include <tpcshell.h>
b2383543 40#include <tpcuser.h>
fb8a56b7
WS
41#include "wx/msw/wince/missing.h"
42
43#include "wx/msw/wince/resources.h"
44
eb3e6de3
WS
45#include "wx/stockitem.h"
46
fb8a56b7
WS
47wxTopLevelWindowMSW::ButtonMenu::ButtonMenu()
48{
49 m_id = wxID_ANY;
50 m_label = wxEmptyString;
51 m_menu = NULL;
52 m_assigned = false;
53}
54
55wxTopLevelWindowMSW::ButtonMenu::~ButtonMenu()
56{
57 if(m_menu)
58 {
59 delete m_menu;
60 m_menu = NULL;
61 };
62}
63
64void wxTopLevelWindowMSW::SetLeftMenu(int id, const wxString& label, wxMenu *subMenu)
65{
66 m_LeftButton.SetButton(id, label, subMenu);
67 ReloadAllButtons();
68}
69
70void wxTopLevelWindowMSW::SetRightMenu(int id, const wxString& label, wxMenu *subMenu)
71{
72 m_RightButton.SetButton(id, label, subMenu);
73 ReloadAllButtons();
74}
75
76void wxTopLevelWindowMSW::ButtonMenu::SetButton(int id, const wxString& label, wxMenu *subMenu)
77{
78 m_assigned = true;
79 m_id = id;
eb3e6de3 80 if(label.empty() && wxIsStockID(id))
ee0a94cf 81 m_label = wxGetStockLabel(id, wxSTOCK_NOFLAGS);
eb3e6de3
WS
82 else
83 m_label = label;
fb8a56b7
WS
84 m_menu = subMenu;
85}
86
87wxMenu *wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(wxMenu *menu)
88{
39fc096d
WS
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.
fb8a56b7 91
39fc096d 92 wxMenu *duplication = new wxMenu;
fb8a56b7 93
39fc096d
WS
94 if (menu)
95 {
fb8a56b7
WS
96 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
97 while (node)
39fc096d
WS
98 {
99 wxMenuItem *item = node->GetData();
100 if (item)
101 {
102 wxMenu *submenu = NULL;
fb8a56b7 103
39fc096d
WS
104 if(item->IsSubMenu())
105 submenu = DuplicateMenu( item->GetSubMenu() );
106 else
107 submenu = NULL;
fb8a56b7 108
39fc096d 109 wxMenuItem *new_item = wxMenuItem::New(duplication, item->GetId(), item->GetLabel(), item->GetHelp(), item->GetKind(), submenu);
fb8a56b7 110
39fc096d
WS
111 if( item->IsCheckable() )
112 new_item->Check(item->IsChecked());
fb8a56b7 113
39fc096d 114 new_item->Enable( item->IsEnabled() );
fb8a56b7 115
39fc096d
WS
116 duplication->Append(new_item);
117 }
fb8a56b7 118 node = node->GetNext();
39fc096d
WS
119 }
120
121 }
fb8a56b7 122
39fc096d 123 return duplication;
fb8a56b7
WS
124}
125
126void 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
179void 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;
39fc096d 191 ::SendMessage(m_MenuBarHWND, TB_SETBUTTONINFO, menuID, (LPARAM) &button_info);
fb8a56b7
WS
192
193 if(button.IsMenu())
194 {
39fc096d 195 HMENU hPopupMenu = (HMENU) ::SendMessage(m_MenuBarHWND, SHCMBM_GETSUBMENU, 0, menuID);
fb8a56b7
WS
196 RemoveMenu(hPopupMenu, 0, MF_BYPOSITION);
197 wxMenuToHMenu(button.GetMenu(), hPopupMenu);
198 }
199}
200
201void 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
96dcd41a
WS
243 // Setup backspace key handling
244 SendMessage(m_MenuBarHWND, SHCMBM_OVERRIDEKEY, VK_TBACK,
245 MAKELPARAM( SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
246 SHMBOF_NODEFAULT | SHMBOF_NOTIFY ));
fb8a56b7
WS
247}
248
249bool 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
96dcd41a
WS
263bool wxTopLevelWindowMSW::MSWShouldPreProcessMessage(WXMSG* pMsg)
264{
265 MSG *msg = (MSG *)pMsg;
fb8a56b7 266
96dcd41a
WS
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__