2012-09-29 38 views
0

我有一个UI几个组合框有着相似的条目(数字)的一个长长的清单。当用户从一个组合框中选择一个项目时,我知道用户将从其他组合框中选择一个具有相似值(但可能不相同)的项目。因此,在用户选择了一个值后,为了避免强迫用户做大量滚动操作,我想“自动滚动”下一个组合框下拉到最后一个选定值的附近(当此下拉菜单还没有时一个选择)。理想情况下,我希望滚动位置设置为使最后选定的值出现在下拉列表的中间。如何设置一个WinForms组合框下拉滚动条的位置

到目前为止,我还试图通过设置在下落事件所选择的项目要做到这一点,但它有自己problems。有没有办法设置下拉的滚动位置而不必选择一个项目?

到目前为止,我已经试过这样:

[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)] 
private static extern IntPtr SendMessageCb(IntPtr hWnd, int msg, IntPtr wp, out COMBOBOXINFO lp); 

[DllImport("user32.dll")] 
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); 

// P/Invoke declarations 
private struct COMBOBOXINFO 
{ 
    public Int32 cbSize; 
    public RECT rcItem, rcButton; 
    public int buttonState; 
    public IntPtr hwndCombo, hwndEdit, hwndList; 
} 

private struct RECT 
{ 
    public int Left, Top, Right, Bottom; 
} 

private const int LVM_FIRST = 0x1000; 
private const int LVM_SCROLL = (LVM_FIRST + 20); 

private const int WM_VSCROLL = 0x0115; 
private const int SB_BOTTOM = 7; 
private const int SB_PAGEDOWN = 3; 

private void comboBox_DropDown(object sender, EventArgs e) 
{ 
    COMBOBOXINFO info = new COMBOBOXINFO(); 
    info.cbSize = Marshal.SizeOf(info); 
    SendMessageCb((sender as ComboBox).Handle, 0x164, IntPtr.Zero, out info); // seems to work 
    SendMessage(info.hwndList, WM_VSCROLL, (IntPtr)SB_PAGEDOWN, IntPtr.Zero); // does nothing 
    SendMessage(info.hwndList, LVM_SCROLL, IntPtr.Zero, (IntPtr) 50); // does nothing   
} 

然而,这似乎并没有工作。 COMBOBOXINFO结构似乎已正确填充,但SendMessage WM_VSCROLL和LVM_SCROLL不起作用。

+0

我不知道你想完全实现的话,但你为什么不只是重新选择列表,以便最后选择项目首次出现? (或者只有它的两个副本 - 一个在正常位置,一个在正常位置) –

+0

因为用户可能会选择与上次选择的项目不同的项目 - 但不同的项目将*关闭*到最后一个选定的项目。我试图选择最后一个项目,但就像我说的问题有其自己的问题(请参阅:http://stackoverflow.com/questions/12640438/detecting-user-selection-in-combobox-dropdownclosed-in -winforms) – Jimmy

回答

0

事实证明,使用WM_VSCROLL,LVM_SCROLL(以及调用SetScrollInfo())发送消息可用于设置ListView的滚动位置,该位置显示为ComboBox的下拉列表;问题出现在实际显示ListView之前引发的DropDown事件。我想到了这一点,因为在DropDown事件中调用时,GetScrollInfo()返回最小值,最大值为0。从DropDown被触发并在该延迟后调用GetScrollInfo()时,设置一个延迟1秒的计时器会返回一个合理的min,max;在延迟之后设置滚动位置也可以。

我显然不喜欢延迟,但我不认为有一个事件可用于ListView显示时?是否有可能创建一些事件?