On the unanswerability of the maximum number of user interface objects a program can create

The answer to the question "What is the maximum number of window classes a program can register?" is not a number.

Most user interface objects come from a shared pool of memory known as the "desktop heap". Although one could come up with a theoretical maximum number of window classes that can fit in the desktop heap, that number is not achievable in practice because the desktop heap is shared with all other user interface objects on the desktop. For example, menus and windows go into the desktop heap, as well as more obscure objects like active window enumerations, window positioning handles used by DeferWindowPos, and even how many threads have attached input queues (either implicitly done by having cross-thread parent/owner relationships or explicitly by calling the AttachThreadInput function). The more windows and menus you have, the less space available for other things like registered window classes.

Typically, when somebody asks this question, the real problem is that they designed a system to the point where desktop heap exhaustion has become an issue, and they need to redesign the program so they aren't so wasteful of desktop heap resources in general. (One customer, for example, was registering thousands of window classes in their program, which is excessive.) In the same way that somebody asking for the maximum number of threads a process can create is an indication that their program is in need of a redesign, a program that registers thousands of window classes needs to be given another look. After all, even just creating a thousand windows is excessive—any UI that shows the user a thousand windows is too confusing to be usable.

(Pre-emptive link: Q126962: On the desktop heap.)

Comments (23)
  1. Carrie says:

    The dread desktop heap!

    A couple browser windows (any browser), outlook, visual studio, photoshop and 3dsmax opened together and you are 100% sure in hitting the default limit in less than 3 hours of work :( Folders start to open without icons or even they don’t open at all.

    Seriously, this is one of those things that give the impression of instability when working on windows, even if the system was actually behaving in a stable way.


  2. Kevin Dente says:

    Why is there a special, finite desktop heap anyways? Has this changed in Vista?

    Like the previous poster, I’ve had machines where a half a dozen apps exhaust the DH for some reason. Very frustrating.

  3. Mike Dimmick says:

    A lot of programmers, particularly .NET programmers, see one graphic == one control (which to a Win32 programmer == one window). If every file in a folder display was its own window, you’d blow the desktop heap pretty quickly.

    Even if you’re coding your own control’s drawing, this way of coding is still simpler than having a single window drawing surface with lots of graphics objects on it. There isn’t really any problem coding your big surface to manage a collection of local objects, passing on painting requests and clicks to those objects, it’s just that developers don’t think of it.

    One of my colleagues is developing something like this right now. I’ve told him he’s doing it wrong but right now it’s ‘just a prototype.’ I really hope this isn’t a prototype that gets put into production.

  4. Naive Newbie says:

    Raymond: What’s preventing a program from using all available memory in the PC to register window classes? I thought heap space consideration was only necessary in win16/win9x?

    Mike: So you are reinventing widgets? I thought that was thing of the last millennium.
    Nowdays such stuff should be in a library/toolbox ready to use, no need to code that yourself.

    [Address space is not interchangeable. -Raymond]
  5. Mihai says:

    <<One customer, for example, was registering thousands of window classes in their program, which is excessive.>>

    It feels excessive to me, to you, and to others.

    Starting programming in the DOS/memory segments/Win 3.0 time, I am used not to waste.

    But I don’t remember seeing anyware a guideline of what is excessive and what is not.

  6. Nawak says:

    Ok, let me put things together
    Q: What is the maximum number of window classes a program can register?

    A: Thousands of window classes […] is excessive.

    So there is no real known limit but the reasonable limit seems “thousands”. So maybe this answer would satisfy them…

    [Thousands is clearly excessive. Hundreds is also excessive. I would recommend not more than a dozen. -Raymond]
  7. jeffdav says:

    No, a reasonable answer is "tens".  Internet Explorer registers less than ten.  IE does, however, tend to eat up desktop heap.  This is why you can generally only have about 40-60 IE windows open at a time… after that we run out of desktop heap.  :-/

  8. ulric says:

    Did anyone every check the number of objects iTune takes.   It takes about 1400 handles here, even if you run in mini mode.  So basically if you have that, and one of Visual Studio and 3DSMax, Maya or XSI it can blow up very rapidly.  I have a theory that iTune will never be fixed, since it makes the rest of windows look bad.

    About the number of classes registered… ‘ten’ is only good for trivial application.  Look again at Max, Maya, XSI, these applications are like an office suite in one application, and they have dozens of custom controls, different views (graphs, shader tree, 3D viewports, property editors), etc. It’s not sloppy programming like a folder view where each item is an individual window.  It’s really what it takes.

    Of course these applications are the exception to the rule, I will concede that, there’re probably the worse case scenario.

    Visual Studio 2005 also seems like pig.

  9. Spire says:

    I remember back when I used to run Internet Explorer under Windows 98.

    Opening a large Slashdot discussion thread was like playing Russian roulette; if you’d happened to have been assigned "moderator" status that day, you’d be greeted by a page filled with hundreds of comboboxes. It was a sure-fire way to bring the entire system to its knees.

  10. Jamie Lorentz says:

    J. Edward, are you sure that /. effect wasn’t intentional?

  11. . says:

    > J. Edward, are you sure that /. effect wasn’t intentional?

    >> I have a theory that iTune will never be fixed, since it makes the rest of windows look bad.

    I once had opened a website on absurd cospiracy theories, but I couldn’t see the icons !! Sure it was a plot of the webmaster to make me feel more stupid.

  12. Goplat says:

    When I used Windows 98, I’d often be unable to open the Options dialog in mIRC when other programs were running. Turned out it had hundreds of child windows in it, and they all had to be created even though only a few dozen were visible at a time.

    Seems hardly anyone cares about efficiency any more. Firefox is probably the worst offender among programs I use. It leaks memory like crazy but the devs just don’t care, they’d rather implement some vector graphics format nobody uses.

  13. Jorge Coelho says:

    Ah-ah! I’ve been waiting for a long time for something like this to come up so I can ask two questions :-) :

    1 – I like to have my XP system running for as long as possible, and frequently have many, many applications open at the same time (with 1GB of RAM this shouldn’t be an issue).

    However, I’ve found out that after some time, I start having problems where folders and owner drawn menus do not display icons, windows do not open, the screen can no longer be captured via PRTSCR, etc… Something is obviously leaking.

    The problem is that I am unable to indentify the culprit using Task Manager! Handles, GDI Objects, User Objects, NP Pool, Paged Pool, VM Size, Mem Usage, they all indicate ‘normal’ values for the various applications.

    I guess the problem here has something to do with the Desktop Heap, but since MS does not seem to provide an indicator for that, how do I (and any other normal user) indentify the ‘leaking’ application?

    2 – Possibly related, I’ve mentioned this before in the first suggestion box (I’ll cut & paste, but it’s a bit long, sorry):

    I’m the developer of NextSTART at Winstep Software Technologies.

    One of the things NextSTART does is to ‘replace’ the Windows startbar with it’s own version, capturing the Windows systray (or tray notification area, if you prefer) into it. The systray is very difficult to handle without replacing Explorer as the shell since there is no API to manipulate it, therefore a lot of ‘tricks’ must be applied in order to make it behave properly.

    One of the nicer tricks is to capture the Windows systray into the NextSTART startbar and render its background transparent (adding a drop shaddow to the icons in the process). For this I must capture an image of the systray into a bitmap in memory and work on it in order to make a ‘mask’ Region, which is then applied to a container form. This must be done whenever there is a change in the systray (i.e.; icons are added or removed from it). Since the systray window does not have a persistent bitmap, before XP I was forced to show the whole systray in the desktop for a brief moment, including the background, in order to capture the contents – this caused an annoying flicker.

    With XP’s PrintWindow API, the systray window no longer needs to be visible on the screen for me to capture the contents. However, because the container form still has the previous Region applied to it (and PrintWindow respects this), I’m still forced to temporarilly move the systray out of the container form and back onto the desktop. I do this by making the desktop the parent of the systray with Setparent while moving it *outside* the visible desktop area with SetWindowPos. I then capture the systray image with PrintWindow, move the systray back into the container with SetParent and re-adjust it’s position with SetWindowPos.

    So far so good. The problem is that, after a while (like a couple of hours running!), moving the systray back to the container form with SetParent makes the CPU peak to 100% usage for nearly half a second – in other words, every time the systray gets updated, the whole system literally pauses.

    Any idea what might be causing SetParent to induce such a high CPU usage and/or how to prevent this from happening?

  14. . says:

    > Firefox is probably the worst offender among programs I use.

    Do you really use only firefox and notepad ?!

  15. cd .. says:

    If an application could manage it’s resources itself in the available memory, the system should not have any problem either to do so.

    We all know windows has fundamental resource handling problems. Nothing new to see here, move along.

  16. asmguru62 says:

    If we look at the contents of WNDCLASS – we will see that only class style is really what distinguish class from class. The rest of members are provided by the window procedure. The background can be drawn in WM_ERASEBKGND. The cursor can be set in WM_SETCURSOR. Icons and menus are also set dynamically at any point when HWND is ready. In conclusion, the application should register class names, like: "AppName-XXXXXXXX", where XXXXXXXX is a hexadecimal value of class style.

  17. ulric says:

    Btw, in order to be able to run iTune, VC++ 2003 and one or two more apps without starting to menus, buttons, font, bitmaps, etc, I’ve modified the desktop heap size in the registry as the KB article in the blog entry.

  18. Bryan says:

    I would /really/ love to be able to watch the usage of the desktop heap.  Many of my users have three or four monitors, so they run with dozens of windows open.  After a few days, programs can’t create new windows, users can’t pop up menus, sometimes the whole desktop starts blinking violently.  We bumped the limit in the registry from 3072 to 4096 and the problem seemed to reduce, but it feels bad to be groping about in the dark, randomly changing settings.

    Raymond, do you know of any tools that can shed some light on the desktop heap usage?

    [Did you at least try searching for the answer yourself? It’s the number one hit on MSN Search and number three on Google. -Raymond]
  19. Jules says:

    asmguru62> Yeah, I got there a while back.  In fact, I also noticed that most of the useful class styles (e.g. CS_HREDRAW and CS_VREDRAW) can be trivially simulated by the window procedure, too.  So most of my programs register a single window class with CS_DBLCLKS and a window procedure that picks up an object based on the contents of GWL_USERDATA and calls methods in that based on the type of event being processed.  Everything else is down to the event handlers to sort out.

  20. asdf says:

    Goplat: make sure to set config.trim_on_minimize to 1, the firefox devs are doing something really inane as a workaround:


  21. Bryan says:

    Did you at least try searching for the answer yourself?

    Yes, I did look.  I Googled and Googled, I raised it with Microsoft contacts (one of whom actually sent me a crufty script that claimed to do the job but didn’t), I looked all over.  But this was a couple of years ago; perhaps dheapmon was released since then?  Perhaps it should be mentioned on Q126962?


  22. someone says:

    The reason old Internet Explorers blow up on pages like slashdots article page with moderation is that they use normal controls for the form controls. A well-visited article could have hundreds of comments, each of which gets a drop-down list and each one would create a window.

    Newer versions of IE use custom controls that look like the normal ones, but care is taken to avoid creating separate windows, just to combat this problem.

  23. BryanK says:

    If by "newer" you mean "IE7", then you’re right.  But any released version of IE (that is, 6SP1 and 6SP2) still uses a new window for every <select> element…

Comments are closed.