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