]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/menuitem.cpp
let the popup listbox process the kbd messages in wxComboBox
[wxWidgets.git] / src / msw / menuitem.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: menuitem.cpp
3// Purpose: wxMenuItem implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 11.11.97
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "menuitem.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#if wxUSE_MENUS
32
33#ifndef WX_PRECOMP
34 #include "wx/font.h"
35 #include "wx/bitmap.h"
36 #include "wx/settings.h"
37 #include "wx/font.h"
38 #include "wx/window.h"
39 #include "wx/accel.h"
40 #include "wx/menu.h"
41 #include "wx/string.h"
42#endif
43
44#include "wx/menuitem.h"
45#include "wx/log.h"
46
47#if wxUSE_ACCEL
48 #include "wx/accel.h"
49#endif // wxUSE_ACCEL
50
51#include "wx/msw/private.h"
52
53// ---------------------------------------------------------------------------
54// macro
55// ---------------------------------------------------------------------------
56
57// hide the ugly cast
58#define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
59
60// conditional compilation
61#if wxUSE_OWNER_DRAWN
62 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
63#else // !wxUSE_OWNER_DRAWN
64 #define OWNER_DRAWN_ONLY( code )
65#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
66
67// ============================================================================
68// implementation
69// ============================================================================
70
71// ----------------------------------------------------------------------------
72// dynamic classes implementation
73// ----------------------------------------------------------------------------
74
75IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
76
77// ----------------------------------------------------------------------------
78// wxMenuItem
79// ----------------------------------------------------------------------------
80
81// ctor & dtor
82// -----------
83
84wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
85 int id,
86 const wxString& text,
87 const wxString& strHelp,
88 wxItemKind kind,
89 wxMenu *pSubMenu)
90 : wxMenuItemBase(pParentMenu, id, text, strHelp, kind, pSubMenu)
91#if wxUSE_OWNER_DRAWN
92 , wxOwnerDrawn(GetLabelFromText(text), kind == wxItem_Check)
93#endif // owner drawn
94{
95 wxASSERT_MSG( pParentMenu != NULL, wxT("a menu item should have a parent") );
96
97 m_startRadioGroup =
98 m_endRadioGroup = -1;
99
100#if wxUSE_OWNER_DRAWN
101 // set default menu colors
102 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
103
104 SetTextColour(SYS_COLOR(MENUTEXT));
105 SetBackgroundColour(SYS_COLOR(MENU));
106
107 #undef SYS_COLOR
108
109 // we don't want normal items be owner-drawn
110 ResetOwnerDrawn();
111
112 // tell the owner drawing code to to show the accel string as well
113 SetAccelString(text.AfterFirst(_T('\t')));
114#endif // wxUSE_OWNER_DRAWN
115}
116
117wxMenuItem::~wxMenuItem()
118{
119}
120
121// misc
122// ----
123
124// return the id for calling Win32 API functions
125int wxMenuItem::GetRealId() const
126{
127 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
128}
129
130// get item state
131// --------------
132
133bool wxMenuItem::IsChecked() const
134{
135 int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetId(), MF_BYCOMMAND);
136
137 return (flag & MF_CHECKED) != 0;
138}
139
140/* static */
141wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
142{
143 return wxStripMenuCodes(text);
144}
145
146// change item state
147// -----------------
148
149void wxMenuItem::Enable(bool enable)
150{
151 if ( m_isEnabled == enable )
152 return;
153
154 long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
155 GetRealId(),
156 MF_BYCOMMAND |
157 (enable ? MF_ENABLED : MF_GRAYED));
158
159 if ( rc == -1 ) {
160 wxLogLastError(wxT("EnableMenuItem"));
161 }
162
163 wxMenuItemBase::Enable(enable);
164}
165
166void wxMenuItem::Check(bool check)
167{
168 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
169
170 if ( m_isChecked == check )
171 return;
172
173 int flags = check ? MF_CHECKED : MF_UNCHECKED;
174 HMENU hmenu = GetHMenuOf(m_parentMenu);
175
176 if ( GetKind() == wxItem_Radio )
177 {
178 // it doesn't make sense to uncheck a radio item - what would this do?
179 if ( !check )
180 return;
181
182 const wxMenuItemList& items = m_parentMenu->GetMenuItems();
183 int pos = items.IndexOf(this);
184 wxCHECK_RET( pos != wxNOT_FOUND,
185 _T("menuitem not found in the menu items list?") );
186
187#ifdef __WIN32__
188 if ( !::CheckMenuRadioItem(hmenu,
189 m_startRadioGroup, // first group item
190 m_endRadioGroup, // last one
191 pos, // the one to check
192 MF_BYPOSITION | flags) )
193 {
194 wxLogLastError(_T("CheckMenuRadioItem"));
195 }
196#endif // __WIN32__
197
198 // also uncheck all the other items in this radio group
199 wxMenuItemList::Node *node = items.Item(m_startRadioGroup);
200 for ( int n = m_startRadioGroup; n <= m_endRadioGroup && node; n++ )
201 {
202 if ( n != pos )
203 {
204 node->GetData()->m_isChecked = FALSE;
205 }
206
207 // we also have to do it in the menu for Win16 (under Win32
208 // CheckMenuRadioItem() does it for us)
209#ifndef __WIN32__
210 ::CheckMenuItem(hmenu, n, n == pos ? MF_CHECKED : MF_UNCHECKED);
211#endif // Win16
212
213 node = node->GetNext();
214 }
215 }
216 else // check item
217 {
218 if ( ::CheckMenuItem(hmenu,
219 GetRealId(),
220 MF_BYCOMMAND | flags) == -1 )
221 {
222 wxLogLastError(wxT("CheckMenuItem"));
223 }
224 }
225
226 wxMenuItemBase::Check(check);
227}
228
229void wxMenuItem::SetText(const wxString& text)
230{
231 // don't do anything if label didn't change
232 if ( m_text == text )
233 return;
234
235 wxMenuItemBase::SetText(text);
236 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
237
238 HMENU hMenu = GetHMenuOf(m_parentMenu);
239 wxCHECK_RET( hMenu, wxT("menuitem without menu") );
240
241#if wxUSE_ACCEL
242 m_parentMenu->UpdateAccel(this);
243#endif // wxUSE_ACCEL
244
245 UINT id = GetRealId();
246 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
247 if ( flagsOld == 0xFFFFFFFF )
248 {
249 wxLogLastError(wxT("GetMenuState"));
250 }
251 else
252 {
253 if ( IsSubMenu() )
254 {
255 // high byte contains the number of items in a submenu for submenus
256 flagsOld &= 0xFF;
257 flagsOld |= MF_POPUP;
258 }
259
260 LPCTSTR data;
261
262#if wxUSE_OWNER_DRAWN
263 if ( IsOwnerDrawn() )
264 {
265 flagsOld |= MF_OWNERDRAW;
266 data = (LPCTSTR)this;
267 }
268 else
269#endif //owner drawn
270 {
271 flagsOld |= MF_STRING;
272 data = (wxChar*) text.c_str();
273 }
274
275 if ( ::ModifyMenu(hMenu, id,
276 MF_BYCOMMAND | flagsOld,
277 id, data) == (int)0xFFFFFFFF )
278 {
279 wxLogLastError(wxT("ModifyMenu"));
280 }
281 }
282}
283
284void wxMenuItem::SetCheckable(bool checkable)
285{
286 wxMenuItemBase::SetCheckable(checkable);
287 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable) );
288}
289
290// ----------------------------------------------------------------------------
291// wxMenuItemBase
292// ----------------------------------------------------------------------------
293
294wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
295 int id,
296 const wxString& name,
297 const wxString& help,
298 wxItemKind kind,
299 wxMenu *subMenu)
300{
301 return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
302}
303
304#endif // wxUSE_MENUS