Snagit (Windows): COM web browser window handle does not autoscroll the window contents


COM web browser window handle does not autoscroll the window contents.


The heart of the problem is that the incorrect window handle is being passed to SnagIt's COM interface (i.e., IWindowOptions). Getting the appropriate handle for your Web browser control is problematic.  Usually the wrong handle is retrieved.

Using Spy++, you see that the correct window, the window that actually needs to be scrolled, is the web browser control's child's child. There is a very annoying hierarchy here. When you use the SnagIt application manually to do the autoscrolling, you can see that it chooses the handle of this child window, because it is the topmost thing in the center of the window where you click. Its parent's parent is the Web browser control.

Unfortunately, it is not easy to get at the appropriate handle for this window. The best practice is to get the document for the browser control, and then to ask the document what the handle is. However, the problem gets worse if you have frames; there will be a window containing the frames, and then each of the scrollable frames will have a handle as well. Again, the client is inside the browser which is inside the "Shell embedding" window.

Here is a link to an MSDN article on getting the appropriate handle for the client window that actually contains the web page content. This is actually an explanation of how to print, but it's the same central problem/solution:

The key portion is the following

      Sub SetFocusToBrowser(hBrowserHwnd As Long)
          Dim lStyle As Long
          Dim lResult As Long
          Dim hwnd As Long
          hwnd = hBrowserHwnd
          While (lResult = 0) And (hwnd <> 0)
              hwnd = GetWindow(hwnd, GW_CHILD)
              lStyle = GetWindowLong(hwnd, GWL_STYLE)
              lResult = lStyle And WS_VSCROLL
          SetFocusAPI (hwnd)
      End Sub

This Sub iterates through the children of the Web browser until it finds one that's scrollable, which it assumes must be the one you're after. If there were frames, this would probably find the first frame.

A search in newsgroups can be helpful to see what others have done. For example, a quick search found this info:

Get the document object with IWebBrowser2::get_Document, query it for IOleWindow and use IOleWindow::GetWindow.

Lastly, a possible workaround to this problem is to consider passing the X,Y coordinates to SnagIt's COM interface (i.e., use a point instead of a handle to specify the window). You could calculate these screen coordinates based on the location of your browser control.