title: IHTMLDocument2 - click button inside iframe
body: <p>I'm creating a DCOM extension for some really old application.
  Main application has IE control inside of it.</p>
  
  <p>Using C# I was able to get handler for that IE Control as below:</p>
  
  <pre><code>Process pr = Process.GetCurrentProcess();
  
  var title = pr.MainWindowTitle;
  if(title.IndexOf("My old application -")&lt;0)
  {
      MessageBox.Show("No such window");
      return;
  }
  var wlwWindow = pr.MainWindowHandle;
  var ieWindow = PI.FindWindowRecursive(wlwWindow, "Internet Explorer_Server", null);
  if (ieWindow == IntPtr.Zero)
  {
      MessageBox.Show("Unable to locate IE window.");
      return;
  }
  var myDocument= PI.GetIEDocumentFromWindowHandle(ieWindow);
  MessageBox.Show(myDocument.url);
  </code></pre>
  
  <p>And here are my helper methods:</p>
  
  <pre><code>    public static IntPtr FindWindowRecursive(IntPtr parent, string windowClass, string windowCaption)
      {
          var found = FindWindowEx(parent, IntPtr.Zero, windowClass, windowCaption);
          if (found != IntPtr.Zero)
          {
              return found;
          }
  
          var child = FindWindowEx(parent, IntPtr.Zero, null, null);
          while (child != IntPtr.Zero)
          {
              found = FindWindowRecursive(child, windowClass, windowCaption);
              if (found != IntPtr.Zero)
              {
                  return found;
              }
              child = GetNextWindow(child, 2);
          }
          return IntPtr.Zero;
      }
  
      public static IHTMLDocument2 GetIEDocumentFromWindowHandle(IntPtr hWnd)
      {
          IHTMLDocument2 htmlDocument = null;
          if (hWnd != IntPtr.Zero)
          {
              uint lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
              UIntPtr lResult;
              SendMessageTimeout(hWnd, lMsg, UIntPtr.Zero, UIntPtr.Zero,
                  SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lResult);
              if (lResult != UIntPtr.Zero)
              {
                  htmlDocument = ObjectFromLresult(lResult, typeof(IHTMLDocument).GUID, IntPtr.Zero) as IHTMLDocument2;
                  if (htmlDocument == null)
                  {
                      throw new COMException("Unable to cast to an object of type IHTMLDocument");
                  }
              }
          }
          return htmlDocument;
      }
  </code></pre>
  
  <p>This part works fine and I was able to get content of that html page from temp:</p>
  
  <pre><code>&lt;body id="state" class="saveFavorite" onload="load()" onunload="RUIMaster.Destroy()" style="margin: 0px; padding: 0px; overflow: hidden;"&gt;
  &lt;p style="display: none;"&gt;
  &lt;object classid="clsid:22FD36F1-A133-11d4-A0E4-005056E2D8AA" height="0" width="0" id="RUIMaster"&gt;
  &lt;/object&gt;
  &lt;/object&gt;
  &lt;form&gt;
  &lt;input id="id" type="hidden" value="" /&gt;
  &lt;/form&gt;
  &lt;/p&gt;
  &lt;iframe name="AAMain" style="margin: 0px; border: 0px; padding: 0px;" id="contents" src="rdaui_frame.htm" width="100%" height="100%" frameborder="0" /&gt;
  &lt;/body&gt;
  </code></pre>
  
  <p>I must access iframe with name <code>AAMain</code>.<br>
  Content of that iframe document looks like so:</p>
  
  <pre><code>&lt;frameset cols="135,*" border="0" frameborder="no" framespacing="0"&gt;
      &lt;frame name="Menu" scrolling="no" noresize marginwidth="0" marginheight="0" src="blank.htm"&gt;
      &lt;frameset rows="310,*,31"&gt;
          &lt;frame name="Top" noresize marginwidth="0" marginheight="0" src="blank.htm"&gt;
          &lt;frame name="Centre" noresize marginwidth="0" marginheight="0" src="blank.htm"&gt;
          &lt;frame name="Bottom" noresize marginwidth="0" marginheight="0" src="blank.htm"&gt;
      &lt;/frameset&gt;
  &lt;/frameset&gt;
  </code></pre>
  
  <p>So basically I must access <strong>frame</strong> name <strong>Centre</strong> inside <strong>iframe</strong> named <strong>AAMain</strong></p>
  
  <p>myDocument -> iframe(AAMain) -> frame(Centre) -> and then click on image</p>
  
  <p>I was trying to iterate over frames of <code>myDocument</code> but I get invalid cast exception.</p>
  
  <pre><code>try
  {
      FramesCollection frames = myDocument.frames;
      object index = 0;
      IHTMLWindow2 frame = (IHTMLWindow2)frames.item(ref index);
      var xx = (HTMLDocument)frame.document;
      MessageBox.Show(xx.body.innerHTML);
  }
  catch (Exception ex)
  {
      MessageBox.Show(ex.Message);
  }
  </code></pre>
  
  <p>even code like this:</p>
  
  <pre><code>MessageBox.Show(myDocument.frames.length.ToString());
  </code></pre>
  
  <p>gives me the same cast exception.</p>