Discussion:
How to assign unique message codes and resource IDs?
(too old to reply)
Woody
2011-07-07 07:28:10 UTC
Permalink
I'm using someone's customized CListCtrl code. The code is in a static
library, which I link w/my apps. I have two "uniqueness" problems, for
which I'd like advice.

1) The control sends a message to the parent dialog under certain
circumstances. How can I be sure the message code is unique? If it is
compiled into the library, an app which defines its own message codes
may conflict.

2) The control creates edit controls dynamically. How can I assign a
unique resource ID to each control, that will not conflict with the
IDs of the other controls in the parent dialog, or doesn't this matter.
David Lowndes
2011-07-07 07:50:47 UTC
Permalink
Post by Woody
1) The control sends a message to the parent dialog under certain
circumstances. How can I be sure the message code is unique? If it is
compiled into the library, an app which defines its own message codes
may conflict.
Decide on a unique string (use a GUID) and use RegisterWindowMessage
at both ends.
Post by Woody
2) The control creates edit controls dynamically. How can I assign a
unique resource ID to each control, that will not conflict with the
IDs of the other controls in the parent dialog, or doesn't this matter.
It doesn't matter - uniqueness of control IDs is only usually relevant
on the same dialog (parent).

Dave
Woody
2011-07-07 19:23:05 UTC
Permalink
Post by David Lowndes
Decide on a unique string (use a GUID) and use RegisterWindowMessage
at both ends.
OK, I have done this, with a global variable in the library and a
differently-named global variable in the app's dialog. Both
RegisterWindowMessage have the same string arg, and both return the
same value.

Although the library is sending the message to the dialog using
SendMessage, the dialog is not receiving the message.

I suspect this has something to do with how the message map is set up
in the MFC dialog.

I have
UINT m1=RegisterWindowMessage(_T("messageName")); // (global scope)
...
ON_MESSAGE(m1,f1) // in the message map
...
LRESULT MyDialog::f1(WPARAM w, LPARAM l)
{
...
}

When I tried making m1 a member variable, the message map entry got a
compile error.
Joseph M. Newcomer
2011-07-07 19:52:44 UTC
Permalink
See below...
Post by Woody
Post by David Lowndes
Decide on a unique string (use a GUID) and use RegisterWindowMessage
at both ends.
OK, I have done this, with a global variable in the library and a
differently-named global variable in the app's dialog. Both
RegisterWindowMessage have the same string arg, and both return the
same value.
****
There is no reason to use a "global" variable in the library; you would use a static
variable in the library, and therefore you could use a static variable of the same name in
the dialog. See my essay on Message Management. Note the use of the anonymous namespace
in C++ is considered the proper way to handle this.
****
Post by Woody
Although the library is sending the message to the dialog using
SendMessage, the dialog is not receiving the message.
****
How do you know this?
****
Post by Woody
I suspect this has something to do with how the message map is set up
in the MFC dialog.
I have
UINT m1=RegisterWindowMessage(_T("messageName")); // (global scope)
...
ON_MESSAGE(m1,f1) // in the message map
****
As I indicated, this must use the ON_REGISTERED_MESSAGE macro in the message map. This
declaration as shown is meaningless, because ON_MESSAGE requires a compile-time-constant
expression.
****
Post by Woody
...
LRESULT MyDialog::f1(WPARAM w, LPARAM l)
****
Note that if you do not use WPARAM or LPARAM, they do not need to have names. So, for
example, if I have a message which carries no information, I might do

LRESULT MyDialog::f1(WPARAM, LPARAM)

or, if I'm passing a pointer to a string as the LPARAM, I would write

LRESULT MyDialog::f1(WPARAM, LPARAM lParam)
{
CString * s = (CString *)lParam;

and so on.
*****
Post by Woody
{
...
}
When I tried making m1 a member variable, the message map entry got a
compile error.
****
It is unfortunate that you didn't get a compilation error for the declaration you used,
since it is completely wrong.
joe
****
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Woody
2011-07-07 19:30:03 UTC
Permalink
I found my problem: ON_MESSAGE should be ON_REGISTERED_MESSAGE.
Joseph M. Newcomer
2011-07-07 19:54:33 UTC
Permalink
Note that you reported an incorrect state. You said "The dialog doesn't get the message",
when the correct statment was "my function is not called". Note that these are orthogonal
concepts; the dialog can certainly get the message, and not call your function (for the
reason you just pointed out).
joe
Post by Woody
I found my problem: ON_MESSAGE should be ON_REGISTERED_MESSAGE.
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Joseph M. Newcomer
2011-07-07 19:05:56 UTC
Permalink
See below...
Post by Woody
I'm using someone's customized CListCtrl code. The code is in a static
library, which I link w/my apps. I have two "uniqueness" problems, for
which I'd like advice.
1) The control sends a message to the parent dialog under certain
circumstances. How can I be sure the message code is unique? If it is
compiled into the library, an app which defines its own message codes
may conflict.
****
You have said nothing about the message. WIthout knowing what you are talking about, it
is hard to answer the question.

If the code is of the form
GetParent()->SendMessage(UWM_WHATEVER, ...);
where UWM_WHATEVER is the message code, then the only way to do this is to use Registered
Window Messages, where the header file defines a string like

#define UWM_WHATEVER_MSG _T("UWM_WHATEVER-") _T("<guid here>")

In the PreSubclassWindow handler for the subclass, do

UWM_WHATEVER = ::RegisterWindowMessage(UWM_WHATEVER_MSG);

where UWM_WHATEVER is a static UINT. Your app does a similar RegisterWindowMessage. What
I usually do is put this in the header file:

namespace {
UINT UWM_WHATEVER = ::RegisterWIndowMessage(_T("UWM_WHATEVER-") _T("<guid here>"));
};

The use of a static variable in an anonymous namespace is the accepted way of handling
this. Note that you can include this header file in as many compilation units as you want
without any multiply-defined symbol errors.

Then, for dispatching, you use the ON_REGISTERED_MESSAGE macro in the message map.

See my essay on message management on my MVP Tips site.

The use of constants, such as

#define UWM_WHATEVER (WM_APP+32)

is considered to be in exceptionally poor taste in defining custom controls, since any two
programmers can choose the same WM_APP offsets (and using WM_USER is considered to be
tasteless-squared). In fact, this is the compelling reason for NEVER using a
compile-time-static control ID for messages from a child to a parent (unless you are
sending a WM_COMMAND or WM_NOTIFY message).
****
Post by Woody
2) The control creates edit controls dynamically. How can I assign a
unique resource ID to each control, that will not conflict with the
IDs of the other controls in the parent dialog, or doesn't this matter.
****
If the purpose of the edit control is to achieve something like a spreadsheet editing
capability, then the parent of the edit control is the custom CListCtrl, not the parent of
the CListCtrl, so there is no possibility of conflict if you handle all the edit messages
in the CListCtrl itself. You can pick some useful random number for the ID and the only
conflict you need to worry about is with other edit controls you create as children of the
CListCtrl. And note that if you have six CListCtrl instances in your dialog, each one of
them can create child edit controls with exactly the same ID, and there will be no
possibility of conflict.
joe
****
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Loading...