What does the HTOBJECT hit-test code do?

Leo Davidson observes that a hit-test code is defined for HTOBJECT, but it is not documented, and wonders what's up.

#define HTOBJECT            19

The HTOBJECT is another one of those features that never got implemented. The code does nothing and nobody uses it. It was added back in Windows 95 for reasons lost to the mists of time, but when the reason for adding it vanished (maybe a feature got cut), it was too late to remove it from the header file because that would require renumbering HTCLOSE and HTHELP, two values which were in widespread use already. So the value just stayed in the header file, taking up space but accomplishing nothing.

Comments (25)
  1. John says:

    Why does removing it from the header file require renumbering other ones?  I'm pretty sure I've seen gaps in #defines in Windows header files before.

  2. Adam Rosenfield says:

    Well then people would ask what happened to the missing numbers.  For example, the window message #4, between WM_MOVE (0x0003) and WM_SIZE (0x0005).  What happened to that?  Was it a message that got cut before it was in a public header file?

  3. Brian_EE says:

    I agree with John. It it is in the header as a #define then there should be no downside to removing it, especially, as Ray claims, that the functionality was never released and the functionality was never implemented.

    Now, if it had been part of an enumerated data type declaration (e.g. typedef enum someType_e {…} someType; ) where it would change the values of members following it, I could see his point.

    Personally, I believe the people who ask "what does this do?" outnumber those who ask "why the gap?" in these sorts of things.

  4. Dan Bugglin says:

    @John somewhere, someone is probably using it for something completely unrelated.

    #define TRUE HTOBJECT-19

  5. Joshua says:

    Personally, I'd have removed it and not renumbered the other messages.

  6. if it had been part of an enumerated data type declaration… where it would change the values of members following it

    You could still remove it and make the values of each enumerant explicit.

  7. Random832 says:

    @The MAZZTer That explains why it can't be removed _now_, not why it couldn't be removed at the stage of the Windows 95 SDK release that the post is talking about.

    [Probably because somebody simply forgot, just like with EM_SETHILITE. -Raymond]
  8. Danny says:

    @The MAZZTer && Random832

    It can be safely removed even with that example – I am pretty sure the compiler made that #define equal zero in the assembler. Remember, Microsoft is in business of backward compatibility from the compiled code point of view, not the source code.

  9. @Danny says:

    You would be wrong there. Microsoft tends to retain source code compatibility as well. Breaking a build with an SDK update counts as a regression.

    The MAZZTer makes a valid point about why you cannot remove the #define after it has shipped. I still don't see why it wasn't possible to remove the #define prior to a public release though.

  10. KenW says:

    @Danny: No. #define is for the preprocessor, and does a pretty simple replacement in this type of statement. It's a literal "replace HTOBJECT with the value 19" operation, and the assembler would never see it – it would see a literal 19 in places HTOBJECT had been, or absolutely nothing (including no zero) if HTOBJECT wasn't used anywhere, as there would have been nothing to replace.

  11. Adam Rosenfield says:

    @Danny: #define's are only automatically made 0 for the purposes of #if tests — if you say "#if SOME_MACRO" (or any expression involving SOME_MACRO) when SOME_MACRO is not defined, it is automatically given a value of 0 for that test.  Stuff like "#define TRUE (HTOBJECT-19)" would still expand to code that gives errors about undefined identifiers or somesuch.

  12. David Walker says:

    @Maurits:  "enumerant".  Great word, I love it.  I'll slip it into casual conversation if I can!

  13. alegr1 says:

    This line could have been simply commented out, with an explanation.

    [That would have introduced a build break for any code that was using the value for its previous (now-abandoned) purpose. -Raymond]
  14. James Curran says:

    Now, assuming that HTOBJECT was never used (for its intended purpose), could some future HTxxxxx constant use value 19 ?

  15. James Curran says:

    @KenW & AdamR: You're missing @Danny's point.  If you were to use #define TRUE HTOBJECT-19 in your code, then the compiler will treat that essentially as if you had written #define TRUE 0.  The compiled code will continue to run regardless of whether are not HTOBJECT is removed (or renumbered) in future editions of the OS.   It would only become a problem when you tried to recompile the code.  

    This is the opposite effect of renumbering the HTxxxxs, which would cause existed compiled code to stop running.

  16. Brian_EE says:

    @Raymond: There is a school of thinking that says in this case a build break is a good thing. If the intended purpose was removed, then code that relied on that intended purpose should be updated to account for the missing functionality from the OS. A build break points this out to the developer that "Hey, that's something I need to look at and address"

    And let's be honest – if the feature is removed from the OS, then any executable that relied on the function is broken, regardless of whether the SDK allows it to build or not.

    But then again you originally said it was never implemented, and never used, so then why would any builds break in the first place?

    [I misspoke when I said it was never implemented. I meant that it the window manager never paid attention to it. Since this is a value you pass from the application to the window manager, the implementation comes from the applications, not the window manager. -Raymond]
  17. Joshua says:

    Documenting it as "Not Used" would have been nice. The obvious way of going about implementing WM_HITTEST & WM_NCPAINT is going through the constant tables and making sure all values are handled. If this one can't occur it would have been nice to know that.

  18. Keithius says:

    I think the point is, why risk breaking something that already works? Sure, it *shouldn't* break anything, but you never know with a system as big and complex as Windows. And there may be other code involved that wasn't mentioned here which, although it does nothing, might break if the define was removed… and then you'd have to make more changes… and then those changes have risks & consequences, too… and you can see where this leads.

  19. mikeb says:

    For all the people arguing that it could/should have been removed, what's the harm in having it there?  That it might cause idle curiosity or speculation isn't much of a reason to remove it.

    And as Adam Rosenfield mentioned, the hole left in the numbering scheme would still leave cause for idle curiosity and speculation, so there's even less of an argument that than you might have thought at first.

    A better reason might be that it's a needless intrusion on the global namespace, but even that rationale is pretty weak.

  20. cheong00 says:

    @James Curran: Never reuse number that has been assigned in previously released SDK of a product version that's still in use, even if you THINK noone is using it.

  21. AC says:

    … full of sound and fury, signifying nothing.

  22. Danny says:

    @Ken, Adam and rest who didn't read my previous comment with enough attention. I was talking about compiled code, not preprocessor code, not source code, not interpreted code, not future to exist code that is different then the one currently is written inside a .exe. Raymond and it's entire department of compatibility is also in business of backward compatibility at that level as well, I doubt he cares if the app who used undocumented features who has to support in the next OS version really care in what programming language was written – he gets a compiled code to which start to attach debugger and debug the assembler that is in the memory. And before windows 95 any compiler would optimize that DEFINE to zero, so none of those applications would care if that define will get removed in current version of the Windows, will still work. That was my point, next time read more careful.

  23. 640k says:

    It could be reused on 64-bit windows. Simple ifdefs would do.

  24. hacksoncode says:


Comments are closed.