What happens to the control names in the IDE when my program is running?

nick_journals demonstrates some confusion about names in source code and their relationship to runtime behavior.

A topic I am particularly interested in is the naming of controls, how it works...

Every control gets a name from a developer...via the IDE (e.g btnOK)

When using this function: GetWindowLong(handle,GWL_ID) it doesn't return the name itself but mostly a number or nothing.

What is GWL_ID, the documentation isn't very clear on this.

How does this whole system work, what are these numbers and where are the 'real' names?

I'm going to answer the questions most technical first. That way you can stop reading when you understand the topic.

The GWL_ID window long (or, more precisely, the GWLP_ID window pointer-sized long) returns the value you passed to the CreateWindowEx function as the child window identifier (overloaded as the hMenu parameter). The call to CreateWindowEx might have happened explicitly in your code, or it may have been the result of a call to CreateWindowEx made on your behalf by another component, such as the dialog manager, which takes the control identifier from the dialog template. (Note that only child windows have child window identifiers. Top-level windows don't have child window identifiers.) And if you passed zero as the child window identifier, then when you ask for the GWLP_ID, you'll get zero back.

The name that appears in your source code is just a name you decided to use to talk about the control. It's just a convenience for yourself, so instead of saying "Control number 103" all over the place, you can say "Control number IDC_ADD". And sometimes even that is too much typing, so you shorten it to "control btnAdd." The window manager doesn't know what cute shortcut names you've created for your child windows; the window manager still calls it control number 103. By analogy, the phone company doesn't know which numbers you've programmed into your speed dial. That's just something you set up in your phone to make dialing more convenient.

In other words, the "real name" is really just a fake name you created to make things easier to talk about. The actual "real name" is the child window identifier. When you look in the telephone book for Bob, you'll see Bob's phone number, not his speed-dial number on your phone.

This is the same thing that happens to your variables after the code has been compiled. At runtime, your variable names don't exist any more. They were just convenient mnemonic names you gave to computational values. The compiler uses those convenient names to determine what you're talking about when you assign a variable or a fetch a variable's value, but once that's done, it has no need for the name any more.

In other words, the name in your source code is just something you did to make things easier to write. The compiler's job is to change your line x = y; into mov eax, [ebp-05ch]; mov [00437180h], eax, at which point the names x and y are no longer needed and are discarded. (Actually, it's saved off in a separate file for the debugger to use, so that when you ask the debugger to show the value of the variable x, it knows to look in 00437180h, but that happens outside of the execution environment.)

It's like asking, "What happens to the phrase 1 cup sugar when I eat my cookies?" The phrase 1 cup sugar was part of the instructions for making the cookies. Once you finish following the recipe, the instructions aren't needed any more. Or at least not for the process of enjoying cookies. (You might still want to hang onto them to debug your recipe!)

Comments (20)
  1. Anonymous says:

    Ah yes, who hasn’t spent countless hours debugging recipes by examining many, many dumps.

  2. Anonymous says:

    It’s hard to believe that someone who programs for Windows doesn’t know that.

    Didn’t this person ever looked at resource.h ?

  3. Anonymous says:

    Any idea when the suggestion box will re-open?

    [Let’s wait until the existing one drains. I’m starting to enjoy not having one, actually… -Raymond]
  4. Anonymous says:

    I remember when I last used 1 cup sugar for a single cookie. It spontaneously combusted in the oven, what a mess to debug.

  5. Anonymous says:

    Hey Raymond, one thing I’d really appreciate (though I have no idea if you have control over this or not) is links on each posting to the previous and next articles.

    Whenever I click on one of your backlinks (such as the "such as the dialog manager" link in this article) that goes back to a multipart series I haven’t read, I liked to read the entire series and not just the one post you linked to.  But, since there are no previous/next links, I have to search through archives links in the right-hand side column for the correct month and year, and then go through there to find the article series.

    Some day I’ll read the entire archives.  Some day.

  6. Anonymous says:

    I second Adam Rosenfield’s request. This may be a part of the blog software and not something you can control, but if you direct us to the right people to pester, we’ll be happy to start pestering.

  7. Anonymous says:

    I third Adam’s request, though I agree with Paul that it’s just as likely outside your control.

  8. Anonymous says:

    I think the real question is – does window manager behave like a file system, where objects are accessible by name, or like your compiler example, where names are translated and never used for access. The file system translates the name to blocks, inodes, sectors, or whatever to perform actual operations. On the other hand, the window subsystem never preserves the names, but uses numeric ids to refer to objects.

  9. Anonymous says:

    Since Raymond doesn’t release one blog post per day, a previous/next entry feature might not take you to the previous/next part of the series. He could of course edit the old post to link to the new one after it’s published (he usually does it the other way around), but this would be hard to automate.

    On-Topic: Maybe the programmer played around with .Net and reflection too much.

  10. Anonymous says:

    Trying to resist urge to post this…

    Totally off topic, but "x = y" would never turn into "mov eax, [ebp-05ch]" because the stack is dword aligned.

    Blargh! Sorry about that…

  11. Anonymous says:

    Although the article is in most cases spot-on, there can be situations where your designated names are kept, for example when you use a UI library that allows you to get the Name property for controls.

    Of course Windows knows nothing about this, so to retrieve it or index a control by it, both of which I consider at least bad style, you’ll have to call the appropriate methods on the objects representing the controls and windows.

  12. Anonymous says:

    "It’s hard to believe that someone who programs for Windows doesn’t know that.

    "Didn’t this person ever looked at resource.h ?"

    Looking at the reference in the question to a control named "btnOK", I suspect that the poster of the question wouldn’t know the Windows API if it got up and bit them in the rear, let alone ever heard of resource.h (quite probably they doesn’t even have a copy of it).

    "btnOK" almost certainly is the name of a variable that references an instance of a class that encapsulates a GDI BUTTON control (or possibly an entirely custom window class that provides some sort of button-like control).  That class will be provided by some framework that distances the developer from the Window manager they are developing code for.

    The correspondence between the name of that variable (and possibly the design-time name for some instance of that control class on a form) and ANY artefacts of the underlying Window manager is entirely arbitrary and cannot be meaningfully discussed without knowledge of which RAD framework is involved (in which case the answer is, the correspondence between a control reference/class and the XYZ properties of the window in the underlying framework are ABC123, where ABC123 are details specific to the particular framework implementation and such questions should be directed at the provider of the framework, not the underlying Window manager API).

    That is all.  :)

  13. Anonymous says:

    To all critics about my question (I am the author), to explain a bit… ;-)

    1. The post is from November 2006 so I had less knowledge than I now have.
    2. My background as a developer is having learned Pascal by myself in ’94 and then went into Delphi later on (that’s why the button name ;-)) I also have knowledge of C, C++, C#

    But I never had to create my windows by using createwindow etc as it was one of the first real+good RAD devtools. (IMHO)

    I did use a lot of Windows API’s and know a lot by heart, but the window/control stuff I left over for the development environment to handle.

    I have always had interest in the internals of Windows and in those 3 years I expanded my knowledge via ‘Windows Internals 3/4/5’, I read Mark R’s articles, and I dive deep into the Windows API’s and prefer them over the massive amount of layers that current frameworks like .NET build on top of them. (although I use them too of course)

    And although the question might seem strange, at that time it was valid and it was unclear to me how the window-manager handled controls and if it also stored the names of the controls.

    Because with API’s from MSAA you can get the name of a control. Of course now I know how that all works but at that time I didn’t have much knowledge on how MSAA worked and I thought that the name was stored somewhere in the control itself and I was hoping to get it via one way or the other… and I thought this API did that, but documentation wasn’t really clear for me and it didn’t return the result I hoped for.

    Just to clear up how this question came about and thanks Raymond for clearing that up! ;-)



  14. Anonymous says:

    The Naming of Controls is a difficult matter,

    It isn’t just one of your holiday games;

    You may think at first I’m as mad as a hatter

    When I tell you, a control must have THREE DIFFERENT NAMES.

    (with apologies to T.S. Elliot)

  15. Anonymous says:


    And in what world is -05ch not on a DWORD boundary?

  16. Anonymous says:


    I would assume he misread 05ch as 05h, as I did at first as well.  The ‘c’ is very easy to miss.

    I prefer my hex constants written with a leading 0x instead, but I’m guessing Raymond chose to use the trailing h because that’s what MSVC/WinDbg use in their disassembly listings.

  17. Anonymous says:

    @Nick J:  I hope you didn’t interpret my comment as being critical of your question… it was intended to be critical of the **replies/comments**.

    The reference to not knowing the Windows API if it got up and bit you on the rear was hyperbole for (hopefully) humorous effect, intended to reference the "disconnect" between the app dev environment (a RAD framework) and the underlying API.  Clearly the poster (i.e. you) was in point of fact familiar with the API, since the question involved an API call!  :)

  18. Anonymous says:

    @Jolyon: No of course not ;-)

    I’m not ‘bitten in the rear’ by anyone.

    But I thought it would be good to explain why I asked this question which may seem like a weird question that is obvious to (some) others.

    And as English isn’t my native language, ‘critics’ may sound a bit harsh for native speakers. :-)

    In real life I am a big fan of the Windows API and rather use that in favour of the frameworks, but times change…

    Just like some of the people here might still love to create windows/controls the hard way.

    So no offence taken by anyone.

    I’m glad Raymond answered this question because now it all fits together and give a definite answer to my question.



  19. Anonymous says:

    The most obvious *error* is the naming. Yes, it’s an error! By convention winapi controls are named IDx_NAME_WITH_SPACES where "x"=resource type and "NAME_WITH_SPACES"=whatever you want to call your control. A generic control is named IDC_…

    btnOK is not an acceptable name in winapi. period.

  20. Anonymous says:

    Whoah there 640k, get off your high horse. Just because something is done by *convention*, it doesn’t make it an error to not do it. If I wanted to call my controls BADGER_1 through BADGER_n, I could and it wouldn’t make the slightest bit of difference to Windows..

Comments are closed.