title: Custom draw dropdown panel outside Control bounds
body: <p>I seem to have picked up an "unclear what I'm asking" vote. I want to custom draw a combo box style control. The pop open section needs to draw outside the bounds of the control itself. I cannot use combo box - think something similar to the gallery control in the Word ribbon.</p>
  
  <p>I have thought of 2 approaches:</p>
  
  <ul>
  <li>Passing the pop open panel back up to the form to render.</li>
  <li>Using a borderless, frameless Form or NativeWindow.</li>
  </ul>
  
  <p>The latter also allows the drop down to escape the bounds of the window, which may be of use, but is not absolutely essential.</p>
  
  <p>Are there any other approaches to this, and which do you think is best?</p>
  
  <p>Thanks.</p>
  
  <hr>
  
  <p><strong>ORIGINAL QUESTION:</strong></p>
  
  <p>I'm writing a winforms based custom draw UI library for a small project. All is largely going well, but I have a slight structural issue with drop downs leaving the bounds of the <code>Graphics</code> object.</p>
  
  <p>Most of the controls are being done with pure custom draw and redraw event model but the overall interface is being laid out using winforms <code>Dock</code>, <code>Width</code>, <code>Height</code> etc.</p>
  
  <p>I've added a dropdown, but obviously when the bounds of the drop down section of it exceed the bounds of the graphics object for the layout <code>Panel</code>, it is cut off. </p>
  
  <p>(I had expected to find something similar to this on SO already, but haven't managed.)</p>
  
  <p>I've worked around this by having the form control the drawing of the drop down overlay, but what with the custom mouse handler and everything else, the form is starting to feel rather overburdened.</p>
  
  <p>I have tried to store references to <code>Graphics</code> objects but found that using them outside of <code>OnPaint</code> being raised is.. temperamental.</p>
  
  <p>Simplified code example of current model follows. This code doesn't run in any useful way alone, but shows the approach used to display the overlays.</p>
  
  <pre><code>public interface IDropDownOverlay
  {
      DropDown DropDown { get; }
  
      /// &lt;summary&gt;can only link to a single form at once - not a problem.&lt;/summary&gt;
      DropDownDrawForm Form { get; set; }
  
      void MouseUpdate(MouseEventArgs e);
  
      void Render(Graphics gfx);
  
      void Show();
  }
  
  public class DropDown
  {
      private DropDownOverlay overlay;
  }
  
  public class DropDownDrawForm : Form
  {
      /* lots of other things... */
  
      private List&lt;IDropDownOverlay&gt; overlays;
  
      public void HideOverlay(IDropDownOverlay overlay)
      {
          if (this.overlays.Contains(overlay))
          {
              this.overlays.Remove(overlay);
              this.Invalidate();
          }
      }
  
      public void ShowOverlay(IDropDownOverlay overlay)
      {
          if (!this.overlays.Contains(overlay))
          {
              overlay.Form = this;
              this.overlays.Add(overlay);
              this.Invalidate();
          }
      }
  
      protected override void OnPaint(PaintEventArgs e)
      {
          base.OnPaint(e);
  
          foreach (IDropDownOverlay overlay in this.overlays)
          {
              overlay.Render(e.Graphics);
          }
      }
  
      private void MouseUpdate(MouseEventArgs e)
      {
          foreach (IDropDownOverlay overlay in this.overlays)
          {
              overlay.MouseUpdate(e);
          }
      }
  }
  
  public class DropDownOverlay : IDropDownOverlay
  {
      public DropDown DropDown { get; }
  
      public DropDownDrawForm Form { get; set; }
  
      public void Hide()
      {
          this.Form.HideOverlay(this);
      }
  
      public void MouseUpdate(MouseEventArgs e)
      {
          // Informs the form to redraw the area of the control.
  
          if (stateChanged)
          {
              this.Invalidate(); // (method to invalidate just this area)
          }
      }
  
      public void Show()
      {
          this.Form.ShowOverlay(this);
      }
  
      public void Render(Graphics gfx)
      {
      }
  }
  </code></pre>
  
  <p>Obviously there are lots of bits missing from this, but it should show the approach I'm using at least.</p>
  
  <p>Any suggestions to prevent me having to pass this back and forth between the form?</p>
  
  <p>Thanks</p>
  
  <hr>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>Just to be absolutely clear, the problem is drawing the "popup" section of the dropdown not the dropdown itself. (ComboBox used here to demonstrate)</p>
  
  <p><img src="https://i.stack.imgur.com/r9zfz.png" alt="DropDown Control Areas"></p>
  
  <p>I've also since remembered that a small window forces a ComboBox outside the bounds of the <em>window</em>.</p>
  
  <p><img src="https://i.stack.imgur.com/QhIRn.png" alt="ComboBox outside window bounds"></p>
  
  <p>The drop shadow on it looks suspiciously like <code>CS_DROPSHADOW</code> from <code>CreateParams</code> to me - could I use a <code>NativeWindow</code> subclass to handle this instead?</p>