views:

1497

answers:

2

How can you create a C# Winforms control which goes out of the bounds of its region? Such as a drop down box. Kind of like if you had a DropDownBox in a Small Sized Panel.

+2  A: 

I did something similiar to that recently, and I used a ListBox. The cool think about a listbox, is that you can display it anywhere you want to, even out of bounds of your control. That way, when you detect via a button click or whatever, that you need to display the DropDown that you want, just populate the ListBox and display it anywhere you want. I got the idea from here:

http://msdn.microsoft.com/en-us/library/aa480727.aspx

They show how to build a Custom DataGridView with filtering, and to display the filter values, they place a ListBox under the header cell.

BFree
+2  A: 

Windows Forms doesn't support windows like that well, it is pretty fundamentally incompatible with the designer. Here's some code to get you started. You can't use this control in the designer, it must be created at run-time. You also must call its Dispose() method yourself.

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

public class MyListBox : ListBox {
  private Control mParent;
  private Point mPos;
  private bool mInitialized;

  public MyListBox(Control parent) {
    mParent = parent;
    mInitialized = true;
    this.SetTopLevel(true);
    parent.LocationChanged += new EventHandler(parent_LocationChanged);
    mPos = mParent.Location;
  }

  public new Point Location {
    get { return mParent.PointToClient(this.Location); }
    set { 
      Point zero = mParent.PointToScreen(Point.Empty);
      base.Location = new Point(zero.X + value.X, zero.Y + value.Y);
    }
  }

  protected override Size DefaultSize {
    get {
      return mInitialized ? base.DefaultSize : Size.Empty;
    }
  }

  protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
    if (this.mInitialized)
      base.SetBoundsCore(x, y, width, height, specified);
  }

  void parent_LocationChanged(object sender, EventArgs e) {
    base.Location = new Point(base.Left + mParent.Left - mPos.X, base.Top + mParent.Top - mPos.Y);
    mPos = mParent.Location;
  }

  protected override CreateParams CreateParams {
    get {
      CreateParams cp = base.CreateParams;
      if (mParent != null && !DesignMode) {
        cp.Style = (int)(((long)cp.Style & 0xffff) | 0x90200000);
        cp.Parent = mParent.Handle;
        Point pos = mParent.PointToScreen(Point.Empty);
        cp.X = pos.X;
        cp.Y = pos.Y;
        cp.Width = base.DefaultSize.Width;
        cp.Height = base.DefaultSize.Height;
      }
      return cp;
    }
  }
}
Hans Passant
Tried it and it works great, but somehow it doesn't raise ListBox events like DrawItem and SelectedIndexChanged. Do you have any idea why?
Meidan Alon
See my response here: http://stackoverflow.com/questions/398176/listbox-with-overriden-createparams-doesnt-raise-item-events#398694
Hans Passant