Pergunta

Estou usando um ToolStripDropDown Controle para implementar a parte suspensa de um controle personalizado do tipo ComboBox. Para ser visualmente atraente, estou impondo um MaximumSize na suspensão e especificando manualmente a largura de cada ToolStripButton Dentro dele - o resultado é um pop -up que é a mesma largura que o controle que o ativa, com uma tampa na altura da altura da parte suspensa.

Exemplo (simplificado):

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));

Como você pode ver, as restrições no tamanho do pop -up são aplicadas, no entanto, os botões de rolagem para cima/para baixo não são exibidos e parece não haver como fazê -los aparecer. Não parece haver nenhum método ou propriedade dentro de ToolStripDropDown em relação ao deslocamento de rolagem ou um mecanismo para rolar um item específico em exibição (como EnsureVisible() sobre ListViewItem).

Como, então, posso obter o menu suspenso para rolar? Qualquer método seria suficiente, seja uma barra de rolagem, botões de rolagem ou até a roda do mouse.

(Aliás, eu tentei muitas vezes fazer controles semelhantes usando um Form Para a parte suspensa - apesar de tentar dezenas de soluções para impedir que o pop -up roube foco ou ganhe foco quando seus controles são clicados, isso parece ser um beco sem saída. Eu também descartei usando ToolStripControlHost, cujo controle hospedado ainda pode tirar o foco do formulário que o abriu.)

Foi útil?

Solução

Finalmente quebrou este. Ocorreu -me que ContextMenuStrip e ToolStripDropDownMenu são capazes do comportamento de rolagem automática que sua classe base, ToolStripDropDown, não pode fornecer. Inicialmente, evitei esses controles alternativos porque eles geralmente adicionam uma margem ampla. Isso pode ser removido via ShowImageMargin e ShowCheckMargin. Mesmo depois de fazer isso, permanece uma pequena margem (aproximadamente 5px). Isso pode ser removido substituindo o DefaultPadding propriedade:

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

Isso resulta em uma janela pop -up que pode conter qualquer tipo de item da pista de ferramentas, aplica MaximumSize, não tem margem e, o mais importante, não rouba o foco e não pode receber foco.

Outras dicas

Este é o seu inimigo:

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

É interno, você não pode substituí -lo. Você pode reviver sua abordagem de usar um formulário corrigindo o comportamento de roubo de foco. Cole isso na classe de formulário:

protected override bool ShowWithoutActivation
{
    get { return true; }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top