OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
menudesc.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1991, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of class TMenuDescr
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9#include <owl/menu.h>
10#include <owl/module.h>
11
12namespace owl {
13
15
16/// \class TMenuDescr
17/// Derived from TMenu, TMenuDescr describes your menu bar and its functional
18/// groups. TMenuDescr provides an easy way for you to group menus on your menu bar
19/// and to add new groups to an existing menu bar. It uses a resource ID to identify
20/// the menu resource and an array of count values to indicate the number of pop-up
21/// menus in each group on the menu bar.
22///
23/// The TGroup enum enumerates the six basic functional groups on a menu bar: File,
24/// Edit, Container, Object, Window, and Help. TMenuDescr's constructors simply
25/// initialize the members based on the arguments passed.
26///
27/// TFrameWindow::MergeMenu actually performs the real work of merging the menu
28/// groups.
29///
30/// For a single document application (SDI), the menus are merged as soon as you
31/// load the application. However, for a multiple-document application (MDI), you do
32/// not see the final menu until you invoke a child menu. See the sample program,
33/// mdifile.cpp, for an example of MDI menu merging.
34///
35/// One technique you can use to create a menu involves invoking the TMenuDescr
36/// constructor and passing the number of group counts for each menu selection.
37///
38/// For example, if your original menu groups included these items:
39/// \image html bm78.BMP
40/// you might use the following group counts:
41///
42/// <TABLE class="owltable">
43/// <TR class="owltable"><TH class="owltableheader">Group</TH><TH class="owltableheader">Count</TH><TH class="owltableheader">Menu</TH></TR>
44/// <TR class="owltable"><TD class="owltable">FileGroup</TD><TD class="owltable">1</TD><TD class="owltable">File</TD></TR>
45/// <TR class="owltable"><TD class="owltable">EditGroup</TD><TD class="owltable">2</TD><TD class="owltable">Edit Search</TD></TR>
46/// <TR class="owltable"><TD class="owltable">ContainerGroup</TD><TD class="owltable">1</TD><TD class="owltable">View</TD></TR>
47/// <TR class="owltable"><TD class="owltable">ObjectGroup</TD><TD class="owltable">3</TD><TD class="owltable">Page Paragraph Word</TD></TR>
48/// <TR class="owltable"><TD class="owltable">WindowGroup</TD><TD class="owltable">1</TD><TD class="owltable">Window</TD></TR>
49/// <TR class="owltable"><TD class="owltable">HelpGroup</TD><TD class="owltable">1</TD><TD class="owltable">Help</TD></TR>
50/// </TABLE>
51///
52/// You would then invoke the constructor this way:
53/// \code
54/// TMenuDescr(IDM_MYMENU, 1, 2, 1, 3, 1, 1)
55/// \endcode
56/// You can build the previous menu by merging two menus. When a zero is passed in
57/// the parent menu's constructor, the group indicated by the zero is filled in by
58/// the child menu's group, if an item is specified, when the menu merging occurs.
59/// Set your application's parent frame menu bar by specifying these menu groups:
60/// \image html bm79.BMP
61/// and passing these group counts in the constructor:
62/// \code
63/// TMenuDescr(IDM_FRAME, 1, 0, 1, 0, 1, 1)
64/// \endcode
65/// Set the word-processor child menu bar this way:
66/// \image html bm80.BMP
67/// and pass these values in the constructor:
68/// \code
69/// TMenuDescr(IDM_WPROC, 0, 2, 0, 3, 0, 1)
70/// \endcode
71/// If no child is active, only the frame menu will be active. When the word
72/// processor's child window becomes active, the child menu bar is merged with the
73/// frame menu. Every group that is 0 in the child menu bar leaves the parent's
74/// group intact. The previous example interleaves every group except for the last
75/// group, the Help group, in which the child replaces the frame menu.
76///
77/// By convention, the even groups (File, Container, Window) usually belong to the
78/// outside frame or container, and the odd groups (Edit, Object, Help) belong to
79/// the child or contained group.
80///
81/// If a -1 is used in a group count, the merger eliminates the parent's group
82/// without replacing it. For example, another child menu bar, such as a calculator,
83/// could be added to your application in this way:
84/// \image html bm81.BMP
85/// \code
86/// TMenuDescr(IDM_WCALC, 0, 1, -1, 1, 0, 1)
87/// \endcode
88/// In this example, the child's menu group contributes nothing from the container
89/// group, and the parent's container group is removed. This produces a merged menu
90/// (with the View menu selection eliminated as a result of the -1) that looks like
91/// this:
92/// \image html bm82.BMP
93///
94/// If you want to merge the following parent menu groups
95/// \image html bm79.BMP
96/// with these paint window menu groups,
97/// \image html bm83.BMP
98/// pass the following group counts in the constructor:
99/// \code
100/// TMenuDescr(IDM_WPAINT, 0, 1, 0, 2, 0, 1)
101/// \endcode
102/// This produces the following merged menu:
103/// \image html bm84.BMP
104///
105/// The simplest way to add groups to a menu bar involves defining the menu groups
106/// and adding separators in a resource file. Insert the term MENUITEM SEPARATOR
107/// between each menu group and an additional separator if one of the menu groups is
108/// not present. For example, the resource file for Step 14 of the ObjectWindows
109/// tutorial defines the following menu groups and separators:
110/// \code
111/// IDM_MDICMNDS MENU
112/// {
113/// // Display a grayed File menu
114/// MENUITEM "File", 0,GRAYED ;placeholder for File menu from DocManager
115/// MENUITEM SEPARATOR
116/// MENUITEM "Edit", CM_NOEDIT ;placeholder for Edit menu from View
117/// MENUITEM SEPARATOR
118/// MENUITEM SEPARATOR
119/// MENUITEM SEPARATOR
120/// POPUP "&Window"
121/// {
122/// // Options within the Window menu group
123/// MENUITEM "&Cascade", CM_CASCADECHILDREN
124/// MENUITEM "&Tile", CM_TILECHILDREN
125/// MENUITEM "Arrange &Icons", CM_ARRANGEICONS
126/// MENUITEM "C&lose All", CM_CLOSECHILDREN
127/// MENUITEM "Add &View", CM_VIEWCREATE
128/// }
129/// MENUITEM SEPARATOR
130/// POPUP "&Help"
131/// {
132/// MENUITEM "&About", CM_ABOUT
133/// }
134/// }
135/// \endcode
136/// You can see the separators by loading Step14.rc into Resource Workshop and
137/// disabling the View as Popup Option in the View menu. This resource file defines
138/// an Edit group, a File group, a Window group, and a Help group, but no entries
139/// for Container or Object groups.
140/// Step14.cpp uses these commands from the resource file to set the main window and
141/// its menu, passing IDM_MDICMNDS as the parameter to SetMenuDescrfunction, as
142/// follows:
143/// \code
144/// SetMainWindow(frame);
145/// GetMainWindow()->SetMenuDescr(TMenuDescr(IDM_MDICMNDS));
146/// \endcode
147/// It produces the following menu groups:
148/// \image html bm85.BMP
149///
150/// TMenuDescr's functions let you perform menu merging similar to that of OLE 2.
151/// That is, you can merge menus from a container's document (the MDI frame window)
152/// with those of an embedded object (the MDI child window). When the embedded
153/// object is activated in place by double-clicking the mouse, the menu of the child
154/// window merges with that of the frame window.
155
156
157
158
159//
160// Construct a default, empty menu descriptor
161//
162/// Default constructor for a TMenuDescr object. No menu resources or groups are
163/// specified. Constructs an empty menu bar.
165:
166 TMenu()
167{
168 Id = 0;
169 Module = &GetGlobalModule();
170 for (int i = 0; i < NumGroups; i++)
171 GroupCount[i] = 0;
172}
173
174//
175/// Copies the menu descriptor object specified in the other parameter.
176//
178:
179 TMenu(other)
180{
181 Id = other.Id;
182 Module = other.Module;
183 for (int i = 0; i < NumGroups; i++)
184 GroupCount[i] = other.GroupCount[i];
185}
186
187//
188/// Constructs a menu descriptor from the resource indicated by id. Places the
189/// pop-up menus in groups according the values of the fg, eg, cg, of, wg, and hg
190/// parameters. The fg, eg, cg, of, wg, and hg parameters represent the functional
191/// groups identified by the TGroup enum. Calls the function ExtractGroups to
192/// extract the group counts based on the separator items in the menu bar.
193//
195 int fg, int eg, int cg, int og, int wg, int hg,
196 TModule* module)
197:
198 TMenu(*module, id),
199 Module(module),
200 Id(id)
201{
202 if (!ExtractGroups()) {
203 GroupCount[FileGroup] = fg;
204 GroupCount[EditGroup] = eg;
205 GroupCount[ContainerGroup] = cg;
206 GroupCount[ObjectGroup] = og;
207 GroupCount[WindowGroup] = wg;
208 GroupCount[HelpGroup] = hg;
209 }
210}
211
212//
213/// Creates a menu descriptor from the menu resource specified in the id parameter.
214/// Calls the function ExtractGroups to extract the group counts based on the
215/// separator items in the menu bar.
216//
218:
219 TMenu(*module, id),
220 Module(module),
221 Id(id)
222{
224}
225
226//
227/// Constructs a menu descriptor from the menu handle indicated in the hMenu
228/// parameter. The menu descriptor can have zero or more pop-up menus in more than
229/// one functional group. The fg, eg, cg, of, wg, and hg parameters represent the
230/// functional groups identified by the TGroup enum. Calls the function
231/// ExtractGroups to extract the group counts based either on the separator items in
232/// the menu bar or on the group count parameters specified if there are no
233/// separators in the menu bar.
234//
236 int fg, int eg, int cg, int og, int wg, int hg,
237 TModule* module)
238:
240 Module(module)
241{
242 if (!ExtractGroups()) {
243 GroupCount[FileGroup] = fg;
244 GroupCount[EditGroup] = eg;
245 GroupCount[ContainerGroup] = cg;
246 GroupCount[ObjectGroup] = og;
247 GroupCount[WindowGroup] = wg;
248 GroupCount[HelpGroup] = hg;
249 }
250}
251
252//
253// destructor
254//
258
259//
260// Assign another menu descriptor on to this one
261//
264{
265 *STATIC_CAST(TMenu*,this) = *STATIC_CAST(const TMenu*,&other);
266 Id = other.Id;
267 Module = other.Module;
268 for (int i = 0; i < NumGroups; i++)
269 GroupCount[i] = other.GroupCount[i];
270 return *this;
271}
272
273//
274/// Extracts the group counts from the loaded menu bar by counting the number of
275/// menus between separator items. After the group counts are extracted, the
276/// separators are removed.
277//
278bool
280{
281 if (!Handle)
282 return false; // no menu to extract from...
283
284 // walk menu & remove separators, setting up count as we go.
285 //
286 int itemCount = GetMenuItemCount();
287 int g = 0;
288 int count = 0;
289 for (int i = 0; i < itemCount; ) {
291 if ((s & MF_SEPARATOR) && !(s & MF_POPUP)) {
292 if (g < NumGroups)
293 GroupCount[g++] = count;
294 count = 0;
296 itemCount--;
297 }
298 else {
299 i++;
300 count++;
301 }
302 }
303 // Leave if no separators were found
304 //
305 if (!g)
306 return false;
307
308 // Get trailing group
309 //
310 if (g < NumGroups)
311 GroupCount[g++] = count;
312
313 // Finish zeroing groups
314 //
315 for (; g < NumGroups; g++)
316 GroupCount[g] = 0;
317 return true;
318}
319
320//
321/// Merges the functional groups of another menu descriptor into this menu
322/// descriptor.
323///
324/// Popups are DeepCopied and are then owned by this menu
325/// Group counts are merged too.
326//
327bool
329{
330 int thisOffset = 0;
331 int srcOffset = 0;
332
333 for (int i = 0; i < NumGroups; i++) {
334 if (srcMenuDescr.GroupCount[i] != 0) {
335 // Delete same menu group in the dest. menudescr.
336 for (int j = GroupCount[i] - 1; j >= 0; j--) {
338 }
339 GroupCount[i] = 0;
340
341 if (srcMenuDescr.GroupCount[i] > 0) {
343 srcOffset += srcMenuDescr.GroupCount[i];
344 GroupCount[i] += srcMenuDescr.GroupCount[i];
345 }
346 }
347
348 if (GroupCount[i] > 0)
349 thisOffset += GroupCount[i];
350 }
351 return true;
352}
353
354//
355/// Merges the functional groups of this menu descriptor and another menu descriptor
356/// into an empty menu.
357///
358/// Popups are DeepCopied and are then owned by the destMenu.
359//
360bool
362{
363 int thisOffset = 0;
364 int srcOffset = 0;
365
366 for (int i = 0; i < NumGroups; i++) {
367 if (srcMenuDescr.GroupCount[i] > 0) {
369 srcOffset += srcMenuDescr.GroupCount[i];
370 }
371 else if (srcMenuDescr.GroupCount[i] == 0 && GroupCount[i] > 0) {
372 DeepCopy(dstMenu, *this, thisOffset, GroupCount[i]);
373 }
374 // else don't copy either
375
376 if (GroupCount[i] > 0)
377 thisOffset += GroupCount[i];
378 }
379 return true;
380}
381
382
383#if OWL_PERSISTENT_STREAMS
384//
385// Extract the menu descriptor from the persistent stream.
386//
389{
390 is >> m.Id;
391 is >> m.Module;
392 for (int i = 0; i < TMenuDescr::NumGroups; i++)
393 is >> m.GroupCount[i];
394 return is;
395}
396
397//
398// Insert the menu descriptor into the persistent stream.
399//
400_OWLCFUNC(opstream&)
401operator <<(opstream& os, const TMenuDescr& m)
402{
403 os << m.Id;
404 os << m.Module;
405 for (int i = 0; i < TMenuDescr::NumGroups; i++)
406 os << m.GroupCount[i];
407 return os;
408}
409
410#endif
411
412
413} // OWL namespace
414/* ========================================================================== */
415
Menu with information used to allow merging.
Definition menu.h:206
TMenuDescr()
Default constructor for a TMenuDescr object.
Definition menudesc.cpp:164
@ FileGroup
Index of the File menu group count.
Definition menu.h:211
@ ContainerGroup
Index of the Container menu group count.
Definition menu.h:213
@ HelpGroup
Index of the Help menu group count.
Definition menu.h:216
@ NumGroups
Total number of groups.
Definition menu.h:217
@ ObjectGroup
Index of the Object group count.
Definition menu.h:214
@ EditGroup
Index of the Edit menu group count.
Definition menu.h:212
@ WindowGroup
Index of the Window menu group count.
Definition menu.h:215
bool ExtractGroups()
Extracts the group counts from the loaded menu bar by counting the number of menus between separator ...
Definition menudesc.cpp:279
TMenuDescr & operator=(const TMenuDescr &original)
Definition menudesc.cpp:263
bool Merge(const TMenuDescr &sourceMenuDescr)
Merges the functional groups of another menu descriptor into this menu descriptor.
Definition menudesc.cpp:328
The TMenu class encapsulates window menus.
Definition menu.h:77
uint GetMenuItemCount() const
Returns the number of items in a top-level or pop-up menu.
Definition menu.h:395
bool RemoveMenu(uint item, uint flags)
Removes the menu item from the menu but does not delete it if it is a submenu.
Definition menu.h:500
bool DeleteMenu(uint item, uint flags)
Removes the menu item (item) from the menu or deletes the menu item if it's a pop-up menu.
Definition menu.h:375
uint GetMenuState(uint item, uint flags) const
Returns the menu flags for the menu item specified by item.
Definition menu.h:430
static void DeepCopy(TMenu &dst, const TMenu &src, int srcOffset=0, int itemCount=-1)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition menu.cpp:338
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:75
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
@ NoAutoDelete
Definition gdibase.h:70
Definition of Window Menu encapsulation class.
Definition of class TModule.
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
owl::opstream & operator<<(owl::opstream &os, const TColor &c)
Insert the color value into a persistent output stream.
Definition color.h:498
TModule * Module
Definition global.cpp:34
OWL_DIAGINFO
Definition animctrl.cpp:14
TModule & GetGlobalModule()
Definition global.cpp:48
owl::ipstream & operator>>(owl::ipstream &is, TColor &c)
Extract the color value from a persistent input stream.
Definition color.h:489
#define _OWLCFUNC(p)
Definition defs.h:342
#define STATIC_CAST(targetType, object)
Definition defs.h:271