OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
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