GetParent, just as confusing as EnumClaw, but it’s an actual function!


The function Enum­Claw, documented as returning "the child or the parent of the window", was a joke, but there's a function whose behavior is just as confusing as the joke function Enum­Claw: Get­Parent.

The Get­Parent function returns the parent window, or owner window, or possibly neither. All that's left is for it to be a floor wax and it'll have everything covered.

The idea behind Get­Parent is that it returns the parent window. Only child windows have parents, so what happens if you pass something that isn't a child window? Well, we shouldn't let a parameter go to waste, right? So let's have it return the owner window if you pass in a top-level window. But wait, we're not going to return the owner window for all top-level windows, just for top-level windows which have the WS_POPUP style.

This last bit regarding the WS_POPUP style is a leftover from Windows 1.0, where there was a distinction made between "tiled windows" and "popup windows." Popup windows could overlap, whereas tiled windows could not, and the function was only interested in windows that can overlap. Of course, now that all windows can overlap, the rejection of tiled windows is just a compatibility remnant.

Anyway, the algorithm for Get­Parent goes like this:

  • If the window is a child window, then return the parent window.
  • Else, the window is a top-level window. If WS_POPUP style is set, and the window has an owner, then return the owner.
  • Else, return NULL.

Here it is in tabular form, since I've discovered that people like tables:

Get­Parent return values WS_CHILD
Set Clear
WS_POPUP Set N/A Owner
Clear Parent NULL

The upper left entry of the table (corresponding to WS_CHILD and WS_POPUP both set) is left as N/A because that combination of styles is illegal.

Fortunately, you don't have to deal with all the craziness of the Get­Parent function. There are ways to get the parent or owner separately and explicitly without having to deal with Get­Parent's quirks.

  • To get the parent window, call GetAncestor(hwnd, GA_PARENT).
  • To get the owner window, call GetWindow(hwnd, GW_OWNER).

Compatibility requirements prevent Get­Parent from ever going away, but that doesn't mean you are forced to continue using it. Use one of the less confusing alternatives. That's why they're there.

Comments (28)
  1. Alex says:

    It's nice that you explained the algorithm three times, since the first explanation contradicts the second two (which are presumably correct).

    [Fixed. Further proof that you shouldn't trust what I write. Fortunately, it's correct in the official documentation. -Raymond]
  2. Raphael says:

    Does it at least generate a compiler warning (much like the old CRT functions)?

  3. Dan Bugglin says:

    It would be nice if MSDN marked legacy functions with links to recommended replacement functions.

    IIRC they only show a similar warning for deprecated functions.

    @Karellen According to MSDN GetAncestor concerns itself with parent relationships while GetWindow has all other relationships such as z-order and owner.  Of course then GetAncestor has a GetParent-style GA_ROOTOWNER to walk the parent/owner chain.

    They both were introduced in Windows 2000 and both live in user32.dll so I guess your question is quite valid, except for the fact that it would violate the "if it ain't broke, don't fix it" rule of coding.  But yeah I too would be interested in hearing why they weren't ORIGINALLY one function.

    Only difference I can see is that GetAncestor's documentation seems to indicate it will always succeed, when GetWindow may not.  But then again you might try calling GetAncestor with the desktop HWND or with an invalid flag or HWND passed in or something, so it's got to fail somehow.

  4. John says:

    @Karellen:  Probably a case of two different people/teams implementing the same functionality at the same time.  GetWindow() does have a GW_OWNER flag, though no GW_PARENT flag.  It doesn't matter anyway.  The function exists, programs use it, and thus it can never be removed.  But at least you'll still be able to run Lotus 1-2-3 in 2045.

  5. Joshua says:

    There is still a distinction between WS_OVERLAPPED and WS_POPUP. A WS_POPUP transits its activation to its owner so the title bar shows active.

  6. jader3rd says:

    "Compatibility requirements prevent Get­Parent from ever going away" And we now know why people accuse Windows of being bloated.

    [Let me know when linux gets rid of olduname. -Raymond]
  7. Glen says:

    I'm curious as to why there's legacy compatibility with Windows 1.0 still…

    [Okay, you tell me: Which version of Windows should have introduced the change that broke nearly all programs designed for the previous version of Windows? -Raymond]
  8. Crescens2k says:

    @Glen

    It's not just Windows 1.0.

    GetWindow wasn't added until Win32 IIRC. Not really sure which version because the MSDN claims it was Windows 2000, but it also claims that CreateFile was Windows 2000.

    So you can't guarantee that it was available in the initial versions of Win32, so that means that there could have been a need for GetParent during the NT 3/Windows 95 era. The other thing to remember was that the Win32 API was designed so you could easily compile 16 bit applications for the new Win32 with very few changes. So this allowed for less breakage. Since you can't guarantee that these programs are not in use even now, then they have to be kept in. So it isn't just Windows 1.0.

    [GetWindow has been around since Windows 1.0. MSDN doesn't cover Windows versions prior to Windows 2000 any more, so anything introduced prior to Windows 2000 is usually just marked "Windows 2000". -Raymond]
  9. Zan Lynx says:

    Glen, presumably because Windows 2.0 was compatible with 1.0. Then, 3.0 was compatible with 2. Of course, 95 had to be fully compatible with 3.1. And XP had to be compatible with 95.

    And so it goes.

    All the way down at the bottom we have 8 core CPUs booting up in 16-bit real mode so that they can run BIOS boot code written in 1995, and we have monstrously powerful GPU cards carrying 2GB of RAM that pretend to be 1MB VGA cards and implement INT 13.

  10. Joshua says:

    [MSDN doesn't cover Windows versions prior to Windows 2000 any more, so anything introduced prior to Windows 2000 is usually just marked "Windows 2000". -Raymond]

    I know. Irritates the heck outta me. I've got an NT3.51 API document lying around but no NT4 or Win 95 or Win 98.

  11. SuperKoko says:

    @Zan Lynx:

    and we have monstrously powerful GPU cards carrying 2GB of RAM that pretend to be 1MB VGA cards and implement INT 13.

    Unfortunately, VGA is also the last GPU hardware interface standard, and so, the only thing we can really rely on. VESA BIOS Extensions are just a software hack.

    BTW, VGA has 256 kB of memory, not 1 MB. :)

    @Glen:

    I'm curious as to why there's legacy compatibility with Windows 1.0 still…

    Compatibility is a feature, not a bug.

  12. Joshua says:

    @SuperKoko: Actually, there is VESA that is newer.

  13. alegr1 says:

    @Jader3rd:

    GetParent doesn't add any bloat, because it must be just a thin wrapper around GetWindow variant.

  14. Crescens2k says:

    [GetWindow has been around since Windows 1.0. MSDN doesn't cover Windows versions prior to Windows 2000 any more, so anything introduced prior to Windows 2000 is usually just marked "Windows 2000". -Raymond]

    Interesting, that shows that I'm not as up on the Windows API as I would like to be.

    Well, I didn't start taking Windows programming seriously until after I graduated from University, and that was after XP was released.

  15. David says:

    Good lord! I remember encountering this little monster a number of times back in the day when I wrote Windows code in C. Somehow I always managed to get it to do exactly what I needed to do, but only after at least a few hours of trial and error. Meh.

  16. Karellen says:

    What is the point of GetAncestor()? Why not just provide GW_* equivalents of GA_* for use with GetWindow()?

  17. Guest says:

    Tiled windows that could not be overlapped……sounds like Metro to me xD

  18. 640k says:

    [Okay, you tell me: Which version of Windows should have introduced the change that broke nearly all programs designed for the previous version of Windows? -Raymond]

    This should have been fixed when 32-bit and 64-bit windows was introduced, for 32/64-bit programs. You had 2 chances!

  19. cheong00 says:

    @640k: I think the next version of Windows would be the first version to drop 16-bit support (Win7 32-bit should still support 16-bit applications so still cannot remove the function), following Win2008 R2's trend.

  20. SuperKoko says:

    @Joshua: Only VESA BIOS Extensions (VBE), part of the VESA standard, are actually used on modern hardware. The physical VESA standard is not used anymore.

    VBE is a software hack, as I pointed. It's some poor, OS independent, driver standard, stored in PCI BIOS extension ROM.

  21. ender says:

    @Zan Lynx: don't worry, UEFI is finally taking hold, so now you can have stuff like a web browser built-in to the firmware so you're able to configure the server's RAID controller (I wish I was kidding, but that's exactly what a certain 3-letter manufacturer's server does; it also needs about 7 minutes to go through the "Initializing firmware" sequence).

  22. Raphael says:

    @640k:

    So just get this straight: You want to remove a negligible amount (especially on 64-bit machines) of obsolescent code so that manufacturers don't go through the trouble of updating their software for the next hardware platform?

    Why?

  23. Crescens2k says:

    @640k

    The problem here is that if GetParent was removed/changed in the transition between 16 bit and 32 bit Windows, we would have had two problems. First, as you can tell with all of the extra definitions in the headers, Win32 was designed so that a 16 bit application could get compiled for 32 bit Windows with as few changes as possible. So that would mean that in that transition GetParent would have stayed in.

    Otherwise how many people would have made it clear in the 3.11 to 95 transition, "don't upgrade Windows, it breaks programs".

    For 64 bit Windows, it was designed to be the same as Win32, so it isn't a surprise that it is in there.

    But shockingly, I have seen GetParent used recently, even in the post Vista times. Since it is actively used even now, are you suggesting to break those applications?

  24. Crescens2k says:

    -_-; I'm doing this too often recently. I forgot something.

    There is even at least one sample of GetParent being used in the MSDN. msdn.microsoft.com/…/hh298366(v=VS.85).aspx

    So you would also be breaking apps which followed a sample, and is that good?

    Oh, and I'm also sure that someone will mention some Windows components like CAPICOM that didn't make it through the 32/64 bit transition. For these you will most likely find that there is a proper replacement, like CNG in place.

  25. Highly Confused says:

    Hey!  I live in Enumclaw.  It means "The Home Of Evil Spirits".

    Oh you coders and your fancy parent windows and whatnot.

  26. Winapi rulz says:

    We should be grateful gdi isn't based on COM. Until w8, that is.

  27. gdalsnes says:

    Crescens2k: Otherwise how many people would have made it clear in the 3.11 to 95 transition, "don't upgrade Windows, it breaks programs". How could it break 32bit programs, they didn't exist yet. 16bit apps would run just as good as before, no change. The problem would be lazy software companies that can't handle changing a few lines of code to compile for 32bit. They could say "don't upgrade from 3.11 to 95, we are too lazy to port our application to 32bit", but that doesn't make _any_ sense.

    [Apparently, in your world, the way to encourage developers to port their code from 16-bit Windows to 32-bit Windows is to make it harder. In my experience, if you make something harder, people are less willing to do it, rather than more. -Raymond]
  28. Crescens2k says:

    Well, I think Raymond summed up what I was thinking perfectly. So I'll just add two little things.

    First, Win32s released during 1994. Fully 32 bit subset of the Win32 API for Windows 3.1x.

    Secondly, Windows NT 3.1, released in 1993. Windows NT has always been a 32 bit protected mode operating system.

    So 32 bit applications did exist before Windows 95.

    Also, how could they break 32 bit apps, well you see, they have the 16 bit application, it runs in a certain way. If you build it for 32 bit Windows and it doesn't run in the same way then isn't it broken?

Comments are closed.

Skip to main content