16

I'm was using private messages in my application for year like this:

UM_APP_BASE = WM_APP; // WM_APP is declared as WM_APP = $8000; in "Controls" unit.

and then defined my private messages:

UM_EXPLORER_MSG = UM_APP_BASE + 1;
UM_LICENSE_CHANGE_MSG = UM_APP_BASE + 2;
etc...

And use them like this in my class:

procedure UMLicenseChanged(var Message: TMessage); message UM_LICENSE_CHANGE_MSG;

(I also use RegisterWindowMessage to "talk" to my other applications but that is a different story)

I don't remember what made me decide to use WM_APP rather than WM_USER as base in the first place.
The docs says:

The WM_USER constant is used to distinguish between message values that are reserved for use by Windows and values that can be used by an application to send messages within a private window class. There are five ranges of message numbers:

Range   Meaning
0 through WM_USER - 1   Messages reserved for use by Windows.
WM_USER through 0x7FFF  Integer messages for use by private window classes.
0x8000 through 0xBFFF   Messages reserved for future use by Windows.
0xC000 through 0xFFFF   String messages for use by applications.
Greater than 0xFFFF Reserved by Windows for future use.

Which means that WM_APP is "reserved for future use by Windows". On the other hand Delphi uses CM_BASE = $B000; which is in that range. and also CN_BASE = $BC00;

How do I define the base message so it wont collide with other messages used both by Windows/Delphi/Other controls? Which base message is preferred as private for my application? and why?
Should I use WM_USER instead of WM_APP? Note that WM_USER base is used in CommCtrl by Windows also e.g. TB_ENABLEBUTTON = WM_USER + 1. etc...

I need some insights on this issue.


I read this on my Delphi help API (D5). which is obviously obsolete!
This is probably why I have decided to use WM_APP.
Still, an explanation about the difference between the two would be nice :)

kobik
  • 21,001
  • 4
  • 61
  • 121
  • 1
    You've probably read documentation of [`WM_APP`](http://msdn.microsoft.com/en-us/library/ms644930%28v=vs.85%29.aspx) or [`WM_USER`](http://msdn.microsoft.com/en-us/library/ms644931%28v=vs.85%29.aspx), where they say *" WM_APP (0x8000) through 0xBFFF - Messages available for use by applications.*" – Sertac Akyuz Dec 15 '13 at 15:22
  • What documentation are you referring to? – Sertac Akyuz Dec 15 '13 at 15:31
  • @SertacAkyuz, Now I understand why the downvotes... I read this on my Delphi help file (D5). which is obviously obsolete! Still, even if I made the right choice. I cant fully understand the difference between "Messages available for use *by applications*" and "Integer messages for use by *private window classes*" – kobik Dec 15 '13 at 15:32
  • 1
    For your own window class is the `WM_USER` base perfectly safe (unless that class is a descendant of a certain common Windows control). And of course, sender of messages of that base should never bradcast them. – TLama Dec 15 '13 at 15:34
  • I have seen programmers declaring "magic" message numbers such as `WM_USER + 666` etc... in the hope of not creating an existing `WM_USER` message. – kobik Dec 15 '13 at 15:35
  • @TLama, what if I *other* window class uses `Parent.Broadcast(WM_USER + 666)` to notify related class controls? your private window might intercept that message if it was declared by it as `UM_MYPRIVATE_MESSAGE = WM_USER + 666`. no? – kobik Dec 15 '13 at 15:39
  • @kobik - Why would a window class send a message that it defines for its own usage to other windows/controls? – Sertac Akyuz Dec 15 '13 at 15:42
  • 1
    @kobik Messages in the `WM_USER` range have different meaning for different window classes. So it is always a mistake to broadcast them. – David Heffernan Dec 15 '13 at 15:44
  • @kobik, I thought that you should never broadcast messages of the `WM_USER` base because they may collide with existing common Windows control instances. If you define a message like `WM_USER + 1` for your own window control class (which is not a descendant of any of that common Windows controls) and you send messages directly to that control, it is safe. – TLama Dec 15 '13 at 15:48
  • Well, TSpeedButton for example broadcast to it's parent `CM_BUTTONPRESSED` in `UpdateExclusive`. which controls other than TSpeedButton might intercept. or am I wrong? This question was basically raised when I saw that code. and I was planing on doing the same with my custom control. – kobik Dec 15 '13 at 15:54
  • @TLama, I know. but I wanted to use MY own message to do a similar job (i.e. broadcast my own message to a group of custom controls). – kobik Dec 15 '13 at 15:55
  • @kobik Can the parent of a `TSpeedButton` ever be anything other than a VCL window? – David Heffernan Dec 15 '13 at 15:58
  • 4
    @kobik, I think I got the point of your question. You would like to have a real message range for your own purpose starting from the `WM_APP` base without any collision with `CM_` or `CN_` messages. Well, then I would say `WM_APP..CM_BASE - 1` should be what you're looking for. – TLama Dec 15 '13 at 16:01
  • 2
    @kobik *Well, TSpeedButton for example broadcast to it's parent.* Sending a message directly to your parent is not the same as "*broadcasting*". So the point is messages in the WM_USER range are allowed to overlap because they **should not** be indiscriminately *broadcast* to all and sundry. But WM_USER messages can be specifically sent/posted to intended targets that should be able to handle them. (Even if these Message ID's overlap with others designed for other controls.) – Disillusioned Dec 15 '13 at 16:03

1 Answers1

17

I'm not sure where your information comes from. The MSDN documentation says:

0 through WM_USER –1
Messages reserved for use by the system.

WM_USER through 0x7FFF
Integer messages for use by private window classes.

WM_APP (0x8000) through 0xBFFF
Messages available for use by applications.

0xC000 through 0xFFFF
String messages for use by applications.

Greater than 0xFFFF
Reserved by the system.


Now, what is the difference between the WM_USER range, and the WM_APP range? This has been covered in many places. For instance, here is what Raymond Chen has to say.

0x400 .. 0x7FFF (WM_USER .. WM_APP-1): Class-defined messages.

The meanings of these messages is determined by the implementor of the window class. (Informally: By the person who calls RegisterClass for that window class.) For example, the WM_USER+1 message means TB_ENABLEBUTTON if the window is a toolbar control, but it means TTM_ACTIVATE if it is a tooltip control, and it means DM_SETDEFID if it is a dialog box. If you created your own control, it would mean something else completely different. Since anybody can create a message in this range, the operating system does not know what the parameters mean and cannot perform automatic marshalling.

0x8000 .. 0xBFFF (WM_APP ... MAXINTATOM-1): Application-defined messages.

The meanings of these messages is determined by the application that created the window. (Informally: By the person who calls CreateWindow.) This message region was created in Windows 95 to ensure that applications which subclass a window and generate custom messages will not interfere with new messages created by the window class in future versions. Again, since anybody can create a message in this range, the operating system does not know what the parameters mean and cannot perform automatic marshalling.

The main thing to take from all this is that if you define messages in the WM_USER range, then be prepared for other controls in your application to have their own use for those same messages. For instance, you must not broadcast messages in the WM_USER range.

On the other hand, messages in the WM_APP range are intended to have the same meaning for all different window classes in an application.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490