wxMenu and wxMenuBar modifications: now works much better with owner-drawn
[wxWidgets.git] / src / msw / menuitem.cpp
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 #ifndef WX_PRECOMP
32 #include "wx/menu.h"
33 #include "wx/font.h"
34 #include "wx/bitmap.h"
35 #include "wx/settings.h"
36 #include "wx/font.h"
37 #endif
38
39 #include "wx/ownerdrw.h"
40 #include "wx/menuitem.h"
41
42 #include <windows.h>
43
44 #ifdef GetClassInfo
45 #undef GetClassInfo
46 #endif
47
48 #ifdef GetClassName
49 #undef GetClassName
50 #endif
51
52 // ---------------------------------------------------------------------------
53 // convenience macro
54 // ---------------------------------------------------------------------------
55
56 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
57
58 // ============================================================================
59 // implementation
60 // ============================================================================
61
62 // ----------------------------------------------------------------------------
63 // dynamic classes implementation
64 // ----------------------------------------------------------------------------
65
66 #if !defined(USE_SHARED_LIBRARY) || !USE_SHARED_LIBRARY
67 #if wxUSE_OWNER_DRAWN
68 IMPLEMENT_DYNAMIC_CLASS2(wxMenuItem, wxObject, wxOwnerDrawn)
69 #else //!USE_OWNER_DRAWN
70 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
71 #endif //USE_OWNER_DRAWN
72
73 #endif //USE_SHARED_LIBRARY
74
75 // ----------------------------------------------------------------------------
76 // wxMenuItem
77 // ----------------------------------------------------------------------------
78
79 // ctor & dtor
80 // -----------
81
82 wxMenuItem::wxMenuItem(wxMenu *pParentMenu, int id,
83 const wxString& strName, const wxString& strHelp,
84 bool bCheckable,
85 wxMenu *pSubMenu) :
86 #if wxUSE_OWNER_DRAWN
87 wxOwnerDrawn(strName, bCheckable),
88 #else //no owner drawn support
89 m_bCheckable(bCheckable),
90 m_strName(strName),
91 #endif //owner drawn
92 m_strHelp(strHelp)
93 {
94 wxASSERT_MSG( pParentMenu != NULL, "a menu item should have a parent" );
95
96 #if wxUSE_OWNER_DRAWN
97 // set default menu colors
98 #define SYS_COLOR(c) (wxSystemSettings::GetSystemColour(wxSYS_COLOUR_##c))
99
100 SetTextColour(SYS_COLOR(MENUTEXT));
101 SetBackgroundColour(SYS_COLOR(MENU));
102
103 // we don't want normal items be owner-drawn
104 ResetOwnerDrawn();
105
106 #undef SYS_COLOR
107 #endif
108
109 m_pParentMenu = pParentMenu;
110 m_pSubMenu = pSubMenu;
111 m_bEnabled = TRUE;
112 m_idItem = id;
113 }
114
115 wxMenuItem::~wxMenuItem()
116 {
117 }
118
119 // misc
120 // ----
121
122 // return the id for calling Win32 API functions
123 int wxMenuItem::GetRealId() const
124 {
125 return m_pSubMenu ? (int)m_pSubMenu->GetHMenu() : GetId();
126 }
127
128 // delete the sub menu
129 // -------------------
130 void wxMenuItem::DeleteSubMenu()
131 {
132 delete m_pSubMenu;
133 m_pSubMenu = NULL;
134 }
135
136 // change item state
137 // -----------------
138
139 void wxMenuItem::Enable(bool bDoEnable)
140 {
141 if ( m_bEnabled != bDoEnable ) {
142 long rc = EnableMenuItem(GetHMenuOf(m_pParentMenu),
143 GetRealId(),
144 MF_BYCOMMAND |
145 (bDoEnable ? MF_ENABLED : MF_GRAYED));
146
147 if ( rc == -1 ) {
148 wxLogLastError("EnableMenuItem");
149 }
150
151 m_bEnabled = bDoEnable;
152 }
153 }
154
155 void wxMenuItem::Check(bool bDoCheck)
156 {
157 wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
158
159 if ( m_bChecked != bDoCheck ) {
160 long rc = CheckMenuItem(GetHMenuOf(m_pParentMenu),
161 GetId(),
162 MF_BYCOMMAND |
163 (bDoCheck ? MF_CHECKED : MF_UNCHECKED));
164
165 if ( rc == -1 ) {
166 wxLogLastError("CheckMenuItem");
167 }
168
169 m_bChecked = bDoCheck;
170 }
171 }
172
173 void wxMenuItem::SetName(const wxString& strName)
174 {
175 // don't do anything if label didn't change
176 if ( m_strName == strName )
177 return;
178
179 m_strName = strName;
180
181 HMENU hMenu = GetHMenuOf(m_pParentMenu);
182
183 UINT id = GetRealId();
184 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
185 if ( flagsOld == 0xFFFFFFFF )
186 {
187 wxLogLastError("GetMenuState");
188 }
189 else
190 {
191 if ( IsSubMenu() )
192 {
193 // high byte contains the number of items in a submenu for submenus
194 flagsOld &= 0xFF;
195 flagsOld |= MF_POPUP;
196 }
197
198 LPCSTR data;
199 #if wxUSE_OWNER_DRAWN
200 if ( IsOwnerDrawn() )
201 {
202 flagsOld |= MF_OWNERDRAW;
203 data = (LPCSTR)this;
204 }
205 else
206 #endif //owner drawn
207 {
208 flagsOld |= MF_STRING;
209 data = strName;
210 }
211
212 if ( ::ModifyMenu(hMenu, id,
213 MF_BYCOMMAND | flagsOld,
214 id, data) == 0xFFFFFFFF )
215 {
216 wxLogLastError("ModifyMenu");
217 }
218 }
219 }
220