2012-09-29 1 views
0

J'ai plusieurs comboboxes dans une interface utilisateur chacune avec une longue liste d'entrées similaires (nombres). Lorsque l'utilisateur sélectionne un élément de l'une des listes déroulantes, je sais que l'utilisateur choisira une entrée avec une valeur similaire (mais probablement pas la même) des autres combobox. Ainsi, après que l'utilisateur ait sélectionné une valeur, pour éviter de forcer l'utilisateur à faire beaucoup de défilement, je voudrais "autoscroller" la liste déroulante suivante au voisinage de la dernière valeur sélectionnée (quand cette liste déroulante n'a pas déjà une sélection). Idéalement, j'aimerais que la position de défilement soit telle que la dernière valeur sélectionnée apparaisse au milieu de la liste déroulante. Jusqu'à présent, j'ai essayé de le faire en définissant l'élément sélectionné dans l'événement dropdown, mais cela a son propre problems. Y at-il un moyen de définir la position de défilement de la liste déroulante sans avoir à sélectionner un élément?Comment faire pour définir la position de défilement dans une liste déroulante de winforms combobox

Jusqu'à présent, j'ai essayé:

[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   
} 

Cependant, cela ne semble pas fonctionner. La structure COMBOBOXINFO semble être remplie correctement, mais SendMessage WM_VSCROLL et LVM_SCROLL n'ont aucun effet.

+0

Je ne suis pas sûr de ce que vous essayez d'accomplir complètement, mais pourquoi ne réorganisez-vous pas simplement la liste de sélection de sorte que le dernier élément choisi apparaisse en premier? (ou en avoir deux copies - une en haut et l'autre en mode normal) –

+0

Parce que l'utilisateur choisira probablement un article différent du dernier article sélectionné - mais cet article différent sera * proche * du dernier Élément sélectionné. J'ai essayé de sélectionner le dernier élément, mais comme je le dis dans la question qui a son propre problème (voir ici: http://stackoverflow.com/questions/12640438/detection-user-selection-in-combobox-dropdownclosed-in -formations – Jimmy

Répondre

0

Il s'avère que l'envoi d'un message avec WM_VSCROLL, LVM_SCROLL (ainsi que l'appel SetScrollInfo()) fonctionnent pour définir la position de défilement de ListView affichée comme une liste déroulante par un ComboBox; le problème est avec l'événement DropDown, qui est levé avant que le ListView ait été réellement montré. Je l'ai compris car GetScrollInfo() renvoie un min, max de 0 lorsqu'il est appelé dans l'événement DropDown. Définir une minuterie pour un délai d'une seconde à partir de quand DropDown a été déclenché et appel GetScrollInfo() après ce délai renvoie un min, max sensible; le réglage de la position de défilement après ce délai fonctionne également.

Je ne suis évidemment pas friands du retard, mais je ne pense pas qu'il y ait un événement disponible pour quand le ListView a été montré? Est-il possible de créer un événement?

Questions connexes