OWLNext
7.0
Borland's Object Windows Library for the modern age
Toggle main menu visibility
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
13
namespace
owl
{
14
15
OWL_DIAGINFO
;
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.
165
TMenuDescr::TMenuDescr
()
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
//
178
TMenuDescr::TMenuDescr
(
const
TMenuDescr
& other)
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
//
195
TMenuDescr::TMenuDescr
(
TResId
id
,
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
//
218
TMenuDescr::TMenuDescr
(
TResId
id
,
TModule
* module)
219
:
220
TMenu
(*module, id),
221
Module(module),
222
Id(id)
223
{
224
ExtractGroups
();
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
//
236
TMenuDescr::TMenuDescr
(HMENU hMenu,
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
//
256
TMenuDescr::~TMenuDescr
()
257
{
258
}
259
260
//
261
// Assign another menu descriptor on to this one
262
//
263
TMenuDescr
&
264
TMenuDescr::operator =
(
const
TMenuDescr
& other)
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
//
279
bool
280
TMenuDescr::ExtractGroups
()
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
//
328
bool
329
TMenuDescr::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
//
361
bool
362
TMenuDescr::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
//
388
_OWLCFUNC
(
ipstream
&)
389
operator >>
(
ipstream
& is,
TMenuDescr
& m)
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&)
404
operator <<
(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
owl::TMenuDescr
Menu with information used to allow merging.
Definition
menu.h:206
owl::TMenuDescr::TMenuDescr
TMenuDescr()
Default constructor for a TMenuDescr object.
Definition
menudesc.cpp:165
owl::TMenuDescr::FileGroup
@ FileGroup
Index of the File menu group count.
Definition
menu.h:211
owl::TMenuDescr::ContainerGroup
@ ContainerGroup
Index of the Container menu group count.
Definition
menu.h:213
owl::TMenuDescr::HelpGroup
@ HelpGroup
Index of the Help menu group count.
Definition
menu.h:216
owl::TMenuDescr::NumGroups
@ NumGroups
Total number of groups.
Definition
menu.h:217
owl::TMenuDescr::ObjectGroup
@ ObjectGroup
Index of the Object group count.
Definition
menu.h:214
owl::TMenuDescr::EditGroup
@ EditGroup
Index of the Edit menu group count.
Definition
menu.h:212
owl::TMenuDescr::WindowGroup
@ WindowGroup
Index of the Window menu group count.
Definition
menu.h:215
owl::TMenuDescr::~TMenuDescr
~TMenuDescr()
Definition
menudesc.cpp:256
owl::TMenuDescr::ExtractGroups
bool ExtractGroups()
Extracts the group counts from the loaded menu bar by counting the number of menus between separator ...
Definition
menudesc.cpp:280
owl::TMenuDescr::operator=
TMenuDescr & operator=(const TMenuDescr &original)
Definition
menudesc.cpp:264
owl::TMenuDescr::Merge
bool Merge(const TMenuDescr &sourceMenuDescr)
Merges the functional groups of another menu descriptor into this menu descriptor.
Definition
menudesc.cpp:329
owl::TMenu::GetMenuItemCount
uint GetMenuItemCount() const
Returns the number of items in a top-level or pop-up menu.
Definition
menu.h:395
owl::TMenu::RemoveMenu
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
owl::TMenu::DeleteMenu
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
owl::TMenu::TMenu
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
owl::TMenu::GetMenuState
uint GetMenuState(uint item, uint flags) const
Returns the menu flags for the menu item specified by item.
Definition
menu.h:430
owl::TMenu::DeepCopy
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
owl::TModule
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition
module.h:78
owl::TResId
Definition
wsyscls.h:206
owl::ipstream
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition
objstrm.h:391
owl::NoAutoDelete
@ NoAutoDelete
Definition
gdibase.h:70
pch.h
menu.h
Definition of Window Menu encapsulation class.
module.h
Definition of class TModule.
owl
Object Windows Library (OWLNext Core).
Definition
animctrl.h:22
owl::operator<<
owl::opstream & operator<<(owl::opstream &os, const TColor &c)
Insert the color value into a persistent output stream.
Definition
color.h:498
owl::OWL_DIAGINFO
OWL_DIAGINFO
Definition
animctrl.cpp:14
owl::uint
unsigned int uint
Definition
number.h:25
owl::GetGlobalModule
TModule & GetGlobalModule()
Definition
global.cpp:48
owl::operator>>
owl::ipstream & operator>>(owl::ipstream &is, TColor &c)
Extract the color value from a persistent input stream.
Definition
color.h:489
owl::InternStreamedResId_
auto InternStreamedResId_(TResId id) -> TResId
Definition
strmresid.h:37
_OWLCFUNC
#define _OWLCFUNC(p)
Definition
defs.h:342
STATIC_CAST
#define STATIC_CAST(targetType, object)
Definition
defs.h:271
strmresid.h
Private helper for reading resource identifiers from persistent streams.
source
owlcore
menudesc.cpp
Generated by
1.18.0