views:

194

answers:

2

This is probably an easy one for a GUI programmer, which I'm not...

In a tool I'm working on (GUI "spy" for internal use) I have the handle of a control the user has chosen. I would like to get the handle of the window that contains the control, in order to sent it a certain message. Now:

  1. The control could be of various types, and possibly the window itself
  2. The control is created by another process
  3. The containing window can be an MDI child, main, pop-up, whatever
  4. I'd rather not use MFC

So, what's the easiest way to get it done?

+1  A: 

Use the Win32 API call ::GetParent(HWND childWindowHandle);

Documentaiton here

Jason Williams
I tried that, but couldn't figure out when to stop when climbing up the parents/owners chain. The control might be on top of others, which means I'm not always looking for the direct parent, but rather for one of the ancestors.
eran
Stop when you find a window with WS_CAPTION in its style?
RichieHindle
That's not bad, but not perfect. The target app does have at least one window without a title bar (floating drag and drop target), which cannot be recognized this way. But it covers most cases, and if no other solution is found I can make do with that.
eran
+1  A: 

Use GetAncestor() with the GA_PARENT flag. This will retrieve a parent window but not an owner window. (You can call it repeatedly to handle the case of nested controls.)

Peter Ruderman
Which leads back to the question how do I know I've reached the actual window, and should stop calling GetAncestor? Checking for WS_CAPTION was suggested by RichieHindle, any other idea?
eran
By actual, do you mean the top-level window? The top level window is the one you get with the last call to GetAncestor(). Calling GetAncestor(hwnd, GA_PARENT) will return NULL if hwnd is a top-level window.
Peter Ruderman
When I used GetAncestor on a control that resided on an MDI client window, I looped all the way up to the application window (the MDI frame). Not sure if the MDI is the problem, but bottom line is that I did not get the NULL on the window I was hoping to.
eran
That's a little surprising. I guess you'll have to write a special case for this. Use GetWindowLong() with GWL_EXSTYLE to check for the WS_EX_MDICHILD style.
Peter Ruderman