C# 如何强制组合框滚动到顶部?

C# 如何强制组合框滚动到顶部?,c#,.net,winforms,combobox,C#,.net,Winforms,Combobox,我有一个带有ComboBox属性的winformsToolStripComboBox。默认情况下,它似乎自动滚动到所选索引。请参见下面的屏幕截图: 在表单加载时,我将SelectedIndex设置为1,这就是需要发生的事情。但我希望列表中的第一项(SelectedIndex 0)可见,或者换句话说,自动滚动到最顶端。我找不到任何方法来强制组合框在默认情况下滚动到顶部,或者以编程方式这样做。ComboBox上有一个AutoScrolOffset属性,我已经尝试过了,但无论我将其设置为什么,它似乎

我有一个带有ComboBox属性的winformsToolStripComboBox。默认情况下,它似乎自动滚动到所选索引。请参见下面的屏幕截图:

在表单加载时,我将SelectedIndex设置为1,这就是需要发生的事情。但我希望列表中的第一项(SelectedIndex 0)可见,或者换句话说,自动滚动到最顶端。我找不到任何方法来强制组合框在默认情况下滚动到顶部,或者以编程方式这样做。ComboBox上有一个
AutoScrolOffset
属性,我已经尝试过了,但无论我将其设置为什么,它似乎都不起作用

正如我上面的截图所示,我想强制组合框(通过属性或方法调用)显示为第二张图片,其中顶部项目(所有-所有类别)可见,同时仍保持索引1处于选中状态


如何做到这一点?

打开下拉菜单时,将向下拉菜单中的列表发送一条消息。此消息负责设置列表中的顶部索引

您可以处理此消息并将其
WParam
更改为
Intptr.Zero
以始终使用
0
作为顶部索引

本机方法

下面是一个包含本机方法、结构和常量的类,用于为此操作组合框:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class NativeMethods
{
    [StructLayout(LayoutKind.Sequential)]
    public struct COMBOBOXINFO
    {
        public int cbSize;
        public RECT rcItem;
        public RECT rcButton;
        public int stateButton;
        public IntPtr hwndCombo;
        public IntPtr hwndEdit;
        public IntPtr hwndList;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left; public int Top; public int Right; public int Bottom;
    }
    [DllImport("user32.dll")]
    public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
    public class ListBoxHelper : NativeWindow
    {
        private const int LB_SETTOPINDEX = 0x0197;
        public ListBoxHelper(IntPtr hwnd) { this.AssignHandle(hwnd); }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == LB_SETTOPINDEX)
                m.WParam = IntPtr.Zero;
            base.WndProc(ref m);
        }
    }
}
组合框

下面是一个组合框,它的下拉列表始终打开,显示项0为顶部项:

public class MyComboBox : ComboBox
{
    NativeMethods.ListBoxHelper listBoxHelper;
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        var info = new NativeMethods.COMBOBOXINFO();
        info.cbSize = Marshal.SizeOf(info);
        NativeMethods.GetComboBoxInfo(this.Handle, ref info);
        listBoxHelper = new NativeMethods.ListBoxHelper(info.hwndList);
    }
}
ToolStripComboBox

ToolStripComboBox
在内部托管一个
ComboBox
。因此,解决方案类似:

public class MyToolStripComboBox : ToolStripComboBox
{
    public MyToolStripComboBox()
    {
        this.Control.HandleCreated += Control_HandleCreated;
    }
    NativeMethods.ListBoxHelper listBoxHelper;
    private void Control_HandleCreated(object sender, EventArgs e)
    {
        base.OnVisibleChanged(e);
        var info = new NativeMethods.COMBOBOXINFO();
        info.cbSize = Marshal.SizeOf(info);
        NativeMethods.GetComboBoxInfo(this.Control.Handle, ref info);
        listBoxHelper = new NativeMethods.ListBoxHelper(info.hwndList);
    }
}