WaitForTabWindow() is not working for me. How to obtain the correct parent window for a modal dialog?

Unanswered WaitForTabWindow() is not working for me. How to obtain the correct parent window for a modal dialog?

  • Monday, December 05, 2011 9:04 PM
     
     

    I have a TaskDialog (the MessageBox on steroids for Vista/7) that needs to show up during the call to IObjectWithSite::SetSite() in case some rare (but possible) scenario appears.  In the rare scenario, the BHO will be unable to initialize its structures and therefore it will be unable to function.  I want to inform the user about this wtih this TaskDialog.

    The problem here is that, even though the dialog shows up appropriately, it doesn't block the IE window, and yes, it is the exact same thread (no new threads to spawn the box).  So I guess I need to properly specify the parent window in TaskDialog.  I don't seem to know how to obtain a handle to this window.

    Before I continue, I'll let you all know that the OS is Windows 7 and the IE is IE8.

    So I have been reading, and WaitForWindowTab() looks like the function of choice.  In order to use it, I borrowed the static C++ class described here, that is, after correcting a few things like the functions' calling convention.

    The BHO compiles OK (Visual Studio 2010 Ultimate, in case it's relevant), and as I have stated, the Task Dialog shows up, but WaitForWindowTab() returns a NULL handle, and so does AcquireModalDialogLockAndParent().  The latter returns a lock handle with value 1.

    The two functions both return S_OK (the former is called with TRUE in its first parameter), but the parent handle remains to be NULL after the two function calls.

    1. Is this the correct way to obtain the window handle to use as parent of dialog boxes in IE8+?
    2. If this is the correct way, what am I doing wrong here?  Why are these function calls returning a NULL parent window?  MSDN Online states that the latter function creates a new parent window if necessary, so what gives?

    Any and all responses are appreciated.


    Jose R. MCP

All Replies

  • Monday, December 05, 2011 9:16 PM
     
     

    On 12/5/2011 4:04 PM, webJose wrote:

    I have a TaskDialog (the MessageBox on steroids for Vista/7) that
    needs to show up during the call to IObjectWithSite::SetSite() in
    case some rare (but possible) scenario appears.  In the rare
    scenario, the BHO will be unable to initialize its structures and
    therefore it will be unable to function.  I want to inform the user
    about this wtih this TaskDialog.

    The problem here is that, even though the dialog shows up
    appropriately, it doesn't block the IE window, and yes, it is the
    exact same thread (no new threads to spawn the box).  So I guess I
    need to properly specify the parent window in TaskDialog.  I don't
    seem to know how to obtain a handle to this window.

    Query the site pointer for IWebBrowser2, call get_HWND


    Igor Tandetnik

  • Monday, December 05, 2011 10:00 PM
     
      Has Code

    Hello Igor.  Thanks for dropping by.  I have tried to get the Task Dialog up by using the handle returned by get_HWND, but the call toTaskDialogIndirect() fails with E_FAIL.  This is the code:

     

    				CComQIPtr<IWebBrowser2> wb = pUnkSite;
    				SHANDLE_PTR sParentWnd = NULL;
    				hr = wb->get_HWND(&sParentWnd);
    				if (FAILED(hr))
    				{
    					::MessageBox(NULL, TEXT("Could not get HWND from web browser."), TEXT("DEBUG"), MB_ICONWARNING);
    				}
    				if (!::IsWindow((HWND)sParentWnd))
    				{
    					::MessageBox(NULL, TEXT("The HWND is not valid."), TEXT("DEBUG"), MB_ICONWARNING);
    				}
    
    

    I don't get the message boxes so I suppose that the returned value is a valid window.  Any ideas why this fails?

     


    Jose R. MCP
  • Monday, December 05, 2011 10:17 PM
     
     

    On 12/5/2011 5:00 PM, webJose wrote:

    I don't get the message boxes so I suppose that the returned value is a valid window.  Any ideas why this fails?

    You are doing something wrong in the code you haven't shown.


    Igor Tandetnik

  • Monday, December 05, 2011 10:32 PM
     
     

    Ok, I think I know what the problem is:  This window returned by IWebBrowser2::get_HWND() belongs to another process (the frame process) and I am trying to use it as a parent to a modal call for the tab process.  That can't work, right?  So This handle is no good for my purposes.

    Or am I mistaken in my conclusion?


    Jose R. MCP
  • Monday, December 05, 2011 10:41 PM
     
     

    On 12/5/2011 5:32 PM, webJose wrote:

    Ok, I think I know what the problem is:  This window returned by
    IWebBrowser2::get_HWND() belongs to another process (the frame
    process) and I am trying to use it as a parent to a modal call for
    the tab process.  That can't work, right?  So This handle is no good
    for my purposes.

    In this case, try querying the pointer for IOleWindow and call GetWindow. See if you get the tab's HWND this way.

    Yet another thing to try is to get the document pointer with IWebBrowser2::get_Document, and query that one for IOleWindow. This should give you the HWND of the document, sitting inside the tab.


    Igor Tandetnik

  • Tuesday, December 06, 2011 1:26 AM
     
     

    Tried to get IOleWindow from pUnkSite, but I got a null pointer (CComQIPtr<IOleWindow>::p is null).

    I'll try the document object, but since we are talking about SetSite() here, most likely there is no document loaded at this point.

    Are you familiar with the WaitForTabWindow() function?  I'd love to hear from someone who has already used this function to try to understand what is happening here with it.  As far as I can tell, this is THE function for this problem. :-(

    EDIT:  Just tried to obtain the document object.  It is not possible during SetSite().  It doesn't exist yet.


    Jose R. MCP

  • Tuesday, December 06, 2011 3:14 PM
     
     

    Ok, so I decided I should study a bit more the stock dialog boxes shown by IE8 in Windows 7.  Using Spy++ I was able to see how the frame window is used as the parent and owner for modal dialog boxes coming from the tab processes.  This means that IWebBrowser2::get_HWND() should have worked OK!

    So I went on and wrote again code to get this HWND and guess what:  A call to MessageBox() fails (returns zero), but GetLastError() also returns zero, and TaskDialogIndirect() continues to return E_FAIL.  Buuuuttttt:  Subsequent new tabs CAN show the message box and the task dialog!  So it seems that only the first tab in the first process is unable to show the dialogs.

    It is my understanding from this blog post that IE8 uses MS Detours to hook into the creation of dialog boxes.  At this point I can only guess that this hook is unprepared to service requests by the time I try to create mine (SetSite() for my BHO during the creation of the first tab).

    Is there a way to get Microsoft support without a paid incident?  I guess Connect is the only way?  What if Connect doesn't list IE8 anymore (which I guess it doesn't)?  It is just that I just spent one of my paid support incidents last week and on a IE8 issue too.  If I were to use another one I will feel like I'm throwing them away through the window!


    Jose R. MCP
  • Wednesday, December 07, 2011 5:57 PM
     
     

    More information:  It is in fact true that IE re-routes WinAPI calls.  During the creation of the task dialog, ieframe.dll!Detour_CreateDialogIndirectParamW() is called, and with Spy++ I have verified that the resulting parent window of the task dialog box is different than the one given by the webbrowser, and it is of class "Alternate Modal Top Most".  The dialog boxes created with this proxy parent window behave as expected.

    The problem comes when more than one tab is loaded, like in the case where you set multiple pages as home page.  In this case, the first tab always fails to show the dialog box, then the second tab successfully displays a modally-correct dialog box, but a third tab simultaneously shows the dialog box too (this one doesn't have the alternate parent, but also went through the detour function)!  All threads are calling WaitForTabWindow(), so I conclude that this function is simply not doing any waiting as the name and documentation suggests.  Furthermore, the function never provides a suitable parent window.

    At this point I'm pretty certain that a paid support incident is the way to go.  It just seems unfair because the documentation about this function is very lacking and the very few examples out there are not clear and simply don't work.  If only an IE expert were to post a nice blog about this functionality... :)  Dreaming is free, right?


    Jose R. MCP
  • Sunday, April 22, 2012 3:02 AM
     
     

    Hi Jose,

    Thank you for your contacting Microsoft.

    This problem is complicated and it has been in the scope of paid support since we should not be able to figure out the solution within the forum. We need do further research to find the root cause behind the appearance.

    You can submit a service request to Microsoft Support from below link:

    http://support.microsoft.com/select/Default.aspx?target=assistance

    Thanks&Regards,

    Xiaoman