When something is available for the user, which user are we talking about?


Some people have taken issue with the term WM_USER for the name of the base of the message range that is the province of the window class implementor. (Refresher for those who forget which messages belong to whom.) The complaint is that the user can't use them since they belong to the window class.

Aha, but the real question is, "Who is the user?" In other words, when we say "user-defined", who is the user that's doing the defining? There are four components involved here, and each one gets its own message range.

  • The window manager gets the messages below WM_USER.
  • The class implementor gets the messages from WM_USER to WM_APP-1.
  • The application (more specifically, the code that creates the window) gets the messages from WM_APP to MAXINTATOM-1.
  • Everybody else gets the messages from MAXINTATOM to MAXWORD (via RegisterWindowMessage).

Who is the user?

It depends on your point of view. From the window manager's point of view, the class implementor is the user, since that's the code that is using the window manager.

From the class implementor's point of view, it is the application that creates the window that is the user, since that's the code that is using the window class.

And from the application's point of view, it's all that outside code that is the user, since that's the code that is using the application.

Conversely, you can look "up" the list and observe that from each component's point of view, the messages that belong to the components above it are "reserved". From the class implementor's point of view, the window manager messages are reserved. From the application's point of view, the class implementor's messages are reserved. And from the outsider's point of view, the application's messages are reserved.

Let's use one of those generic box diagrams.

Outsiders

Application

Class

Window
Manager

Each box considers the messages that belong to its inner boxes as reserved; conversely, each inner box considers the next outer box as its "user".

Since the winuser.h header file was written by the window manager team, it's not surprising that they look at the world from the window manager's point of view. Therefore, everything outside the window manager is "user-defined" and everything inside the window manager is "reserved".

Of course, if you look at things from the point of view of the class implementor, then the context of the words "reserved" and "user" changes. You can see this, for example, in the dialog box constant DWLP_USER, which is the index of window bytes that can be used by the "user" of the dialog box; i.e., by the application's dialog procedure.

Comments (22)
  1. Lewis says:

    Probably a dumb question, but when creating an MFC CWnd-derived Cass, may we use the WM_USER range in that case? (My understanding is that all MFC windows share a set of common window classes, so it may be that MFC is using WM_USER for it’s own purposes…)

  2. Mike Dimmick says:

    Lewis: you have the MFC source code, find out. Look for uses of WM_USER.

    Actually MFC sneakily uses messages in the range 0x0360 to 0x037F, which strictly are for the window manager. Reflected messages are up in the 0xBC00 range (the top end of the WM_USER range).

    Raymond’s article doesn’t quite cover the dialog window procedure which uses a few messages in the WM_USER range, which is why a dialog author who wants to define a custom message needs to avoid the first few message numbers after WM_USER. In effect these should probably be below WM_USER but it’s too late to change them now since the values are compiled into every Windows program. You can’t change the definition of WM_USER either for the same reason.

    Also, when subclassing a (non-USER) control, you need to know which WM_USER-range messages the control already defines.

  3. asdf says:

    Do you know if WM_APP was tacked on at some later date or was it there since the beginning?

    [WM_APP was added in Windows 95. -Raymond]
  4. CarlSo says:

    Raymond’s article doesn’t quite cover the dialog window procedure which uses a few messages in the WM_USER range, which is why a dialog

    author who wants to define a custom message needs to avoid the first few message numbers after WM_USER.

    Raymond’s article is relevant to the dialog manager.  The dialog manager’s window proc (DefDlgProc) is associated with the predefined class definition for dialogs.  Therefore, its messages are in the range WM_USER to WM_APP-1.

    The application provides a DLGPROC callback (called back from within DefDlgProc) to handle dialog box messages.  And this is where the confusion comes in.  People mistakenly assume that a WNDPROC (associated with a window class) and a DLGPROC (not associated with a window class, but with a single instance of a dialog box) are the same thing.  They are not.  And if you are going to send/process your own defined messages within a DLGPROC, you better make sure they start at WM_APP.

    Of course, you can create a custom class for a dialog box (see http://blogs.msdn.com/oldnewthing/archive/2003/11/13/55662.aspx), in which case you can define your own window proc for the dialog (in place of DefDlgProc).  If you did that, then you can use WM_USER-based messages for your own.  Just be careful… if your custom dialog window proc ends up calling DefDlgProc, you’ll have to make sure your custom window proc’s messages do not conflict with those that DefDlgProc uses.

  5. Mak says:

    > Since the winuser.h header file was written by the window manager team

    Yeah… but how can we know that??

    [Um, who else would have written the header file for the window manager? -Raymond]
  6. Mak says:

    Um, who else would have written the header file for the window manager? -Raymond

    Of course… If I only had known there was a window manager team, who treated the dialog class as just a user….

    Anyway, your blog is really great, and thanks for your comment!

  7. Cody says:

    "From the window manager’s point of view, the class implementor is the user, since that’s the code that is using the window manager." — I think that cleared it up nicely.

  8. steveg says:

    [Um, who else would have written the header file for the window manager? -Raymond]

    For reference, so we don’t appear stupid in future, what is the windows dev team structure? There’s nothing on Google I could find.

    [Here are some tips: Header files for shell functions are written by the shell team. Header files for NLS functions are written by the NLS team. Header files for GDI functions are written by the GDI team. I hope you see the pattern. -Raymond]
  9. Bjorn says:

    I think the point steveg and Mak are trying to make is that it’s not obvious from the headers that, e.g, the dialog manager and window manager are run by separate teams and thus have different definitions of "user." Do we go by file organization? In that case, comctl32 and shellapi would apparently be different organizations, and one "mmsystem" team must be responsible for both the joystick and audio interfaces.

  10. PatriotB says:

    I don’t believe that the window manager and dialog manager were necessarily "seperate teams", but from a technology point of view, the dialog box mechanisms are definitely consumers of the window manager mechanisms.

    Dialog box messages are an intersting subject.  By today’s rules, the dialog box window procedure should have total control over all messages from WM_USER to WM_APP-1.  Specialized dialogs themselves shouldn’t define any messages in this range.

    However, many Windows dialog boxes have custom messges that fall within this range.  Examples are the Common Dialogs (which defines some CDM_xxxx messages that start at WM_USER+100), and the Browse for Folder dialog box (which defines some BFFM_xxxx messages that also start at WM_USER+100).

    So if a future version of the dialog manager, for some wacky reason, would want to define its own messages in that range (completely within its right), there would be compatibility problems.

    Note that earlier I said "by today’s rules."  At the time the common dialogs were introduced, WM_APP didn’t yet exist (As Raymond stated, WM_APP wasn’t introduced until Windows 95).  So, since the common dialog designers weren’t psychic, they introduced messages that technically violate today’s rules.

    But since I doubt the dialog manager will ever see any new messages added (the last one was added for Windows 95 according to winuser.h), it doesn’t really matter.

  11. Vipin says:

    We all know that WM_APP + n is what should be used by programmers.The problem is that because of microsoft’s mistake the WM_USER topic seems to keep popping up again and again. It will be good if Microsoft removes the #define of WM_USER from winuser.h in future versions of sdk.

    They could have done something like this early in the game, this could have prevented the existence of WM_USER constant and could have served as a warning for programmers.

    #ifdef _WIN32_WINNT < xxx

    #define WM_USER 0x400

    #endif

    [And then you get “undefined symbol: WM_USER” errors when you include commctrl.h? -Raymond]
  12. Vipin says:

    One thing is that the message based architecture is not a scaleable solution. The best messaging solution would be to use RegisterWindowMessage(…) because that brings uniqueness to certain extent.

    Coming back to WM_USER + x messages, these are meant for people who are writting the controls from scratch(without deriving from an existing controls).That will be a small segment of the entire programming community(5%??) who create and sell custom controls from scratch without using the existing controls that MS ships or building on top of the existing controls. Since MS messed with the WM_USER range, nobody knows what message will work when creating a subclassed control, so it is better off using WM_APP range all the time. well WM_APP range causes problem if somebody is going to derive from a control a third party vendor created and that is life,live with hit and trial.

    So, I guess it is time to move on to property based programming as in wpf(.net 3.0) instead of sending around windows messages to trigger something to happen in a control, application, etc and hoping it won’t break.

    [Less than 5% of the entire programming community uses the windows.h header file in the first place, so changes to winuser.h will miss 95% of the community anyway. Of the people that do use windows.h, I suspect more than 5% of them create their own custom controls. Look at any introductory Win32 programming book. They nearly all start with RegisterClass and WndProc. -Raymond]
  13. Vipin says:

    It will be better if commctrl.h is fixed by hardcoding it.

    A quick

    findstr /I /M WM_USER *.h* in the sdk include directory gave this:-

    AclUI.h

    AdsProp.h

    CommCtrl.h

    CommDlg.h

    Cpl.h

    Dispdib.h

    FtsIface.h

    inked.h

    MAPIWz.h

    msoeapi.h

    OleCtl.h

    PrSht.h

    Richedit.h

    ShellAPI.h

    ShlObj.h

    Smx.h

    Tapi.h

    Umx.h

    Vfw.h

    WFExt.h

    WinUser.h

    WinWlx.h

    Fixing up a few header files is better than teaching millions of programmers  and fixing subtle bugs for their mistakes. New programs using latest sdk headers will not be able to use the macro or may be there should be a DEPRECATE macro which should wrap up the WM_USER macro, so that already written programs can get compiled by specifying the bypass macro.

    From:-

    #define TB_ENABLEBUTTON         (WM_USER + 1)

    #define TB_CHECKBUTTON          (WM_USER + 2)

    #define TB_PRESSBUTTON          (WM_USER + 3)

    #define TB_HIDEBUTTON           (WM_USER + 4)

    To:-

    #define TB_ENABLEBUTTON         0x401

    #define TB_CHECKBUTTON          0x402

    #define TB_PRESSBUTTON          0x403

    #define TB_HIDEBUTTON           0x404

    [Okay, so you get rid of WM_USER. How should people define their custom messages? Should they just hard-code the number 0x0400? How does that fix anything? -Raymond]
  14. Yuhong Bao says:

    You must remember that before WM_APP was invented, WM_USER *was* for both applications and window classes. This however led to conflicts and so WM_APP was invented.

  15. PatriotB says:

    Vipin, WM_USER isn’t just for controls, it’s for any custom window classes that you own the WndProc for.  An app’s "main window" class is a good example.

    There’s nothing wrong with WM_USER and surely no need to deprecate it.

  16. cmil says:

    "There’s nothing wrong with WM_USER and surely no need to deprecate it."

    Agreed. In fact you can view the WM_APP range as being a subset of the WM_USER range – i.e. WM_APP is just a marker for the end of the range of messages reserved for Windows’ own controls (which are themselves ‘users’ of the window manager). If you’re not doing anything with the standard windows controls there is no reason not to use WM_USER.

    It is also not the OS’s responsibility to decide which messages in the WM_USER – MAXINTATOM-1 range should be used for custom controls. The sensible approach is to always start at WM_USER and increment by one for every custom message you need. Then ‘reserve’ a hundred or so more for future use, so that ‘users’ of your control know which messages they can safely use for subclassing.

    With a possible 48128 messages, scalability shouldn’t be an issue.

  17. Vipin says:

    Patriot,

          what if you/someone uses SendMessageToDescendants(…)?

    That said, the same issue would arise had we *all* started used WM_APP + n messages, in which case controls from third party vendors could conflict as a result.

  18. Tossing Figures says:

    Less than 5% of the entire programming community uses the windows.h header file

    I would guess more than 95% of windows c/c++ programmers include windows.h, and 95% of the non c/c++ programmers don’t subclass.

    How many programmeras are aware that a winclass derived from a winclass can result in message conflicts?

    Btw, does this problem include subclassing from controls like STATIC, BUTTON and similar?

  19. dave says:

    It seems to me that the Obvious Solution is to add WM_CLASS as a synonym for WM_USER and deprecate WM_USER.  That way it would be clear which user the ranges are reserved for; below WM_CLASS is for the window manager, WM_CLASS to WM_APP is for the window class, WM_APP to MAXINTATOM is for the application that creates the window.  (Are there problems with libraries and applications stepping on each others’ toes in the WM_APP space?  Does that need to be partitioned into WM_LIB and WM_APP?  Though that could get messy if you end up with libraries stepping on each others’ toes.)

    This doesn’t handle creating a class as a subclass of another class, but that’s inherited from the current way of doing things, and it could be handled by having controls document a "I don’t plan to use anything above this" value in the WM_CLASS space.  (Partitioning that one into WM_CLASS and WM_SUBCLASS would only work until somebody wants to subclass an already-subclassed one.)

    Besides "Once it’s there it’s impossible to get rid of it", is there any reason why something like this hasn’t been / couldn’t be done?

  20. cmil says:

    Adding a WM_CLASS and deprecating WM_USER would simply add yet another value for people to remember and be confused by. And how many developers are still using old headers and would simply continue to use WM_USER anyway?

    The point is that if people had been sensible from the word go there would never have been any need for anything other than a single range of user messages, from WM_USER to MAXINTATOM-1. Provided everybody documents which ranges they use for controls / subclassing etc. there would never be any problem.

    I suspect originally WM_APP really was just a declaration that microsoft would not use messages below that value for standard windows controls. The notion of a separate "application" range sounds to me more like an attempt to make life easier for developers who were already misusing WM_USER, although it does perhaps make more sense. But I wonder how many custom controls (that register their own classes) technically break the rules by using messages in the WM_APP range?

    "Btw, does this problem include subclassing from controls like STATIC, BUTTON and similar?"

    No, as long as you use WM_APP and greater you are guaranteed to be safe – unless somebody else has already subclassed the button you’re subclassing, in which case you have to know which messages they’ve already used. Or you could use RegisterWindowMessage().

  21. cmil says:

    Sorry, "would not use messages below that value" should have been "would ONLY use messages below that value"

  22. PatriotB says:

    @Vipin: "what if you/someone uses SendMessageToDescendants(…)?"

    I suspect that cases like this are what RegisterWindowMessage is for: you can’t use a WM_USER message because you aren’t the owner of the wndclass, and you can’t use a WM_APP message because you aren’t the creator of the window.  For example, the "TaskbarCreated" message that the shell uses falls into this category.

    @cmil: "I suspect originally WM_APP really was just a declaration that microsoft would not use messages below that value for standard windows controls. The notion of a separate "application" range sounds to me more like an attempt to make life easier for developers who were already misusing WM_USER"

    I don’t quite agree here; I think WM_APP takes the place of having to use RegisterWindowMessage all over the place.  I’ve primarily used WM_APP in one case: where I have a dialog box, and I need to send a message to the dialog box procedure.  I’m not supposed to use a WM_USER message because those are reserved for the dialog class itself, so prior to WM_APP my only option would be to use RegisterWindowMessage.

    The other place it makes sense to use WM_APP is when sending messages to windows you created, whose wndclass you don’t own, but that you have subclassed.  In this case it’s usually perfectly safe to send a WM_APP because you will catch it during your subclassed wndproc; the window class’s original wndproc itself shouldn’t ever need to process anything in the WM_APP range.

    (The only time that you might run into trouble, as the window creator, is if the window gets subclassed a second time without your knowledge.  For example, a plugin that runs in your process that decides to subclass some of your controls.)

Comments are closed.

Skip to main content