Here a menu structure that represents the issue... the item text is
irrelevant... these are the command IDs...
1
2------->5
3 6
4 1000
1000
Not sure how that will come across usenet... but the point is... I have a
menu and a submenu. The last item in both the menu and the sub menu is ID
'1000'. I use this shared ID inside my GUI library as a sort of "control
item"... Lets say the main menu is HMENU = 0x1000 and the submenu is HMENU =
0x2000
Anyways... basically ALL menu API functions have a bug with the MF_BYCOMMAND
function...
If I open HMENU = 0x1000 and never even look at HMENU = 0x2000 everything
works as expected... MF_BYCOMMAND(1000) returns the correct item.
BUT if I open the submenu (HMENU = 0x2000) which also has item 1000 in it,
MF_BYCOMMAND will begin returning HMENU = 0x2000's item 1000 regardless of
where I pass in 0x1000 or 0x2000 as the HMENU.
It appears that Windows is internally creating some kind of cache to map the
ID to its internal menu item info. BIG BUG!!! since it doesn't do this for
each HMENU, but rather for an HMENU and ALL its sub menus. Duplicate command
IDs break the cache!
I think the bug is in your program. You are not supposed to have duplicate
menu IDs.
When a menu is clicked, you get a WM_COMMAND message with the LOWORD of
wParam giving the menu identifier. Plainly if you have two menu items with
the same ID, then you will get the same WM_COMMAND message from two
different menu items with no way for your program to figure out which one
has been clicked.
--
John Carson
How is that a bug in *my* code? :) I understand I can't tell the difference
between the two. I don't really care to. ID 1000 is ID 1000 is ID 1000...
Everywhere in my menus that I use ID 1000 it does the same thing: its a
special item that has special handling everywhere to allow the user to
scroll clipped menus.
But the fact that:
GetMenuItemInfo(hMenu1, 1000, MF_BYCOMMAND, &mii);
this call can possibly fill mii with information from item 1000 in hMenu2 is
CLEARLY a bug in the OS.
I'd like to see any documentation anywhere that says I can't have the same
ID in a menu and a submenu. The only limitation is that I can't have it in
the same menu itself.
Also, when I changed my code to work based on MF_BYPOSITION rather then
MF_BYCOMMAND everything works lovely. So its clearly supported.
Then you are not using menus as they were designed to be used. That is OK,
but you are on your own when you do this; don't be surprised if the OS does
things in ways that are unhelpful to you.
> But the fact that:
>
> GetMenuItemInfo(hMenu1, 1000, MF_BYCOMMAND, &mii);
>
> this call can possibly fill mii with information from item 1000 in
> hMenu2 is CLEARLY a bug in the OS.
Not if you are doing something the documentation says you shouldn't.
Note that if you have unique identifiers and have a submenu, then you can
get and set properties for submenu items using the handle for the PARENT
menu --- you don't have to use the submenu handle. This is a further
indication that identifiers are meant to be unique.
> I'd like to see any documentation anywhere that says I can't have the
> same ID in a menu and a submenu. The only limitation is that I can't
> have it in the same menu itself.
I don't have the time to do a thorough search of the documentation, but here
is one section on menus from the MSDN docs:
"Associated with each menu item is a unique, application-defined integer,
called a menu-item identifier. When the user chooses a command item from a
menu, the system sends the item's identifier to the owner window as part of
a WM_COMMAND message. The window procedure examines the identifier to
determine the source of the message, and processes the message accordingly."
The clear implication of this passage is that each menu item should have an
identifier that is unique at least for all menu items that are to be
processed by the same window procedure.
> Also, when I changed my code to work based on MF_BYPOSITION rather
> then MF_BYCOMMAND everything works lovely. So its clearly supported.
It is not supported. If you are using MF_BYPOSITION, then you are not using
the IDs.
--
John Carson
Well, don't dat fill grandmas drawers with nightcrawlers! Thats the first
time I've ever heard of that behavior.
"Nobody" <nob...@cox.net> wrote in message news:eUplg.25$RD.23@fed1read08...
Of course it's a bug, despite the ludicrous claims to the contrary, but
it makes no difference. If pressed Microsoft will no doubt state that
the behavior is 'by design' and there's not the slightest chance they
will change it. So, bug or not, you've got to live with it.
Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
You are talking nonsense. APIs are not psychic, and no programmer should
expect them to be.
Here is the menu structure from the OP
1
2------->5
3 6
4 1000
1000
Lets us suppose instead that the IDs were unique:
1
2------->5
3 6
4 1000
2000
We have two handles, hmenu and hsubmenu. If you call
GetMenuItemInfo(hmenu, 5, MF_BYCOMMAND, &mii);
or
GetMenuItemInfo(hmenu, 6, MF_BYCOMMAND, &mii);
or
GetMenuItemInfo(hmenu, 1000, MF_BYCOMMAND, &mii);
then it will successfully retrieve the desired information, i.e., you can
get submenu information using the handle to the parent menu. That is by
design because it makes life easier: you don't have to iterate along menus
to get the desired submenu handle before you can access a menu item on the
submenu. It is a "flat menu access" model if you like, allowing you access
to every menu item from a single menu handle.
Now revert to the original structure.
1
2------->5
3 6
4 1000
1000
When you call
GetMenuItemInfo(hmenu, 1000, MF_BYCOMMAND, &mii);
how is the OS supposed to resolve the ambiguity? By being psychic of
course!!
The ID structure given above is buggy, plain and simple. No API offering
flat menu access based on IDs can resolve the ambiguity. The code is bad,
the API is fine.
--
John Carson
> <ne...@rtrussell.co.uk> wrote in message
> news:1150790483....@h76g2000cwa.googlegroups.com
>
>>Nobody wrote:
>>
>>>this call can possibly fill mii with information from item 1000 in
>>>hMenu2 is CLEARLY a bug in the OS.
>>
>>Of course it's a bug, despite the ludicrous claims to the contrary,
>>but it makes no difference. If pressed Microsoft will no doubt state
>>that the behavior is 'by design' and there's not the slightest chance
>>they will change it. So, bug or not, you've got to live with it.
>
> [...snip...]
>
> Now revert to the original structure.
>
> 1
> 2------->5
> 3 6
> 4 1000
> 1000
>
> When you call
>
> GetMenuItemInfo(hmenu, 1000, MF_BYCOMMAND, &mii);
>
> how is the OS supposed to resolve the ambiguity? By being psychic of
> course!!
I don't disagree with you as far as duplicating IDs is really bad,
but I do think that the OS could handle this better. This is
probably how it's coded:
For each item in hmenu:
1. If item id == parameter, get that item
2. If item is a popup menu and popup menu is loaded, recurse
This would mean that a duplicate ID somewhere inside a submenu would
be found first, but only if the submenu was higher in the menu (i.e.,
lower position value).
It wouldn't be that hard to iterate exact item ids first and then
go back and recurse through submenus, and it would be a lot more
intuitive for the API caller in cases like this -- it would just
make the code slightly more complex:
For each item in hmenu:
1. If item id == parameter, get that item
For each item in hmenu:
1. If item is a popup menu and popup menu is loaded, recurse
I wouldn't qualify this as a bug in the OS, though, but that doesn't
mean the API couldn't be improved to handle cases like this. (I'd
only count it as a "bug" if you tried to get MF_BYCOMMAND on the
submenu and got the item in the parent menu. Since MF_BYCOMMAND
makes no guarantees on the order it searches, you can't make any
assumptions about which item will be returned. It's a simple rule
of thumb: anything not specified is unspecified.)
> The ID structure given above is buggy, plain and simple. No API offering
> flat menu access based on IDs can resolve the ambiguity. The code is bad,
> the API is fine.
Sure it can resolve the ambiguity. See above. It would then be
incumbent on the programmer to deal with it themselves by passing
the correct HMENU. This is one case where you can have your cake
and eat it too. :)
Of course, if you have duplicate IDs in two submenus and try to use
MF_BYCOMMAND on the parent menu, it wouldn't be able to resolve that
ambiguity... but it would be crazy to do something like that.
David
I'm not expecting the API to be psychic. Of course if you accept that
being able to retrieve sub-menu information by passing only the parent
menu's handle is intentional then the described behaviour follows. But
where in the docs does it say that?
Where else in Windows does automatic recursion into lower levels of a
hierarchy take place whether you want it to or not? Does FindFirstFile
automatically search sub-directories? Does RegOpenKeyEx automatically
search sub-keys?
The behavior of GetMenuItemInfo is anomalous. If it was intentional
then the docs should draw attention to it. If it was accidental but
has subsequently been declared as 'by design' then it's reasonable to
call it a bug.
> That is by
> design because it makes life easier: you don't have to iterate along menus
> to get the desired submenu handle before you can access a menu item on the
> submenu. It is a "flat menu access" model if you like, allowing you access
> to every menu item from a single menu handle.
It doesn't make life easier if hardly anybody knows about it!
> The code is bad, the API is fine.
The code is only bad if that behavior of the API is clearly documented.
Where is that documentation?
In your scheme, the API does not offer flat menu access based on IDs. It
offers flat menu access based on IDs where they are unequal and menu access
based on position in the menu heirarchy where the IDs are equal.
As I have pointed out previously, WM_COMMAND messaging depends on unique
menu IDs by design. It is a flat menu access system which does not offer
scope for supplementation by non-flat access techniques in order to resolve
ambiguities associated with duplicate IDs.
I might also say that a menu access API that depends on the user accurately
predicting the consequences of a particular search algorithm leaves a lot to
be desired in terms of simplicity.
--
John Carson
1. The documentation says that menu IDs are unique. It doesn't say "locally
unique for each submenu". It says unique. That alone is sufficient to enable
the conclusion that anyone using non-unique IDs is in the realm of undefined
behaviour and cannot claim the API is buggy.
2. Your claim about automatic recursion assumes that a hierarchy is the
appropriate way to look at menus. Graphically, that is correct. However, in
terms of the way they send WM_COMMAND messages, there is no hierarchy at
all. The structure is completely flat. Mirroring this, GetMenuItemInfo and
related menu commands offer two methods of access --- "by position" and "by
command". Accessing menu items by position means viewing menus as organised
in a hierarchy. Accessing them by command means viewing them in the same way
as they are treated by WM_COMMAND --- organised in a flat structure.
>> That is by
>> design because it makes life easier: you don't have to iterate along
>> menus to get the desired submenu handle before you can access a menu
>> item on the submenu. It is a "flat menu access" model if you like,
>> allowing you access to every menu item from a single menu handle.
>
> It doesn't make life easier if hardly anybody knows about it!
I very much doubt that "hardly anybody knows about it". I note, for example,
that Rector and Newcomer in their Win32 Programming write: "when a command
ID is specified, the entire menu tree is searched for a menu item that has
the designated menu ID." (pp. 834-5)
If you wish to say that the documentation should be more explicit, then you
won't get an argument from me.
>> The code is bad, the API is fine.
>
> The code is only bad if that behavior of the API is clearly
> documented. Where is that documentation?
You must think a lot of buggy code is just fine. The "by position" or "by
command" option is available for more than a dozen menu commands and, while
I haven't tested all of them, all that I have tested behave the same way.
Sad but true, Windows programming almost invariably involves a certain
amount of testing to resolve doubts about what is expected from the
programmer.
--
John Carson
OK, but I would say there was some 'interpretation' there. Clearly
menu IDs aren't unique in the world (in the way class IDs are) or
unique on a given PC, or unique amongst all running processes. One has
to use a degree of common sense to determine what 'unique' means: I
have always taken it to mean 'unique within a given menu'. I don't
think it is obvious that it should mean 'unique within a given menu and
its submenus'.
> 2. Your claim about automatic recursion assumes that a hierarchy is the
> appropriate way to look at menus. Graphically, that is correct.
It is also correct given the way menus are created. You can even make
the same menu a submenu of two (or more) different parents! That is
hardly consistent with a 'flat' model.
> However, in terms of the way they send WM_COMMAND messages, there is no
> hierarchy at all. The structure is completely flat.
Sure, there must be a unique relationship between a menu ID and the
code it activates, but as the OP pointed out that doesn't necessarily
imply unique IDs - it just implies a given ID always performing the
same task.
> I very much doubt that "hardly anybody knows about it". I note, for example,
> that Rector and Newcomer in their Win32 Programming write: "when a command
> ID is specified, the entire menu tree is searched for a menu item that has
> the designated menu ID." (pp. 834-5)
The "entire menu tree"? Including menus *above* (in the hierarchy) the
one whose handle is passed? You see it really isn't as unambiguous as
you might like to hope.
> If you wish to say that the documentation should be more explicit, then you
> won't get an argument from me.
Great. We agree! If you re-read my original message on the subject,
the point I was making is that it's irrelevant whether it's a bug, a
feature or whatever. It's the way Windows works and we have to live
with it.
Duh... the OS can resolve the "ambiguity" by using the HMENU I gave it...
Lets say the main menu was hMenu1, and the submenu was hMenu2. Lets also say
hMenu2 didn't even have 1000 in it. So I give the os hMenu2 and say give me
1000 and it says ok, I pulled it out of my ass from some random place and
here it is...
Well, thats wrong in my book, because it doesn't even exist in hMenu2.
Maybe the api is doing what its designed for, but its a stupid design. Why
even HAVE submenu handles if the top level menu and all its submenus are
considered a single menu?
Is the menu bar itself all considered a single menu and MF_BYCOMMAND will
find a menu item in the whole damn thing? Oh wait... it'll only find it half
the time, not all the time... sigh... actually not even half the time, but
only when that menu becomes visible.
So basically what the API does is that until the menu containing the ID
becomes visible in the modal loop, MF_BYCOMMAND will fail. Then it'll work
with any hMenu you give it...
Sounds ludicrous.
First time I'd ever heard of it... I'd bet if you asked 1000 developers, and
even gave them the MSDN documentation, they wouldn't in a million years make
an assumption like the way the API is implemented. Unless they'd run into it
like I did.
There is nothing "buggy" about using duplicate IDs since its clearly allowed
by the insert/append APIs, and the Visual Studio IDE menu editor lets me use
duplicate IDs just fine. If using duplicate IDs is bad or illegal, then
these APIs should fail.
You are right: I did forget about WM_COMMAND.
MF_BYCOMMAND also depends on unique menu IDs by design, but it can
be changed so that you can access duplicate IDs in the manner the OP
was trying to use them. Yes, it doesn't work like that now, but I
don't think allowing a "by command" with duplicate IDs would be
*that* big of a problem.
Imagine WM_MENUCOMMAND (sent instead of WM_COMMAND when the menu
has the MNS_NOTIFYBYPOS style) with the command ID instead of the
position. (It's not as though the LPARAM for WM_COMMAND is that
useful anyway.) You said "no API"... it /can/ be done, it just
/isn't/ done.
You may be wondering why I consider this "flat" if we're passing
the HMENU around. To me, flat menu access means you can treat
everything as if it was directly attached to the root menu. Using
this scheme would allow you to ignore the HMENU if you want, thus
acting as though it was in a flat menu, but it can also offer the
capability of resolving duplicates. So, the same API offers both
flat menu access and simultaneously allows duplicate IDs through a
slight extension, exactly what you said "no API" could do.
Of course, all of this is moot since Microsoft isn't going to change
the way it works, but that doesn't mean it's impossible to do, and
it's kinda fun to think about anyway. :)
> I might also say that a menu access API that depends on the user accurately
> predicting the consequences of a particular search algorithm leaves a lot to
> be desired in terms of simplicity.
On the contrary, it would be quite simple both in terms of the API's
implementation and in how the user uses it. You could drop it in
place with virtually no change for existing menus with no duplicates.
Besides, even if it was complex (as is a *lot* of Win32!), that
doesn't necessarily make it /bad/... especially if the end result
is more intuitive. I certainly wouldn't call the menu API "simple"
as it exists today.
David
I agree that some interpretation is required. If you read the documentation
carefully, then I think it is clear that 'unique within a given menu and
its submenus' is implied. But it does require careful reading or, more
convincingly, some experimentation to be sure.
> Sure, there must be a unique relationship between a menu ID and the
> code it activates, but as the OP pointed out that doesn't necessarily
> imply unique IDs - it just implies a given ID always performing the
> same task.
Except that the documentation describing IDs and WM_COMMAND gives no support
for such a practice.
>> I very much doubt that "hardly anybody knows about it". I note, for
>> example, that Rector and Newcomer in their Win32 Programming write:
>> "when a command ID is specified, the entire menu tree is searched
>> for a menu item that has the designated menu ID." (pp. 834-5)
>
> The "entire menu tree"? Including menus *above* (in the hierarchy)
> the one whose handle is passed? You see it really isn't as
> unambiguous as you might like to hope.
The quote continues:
"Hence, even if the menu item you want to modify is in a pop-up menu, or
even a pop-up menu within a pop-up menu, then to perform the operation
successfully you need only the top-level menu handle (usually for the main
window's menu, which you can get with GetMenu)."
--
John Carson
I suspect that at least 500 would get it right (possibly after deciding they
needed to test it to make sure), but we are both speculating without hard
evidence.
> There is nothing "buggy" about using duplicate IDs since its clearly
> allowed by the insert/append APIs, and the Visual Studio IDE menu
> editor lets me use duplicate IDs just fine. If using duplicate IDs is
> bad or illegal, then these APIs should fail.
You should know better. C/C++/Windows let you do all sorts of things that
will cause you problems elsewhere in the program. It is the "trust the
programmer" philosophy.
--
John Carson
But that isn't using a flat access system.
> Lets say the main menu was hMenu1, and the submenu was hMenu2. Lets
> also say hMenu2 didn't even have 1000 in it. So I give the os hMenu2
> and say give me 1000 and it says ok, I pulled it out of my ass from
> some random place and here it is...
>
> Well, thats wrong in my book, because it doesn't even exist in hMenu2.
That isn't how it works. The menu item must exist in the menu for which you
have the handle or in a submenu leading from it (directly or indirectly).
The menu item can't exist in a parent menu.
> Maybe the api is doing what its designed for, but its a stupid
> design. Why even HAVE submenu handles if the top level menu and all
> its submenus are considered a single menu?
They are not considered a single menu for all purposes, only for some. For
the particular task of accessing menu items, you are given a choice. You can
access menu items by position or by command. Submenu handles are relevant
for doing things by position. On the other hand, when you access menu items
by command, with a single top-level menu handle you can access all menu
items on that menu or its submenus (direct or indirect). For 99.99% of
menus, that is very convenient, even if it causes trouble for the 0.01% of
menus like yours.
> Is the menu bar itself all considered a single menu and MF_BYCOMMAND
> will find a menu item in the whole damn thing? Oh wait... it'll only
> find it half the time, not all the time... sigh... actually not even
> half the time, but only when that menu becomes visible.
>
> So basically what the API does is that until the menu containing the
> ID becomes visible in the modal loop, MF_BYCOMMAND will fail. Then
> it'll work with any hMenu you give it...
That is not what I see. I suspect you may be seeing artifacts of your own
menu system. I have:
Menu bar
Popup menu
Submenu of popup
The ID of the first item on Submenu of popup is ID_SUBMENU_ITEMA and I put
the following code in WM_CREATE processing before the window itself appears,
much less any menu.
HMENU hmenu = GetMenu(hwndFrame); // handle to menu bar
EnableMenuItem(hmenu, ID_SUBMENU_ITEMA,
MF_BYCOMMAND | MF_GRAYED);
This works. When I subsequently open the menu, the first time on the submenu
of the popup is grayed out.
--
John Carson
This is a purely semantic dispute. By "flat access" I mean "only flat
access". By "flat access" you mean "allows for flat access with distinct IDs
and non-flat access with duplicate IDs".
Win32 offers a flat memory access model, which means that each distinct
piece of memory must have a distinct address (which is why, for example, an
empty struct must have a positive size). Distinct IDs and distinct memory
addresses involve the same principle. Resolving duplicates is a complication
best avoided.
>> I might also say that a menu access API that depends on the user
>> accurately predicting the consequences of a particular search
>> algorithm leaves a lot to be desired in terms of simplicity.
>
> On the contrary, it would be quite simple both in terms of the API's
> implementation and in how the user uses it. You could drop it in
> place with virtually no change for existing menus with no duplicates.
I think that it substantially complicates the interface in order to benefit
approximately zero percent of users.
> Besides, even if it was complex (as is a *lot* of Win32!), that
> doesn't necessarily make it /bad/... especially if the end result
> is more intuitive. I certainly wouldn't call the menu API "simple"
> as it exists today.
All that is needed is for the documentation to be a little more explicit on
what access "by command" means. Expecting people to analyse search orders
(or even expecting people to make the determination that they do not NEED to
analyse search orders because their IDs are distinct) does not make things
more intuitive, just more complicated.
--
John Carson
For "the first time on the submenu" read "the first ITEM on the submenu".
--
John Carson
I had no idea there was anyone who believed they could have two menu
selections with the same menu ID. I, personally, never assumed for even a
moment that it would be possible. But, I am only one person.
> There is nothing "buggy" about using duplicate IDs since its clearly
> allowed by the insert/append APIs, and the Visual Studio IDE menu editor
> lets me use duplicate IDs just fine. If using duplicate IDs is bad or
> illegal, then these APIs should fail.
You should never assume that anything is OK just because the Win32 API
doesn't complain. Imagine how slow the Win32 API would be if it had to
check everything to catch programmer bugs? Ouch. (Windows would have not
succeeded for us to be here discussing it.)
I do agree it would be nice if it did perform lots of checks, for learning
purposes. I also agree that MSDN could be improved in many ways.
Also, the Visual Studio resource editor is very much a thrown-together
product. It replicates hardly any of normal Windows UI (anything beyond the
basics), and it messes things up all the time, if you don't use it in just
the way it wants to be used. I do not trust it as far as I can throw it,
and I am constantly editing the files manually to ensure things are ok. So,
please, do not use it's lack of complaints for any judging purposes.
--
Jason Doucette / Xona.com
www.jasondoucette.com / www.xona.com
This is certainly needed for flat memory access, but is actually also needed
for some forms of non-flat memory access.
--
John Carson
> This is a purely semantic dispute. By "flat access" I mean "only flat
> access". By "flat access" you mean "allows for flat access with distinct IDs
> and non-flat access with duplicate IDs".
Fair enough. Though, by that definition, the Win32 menu API wouldn't
count since you can use something other than "flat" access and thus be
able to use duplicate IDs - MF_BYPOSITION.
But, then again, that's just more semantics. ;-)
> Win32 offers a flat memory access model, which means that each distinct
> piece of memory must have a distinct address (which is why, for example, an
> empty struct must have a positive size). Distinct IDs and distinct memory
> addresses involve the same principle. Resolving duplicates is a complication
> best avoided.
Actually, that's a poor example to support your position. The same
piece of memory can be mapped at multiple addresses, both in terms
of using different selectors (i.e., fs:[0]) and in the same selector
(through paging manipulation).
"Flat" in this case just means that, unlike 16-bit code, you don't
/normally/ have to worry about your segment/selector value, but in
some cases you do -- such as SEH using fs:[0] as I mentioned above.
This is exactly the same as the "flat" menu access I was discussing -
in the average case, you don't need to worry about it, but in some
cases you might.
As an aside, 16-bit / segmented memory models would allow negatively
sized structs? I don't see how your struct statement follows from
the memory model.
Moreover, I would disagree that it's a complication best avoided.
If you can simply extend functionality to cover a broader set of
cases, why should this be avoided, especially when the change is
as trivial as this one? Avoiding complications at all costs is
just as bad as adding needless features at all costs. In this
case, the benefits are arguable, sure, but the costs are also low.
David
And why wouldn't you be able to? FYI... Microsoft doesn't seem to believe
this as they have duplicate menu items in some of their products.
And the fact that duplicate menu item IDs work just fine until you use the
MF_BYCOMMAND flag says that too...
Hmmm... Microsoft Office supports duplicate menu ids in the same damn
menu... well what do you know...
I didn't say I wouldn't be able to. The reason I never assumed this would
be possible is because the documentation states that menu IDs should be
unique, and some of the Win32 API functions demand this be the case.
> And the fact that duplicate menu item IDs work just fine until you use the
> MF_BYCOMMAND flag says that too...
No, it doesn't 'say' that, too. John Carson has done a great job clearly
explaining this.
All this 'says' is that duplicate menu item IDs work fine until you use a
Win32 API function that demands them be unique. Of course... how could it
be any other way? Does every function in the Win32 API need to error check
information it does not use? Of course, not. That is why when a Win32 API
function fails to complain, it does not mean all is well. It just means it
does not care about any information than what it need to get IT'S job done,
regardless if the rest of the structure is falling to pieces.
Now, I have now explained this twice. No further.
> Hmmm... Microsoft Office supports duplicate menu ids in the same damn
> menu... well what do you know...
Microsoft uses undocumented behaviour in a lot of its products. If you have
ever tried to make child windows look active when the main window is active,
you would see a classic case of this. Microsoft knows the code behind the
Win32 API, and therefore, knows what it can get away with. You don't. So
play safe.
http://www.google.com/search?q=site%3Ablogs.msdn.com+undocumented
Within an application's virtual address space, each object is at a unique
memory address. How physical memory is mapped into the application's address
space isn't something the application normally needs to worry about. The
whole point of a decent API is that it hides unnecessary complexity. You
seem to delight in revealing complexity.
> As an aside, 16-bit / segmented memory models would allow negatively
> sized structs? I don't see how your struct statement follows from
> the memory model.
The distinction is between zero-sized and positive-sized structs. If a
struct is zero-sized, then you can have two struct objects at the same
address. As I pointed out in an addendum, even non-flat memory models want
to exclude that. The point is simply that non-unique locators (whether
addresses, IDs or whatever) that necessitate a second step to disambiguate
them are a pain in the neck. That is why each window has a unique
handle...and each person has a unique social security number.
> Moreover, I would disagree that it's a complication best avoided.
> If you can simply extend functionality to cover a broader set of
> cases, why should this be avoided, especially when the change is
> as trivial as this one? Avoiding complications at all costs is
> just as bad as adding needless features at all costs. In this
> case, the benefits are arguable, sure, but the costs are also low.
The cost is not just in terms of writing the code; it is in documenting the
API and having the user understand it and remember it. Telling the user to
use a top level menu handle plus an ID is trivial. Explaining how the thing
works with duplicate IDs is less trivial. Moreover, you are increasing the
likelihood that users will adopt bad practices. Almost no users have a
reason to use duplicate IDs and you shouldn't be muddying the waters by
talking about it. If 1 in a million users wants multiple menu items to do
the same thing, then the 1 in a million user can write code that works
around the API (by, e.g., processing distinct menu items in the same way). I
think it is a really bad idea to complicate the API for the benefit of
almost non-existent users.
--
John Carson
"Jason Doucette" <www.jasondoucette.com> wrote in message
news:OPp7VEOl...@TK2MSFTNGP03.phx.gbl...
What is undocumented is the fact that lParam of WM_NCACTIVATE is actually
used, contrary to what the documentation says.
http://www.catch22.net/tuts/docking1.asp
--
John Carson
> "David Jones" <nc...@tadmas.com> wrote in message
> news:002mg.49317$ZW3.21096@dukeread04
>
>>John Carson wrote:
>>
>>
>>>Win32 offers a flat memory access model, which means that each
>>>distinct piece of memory must have a distinct address (which is why,
>>>for example, an empty struct must have a positive size). Distinct
>>>IDs and distinct memory addresses involve the same principle.
>>>Resolving duplicates is a complication best avoided.
>>
>>Actually, that's a poor example to support your position. The same
>>piece of memory can be mapped at multiple addresses, both in terms
>>of using different selectors (i.e., fs:[0]) and in the same selector
>>(through paging manipulation).
>
>
> Within an application's virtual address space, each object is at a unique
> memory address. How physical memory is mapped into the application's address
> space isn't something the application normally needs to worry about. The
> whole point of a decent API is that it hides unnecessary complexity. You
> seem to delight in revealing complexity.
And you seem to delight in shouting it down. In non-flat memory
models, objects are also at a unique memory address. In 16-bit
x86, segment+offsets are not unique, but that has nothing to do
with the memory *model* -- it's a hardware quirk. You can have a
segmented architecture with unique addresses. The advantage of the
flat memory model is that you don't need to worry about the segment
register since they are all set the same. But, even in a flat
model, the segment is still part of the full memory address.
I also notice that you said "normally needs to worry about"...
this is exactly my point. You normally don't need to worry about
segments/selectors in a flat memory model, but sometimes you do.
It's the common case that matters, not the exception, but that
doesn't mean you should support *only* the common case.
And a good API isn't necessarily simple. A good API allows you
to accomplish what you need to do. Look at CreateProcess -- I
think this is a good API. It's actually pretty complex, but if
you don't need a lot of the complexity, you can ignore most of
the arguments. With this change to menus, you can ignore the
MF_BYCOMMAND differences if you want and just deal with all the
menus as perfectly flat. Same thing.
>>As an aside, 16-bit / segmented memory models would allow negatively
>>sized structs? I don't see how your struct statement follows from
>>the memory model.
>
>
> The distinction is between zero-sized and positive-sized structs. If a
> struct is zero-sized, then you can have two struct objects at the same
> address. As I pointed out in an addendum, even non-flat memory models want
> to exclude that. The point is simply that non-unique locators (whether
> addresses, IDs or whatever) that necessitate a second step to disambiguate
> them are a pain in the neck. That is why each window has a unique
> handle...and each person has a unique social security number.
Um, ok, I didn't think about zero-byte structs. You certainly
don't want those at the same address since you might store pointers
to them and accidentally misread the wrong zero bytes of data.
Or maybe zero-byte structs aren't used because they're pointless
without any regard to whether they take up the same address.
Yeah, non-unique locators are pretty bad. The real question is
your definition of unique. Some handles are not unique across a
process boundary, so you have these handles implicitly paired with
the process ID. Segmented memory addresses are not unique, unless
paired with a segment value. Menu command IDs are not unique across
a process unless paired with an HMENU (or HWND). And I'm suggesting
pairing the menu command ID with an HMENU -- it won't deal with
duplicate IDs in the same menu, but it will allow you to disambiguate
duplicate IDs between menus by providing a piece of information
you're *already* providing -- the HMENU. It would basically allow
MF_BYPOSITION-style access using MF_BYCOMMAND. How inconvenient!
What a pain in the neck!
>>Moreover, I would disagree that it's a complication best avoided.
>>If you can simply extend functionality to cover a broader set of
>>cases, why should this be avoided, especially when the change is
>>as trivial as this one? Avoiding complications at all costs is
>>just as bad as adding needless features at all costs. In this
>>case, the benefits are arguable, sure, but the costs are also low.
>
>
> The cost is not just in terms of writing the code; it is in documenting the
> API and having the user understand it and remember it. Telling the user to
> use a top level menu handle plus an ID is trivial.
And telling them to use a submenu handle plus an ID is rocket science?
> Explaining how the thing works with duplicate IDs is less trivial.
No, it would be a blurb like "The function will match an item in the
specified hMenu before searching submenus, so you must specify the
correct submenu handle if command IDs are not unique across the
entire menu." If you mean less trivial in the sense that it would
have more information, ok, sure, but only slightly less trivial.
It wouldn't have to go into excruciating detail -- only enough to
explain the effect it will have on the caller.
> Moreover, you are increasing the
> likelihood that users will adopt bad practices. Almost no users have a
> reason to use duplicate IDs and you shouldn't be muddying the waters by
> talking about it. If 1 in a million users wants multiple menu items to do
> the same thing, then the 1 in a million user can write code that works
> around the API (by, e.g., processing distinct menu items in the same way).
It's only a bad practice if you're using it incorrectly. This thread
clearly states that MF_BYCOMMAND does *not* distinguish between
duplicate IDs and can pick any item arbitrarily. If someone reads
this and then thinks duplicate IDs (while still using WM_COMMAND and
MF_BYCOMMAND) is a good idea, no amount of dissuading them would have
worked anyway.
In many ways, I don't disagree with you here, though. People should
NOT use my comments to code menus based on the current API since it
doesn't work the way I'm suggesting it could. That having been said,
is a theoretical discussion such a bad thing? I only remarked on it
originally since you said that it was impossible, which it's not.
> I think it is a really bad idea to complicate the API for the benefit of
> almost non-existent users.
"Complicating the API" is a cost/benefit tradeoff. You're saying
that benefits are low (which I said in my previous post!) and I'm
saying that costs are low. To me, it seems about even. It's a
trivial change that would help, as you put it, one in a million
users. In cases like this, functionality wins for me every time.
You may not always need it, but boy it sure is nice when you do.
David
A struct can have no data members but still have functions. Such structs are
not pointless and would ordinarily have a sizeof zero, but the C++ standard
(section 9/3) states that "Complete objects and member subobjects of class
type shall have nonzero size." This is simply so different objects always
have different addresses.
> And telling them to use a submenu handle plus an ID is rocket science?
Apparently people can't understand the existing API. The most important
problem in computer programming is that programmers make mistakes. You seem
to give this little weight. The more information there is in an explanation,
the more likely programmers are to misunderstand the explanation because,
for example, they read it quickly and skip over important details. It
happens a million times a week (usually corrected before too much damage is
done, but not always and not always quickly).
> No, it would be a blurb like "The function will match an item in the
> specified hMenu before searching submenus, so you must specify the
> correct submenu handle if command IDs are not unique across the
> entire menu."
Uh huh. A little terse if I might say so. What do you mean by "correct
submenu handle"? And am I right to infer from your instructions that it is
OK to use an "incorrect" submenu handle if IDs are unique? What if IDs are
non-unique on a single popup menu? Is that OK provided the "correct" submenu
handle is used? In what order does the function search submenus? Oh, and by
the way, how does WM_COMMAND processing handle the case of duplicate IDs?
These questions are somewhat tongue in cheek, but the point is
real; you are not going to get away with a one sentence description
or anything like it.
Ultimately, you have to draw the line somewhere in terms of the complexity
of the API and the thoroughness of its documentation. I draw the line at
providing features that are useless to almost everyone and of only slight
use to the remainder.
>> Moreover, you are increasing the
>> likelihood that users will adopt bad practices. Almost no users have
>> a reason to use duplicate IDs and you shouldn't be muddying the
>> waters by talking about it. If 1 in a million users wants multiple
>> menu items to do the same thing, then the 1 in a million user can
>> write code that works around the API (by, e.g., processing distinct
>> menu items in the same way).
>
> It's only a bad practice if you're using it incorrectly. This thread
> clearly states that MF_BYCOMMAND does *not* distinguish between
> duplicate IDs and can pick any item arbitrarily. If someone reads
> this and then thinks duplicate IDs (while still using WM_COMMAND and
> MF_BYCOMMAND) is a good idea, no amount of dissuading them would have
> worked anyway.
But in your scheme it is declared that duplicate IDs are OK or at least
there is no statement that they must be unique. I can't help but think that
this will increase the use of non-unique IDs by people who should be using
unique IDs. Presumably you think that the documentation should include a
discussion of when to use unique IDs and when not to. Reading and digesting
this is no doubt a valuable way for programmers to spend their time.
At the end of the day, the change you propose would not make the sky fall
in. However, if I were on a committee deciding these matters, I would vote
against it.
--
John Carson