title: How to handle events from embedded Excel.OleObjects or Excel.Shapes
body: <p>I'm working on <code>C#</code> and now <code>VB.NET</code> ports of an old <code>VBA</code> program.  It has lots of <code>MSForms/OleObjects</code> embedded in it like <code>CommandButton</code> or even images.  </p>
  
  <p>My first thought was to declare all the buttons as <code>Microsoft.Vbe.Interop.Forms.CommandButton</code>but that leads to a <code>COM</code> exception that the <code>System._COM type</code> can't be cast to <code>...Forms.CommandButton</code>.  If I try a more generic version of <a href="https://stackoverflow.com/questions/1200576/find-all-controls-on-msform-from-c-sharp">this solution</a>, I don't find any items, and if I try to go through all <code>VBComponet</code>s I note that they are all the sheets in the <code>workbook</code>, but none of the controls:</p>
  
  <pre><code>foreach (VBComponent xxx in Globals.ThisWorkbook.VBProject.VBComponents) {
      Interaction.MsgBox(xxx.Name);
      Interaction.MsgBox(xxx.ToString);
  }
  </code></pre>
  
  <p>Thus all of these controls are not in <code>.VBComponets</code>, but I can find them as <strong>OLEobjects</strong> in <code>thisworkbook.worksheets(n).OLEobjects</code> (this is counterintutive to me, but I probably don't understand the system to begin with).</p>
  
  <p><strong>How do I handle the Click action from such an object?</strong>  </p>
  
  <p>I'm assuming that I need to be using the <code>Excel.OLEObjectEvents_Event</code> interface, but I can't seem to figure out how.  If I try to make custom events with <code>delegates</code>, I don't seem to be able to assign them to <code>OleObjects</code>.  If I use <code>ActionClickEventHandler.CreateDelegate</code> I can get a huge variety of errors that makes me think that's a dead end.  </p>
  
  <p>The <a href="http://msdn.microsoft.com/en-us/library/office/microsoft.office.interop.excel.oleobject(v=office.15).aspx" rel="nofollow noreferrer">official documentation</a> from MS doesn't seem that helpful, though it did introduce me to the <a href="http://msdn.microsoft.com/en-us/library/office/microsoft.office.interop.excel._oleobject_members(v=office.15).aspx" rel="nofollow noreferrer">idea</a> of <code>Verb</code>, which I'm looking into.  So far that has only produced COM errors along the lines of "Application Failed to start."</p>
  
  <p>Even just trying to use one of the two standard events, <code>.GotFocus</code>, I always pull a 0x80040200 error.
  Example:</p>
  
  <pre><code>Excel.OLEObject ButtonCatcher = Globals.ThisWorkbook.Worksheets(1).OLEObjects("CommandButton1");
  ButtonCatcher.GotFocus += CommandButton1_Click;
  </code></pre>
  
  <p>Throws a COMException <code>Exception from HRESULT: 0x80040200</code> at the second line.  The button is enabled, which is I checked after looking up the <a href="http://msdn.microsoft.com/en-us/office/dd757489(v=vs.100).aspx" rel="nofollow noreferrer">code number from the office dev site.</a></p>
  
  <p>Trying a more <a href="https://social.msdn.microsoft.com/Forums/office/fr-FR/dee3ba0a-cc7c-4e9b-b469-ffbd42ea7295/invalidcastexception-unable-to-cast-com-object-of-type-systemcomobject-to-interface-type?forum=vsto" rel="nofollow noreferrer">generic approach</a> within the code for a sheet containing controls:</p>
  
  <pre><code>object CommandButtonStart = this.GetType().InvokeMember("CommandButton1", System.Reflection.BindingFlags.GetProperty, null, this, null);
  </code></pre>
  
  <blockquote>
    <p>Throws a Missing Method error.</p>
  </blockquote>
  
  <p>Any help is greatly appreciated, this seems like this should be obvious and I'm missing it.</p>
  
  <hr>
  
  <p>**Edit:  I have also found that I can cast these controls into <code>Excel.Shape</code> but that doesn't actually get me any closer to running a function or sub from the VSTO.  I'm playing with <code>Excel.Shape.OnAction</code> but this requires a VBA sub to be called.  Presumably, I could call a VBA sub which calls a sub from the VSTO as long as the VSTO was COM visible.  This seems really round-about and I'd only like to do it as a last resort.</p>