views:

42

answers:

2

I am using a ToolStripDropDown control to implement the dropdown portion of a custom ComboBox-like control. In order to be visually appealing, I am imposing a MaximumSize on the dropdown and manually specifying the width of each ToolStripButton within it - the result is a popup which is the same width as the control that activates it, with a cap on the height of the height of the dropdown portion.

Example (simplified):

ToolStripDropDown dropDown = new ToolStripDropDown();
dropDown.MaximumSize = new Size(200, 100);
dropDown.RenderMode = ToolStripRenderMode.System;
dropDown.AutoSize = true;

for (int i = 0; i < 50; i++) {
    ToolStripButton dropDownItem = (ToolStripButton)dropDown.Items.Add("Item " + i);
    dropDownItem.AutoSize = false;
    dropDownItem.Size = new Size(200, 20);
}

dropDown.Show(owningControl, new Point(0, owningControl.Height - 1));

As you can see, the constraints on the popup's size are applied, however the up/down scroll buttons are not displayed and there seems to be no way to make them appear. There do not appear to be any methods or properties within ToolStripDropDown regarding the scrolling offset or a mechanism to scroll a particular item into view (such as EnsureVisible() on ListViewItem).

How, then, can I get the dropdown to scroll? Any method would be sufficient, be it a scroll bar, scroll buttons or even the mouse-wheel.

(Incidentally, I have tried many times to make similar controls using a Form for the dropdown portion - despite trying dozens of solutions to prevent the popup from stealing focus or gaining focus when its controls are clicked, this seems to be a dead end. I have also ruled out using ToolStripControlHost, whose hosted control can still take focus away from the form that opened it.)

+1  A: 

This is your nemesis:

internal virtual bool RequiresScrollButtons
{
    get
    {
        return false;
    }
    set
    {
    }
}

It is internal, you cannot override it. You can revive your approach of using a Form by fixing the focus stealing behavior. Paste this into the form class:

protected override bool ShowWithoutActivation
{
    get { return true; }
}
Hans Passant
`ShowWithoutActivation` does not prevent the form's child controls from bringing the form into focus; for example, clicking a `TreeView` on the form will give focus to the popup form. All that `ShowWithoutActivation` does is stop the form from stealing focus as the form is initially displayed; it can receive focus at any point after that. In Vista and 7, this is very obvious because the drop shadow around the parent window changes.
Bradley Smith
I don't get this, it shouldn't get focus when the user clicks a button? Start a new question about it, this one is answered.
Hans Passant
From MSDN: "Use [ShowWithoutActivation] if you want to show a top-level window, but don't want to interrupt a user's work by taking the input focus away from the current window ... If your non-activated window needs to use UI controls, you should consider using the ToolStrip controls, such as ToolStripDropDown." - Like I said, ShowWithoutActivation only affects the first call to the form's Show() method. After that, it behaves like an ordinary form. No point asking again about this topic, it's been asked several times and never answered satisfactorarily.
Bradley Smith
A: 

Finally cracked this one. It occurred to me that ContextMenuStrip and ToolStripDropDownMenu are capable of the auto-scrolling behaviour which their base class, ToolStripDropDown, cannot provide. Initially, I avoided these alternative controls because they usually add a wide margin. This can be removed via ShowImageMargin and ShowCheckMargin. Even after doing this, a small (approx 5px) margin remains. This can be removed by overriding the DefaultPadding property:

public class MyDropDown : ToolStripDropDownMenu {

    protected override Padding DefaultPadding {
        get { return Padding.Empty; }
    }

    public MyDropDown() {
        ShowImageMargin = ShowCheckMargin = false;
        RenderMode = ToolStripRenderMode.System;
        MaximumSize = new Size(200, 150);
    }
}

// adding items and calling Show() remains the same as in the question

This results in a popup window which can contain any type of ToolStrip item, enforces MaximumSize, has no margin and, most importantly, does not steal focus and cannot receive focus.

Bradley Smith