merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ComboBox.cs
index 89bf462a095e3f93960b9b321e6ae56670a5a5e0..5c9d713b1307d32c6abae34a57b583abe2403a74 100644 (file)
@@ -22,8 +22,7 @@
 // Authors:
 //     Jordi Mas i Hernandez, jordi@ximian.com
 //     Mike Kestner  <mkestner@novell.com>
-//
-// NOT COMPLETE
+//     Daniel Nauck    (dna(at)mono-project(dot)de)
 
 using System;
 using System.Drawing;
@@ -37,10 +36,14 @@ using System.Runtime.InteropServices;
 
 namespace System.Windows.Forms
 {
-
        [DefaultProperty("Items")]
        [DefaultEvent("SelectedIndexChanged")]
        [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
+#if NET_2_0
+       [DefaultBindingProperty ("Text")]
+       [ClassInterface (ClassInterfaceType.AutoDispatch)]
+       [ComVisible(true)]
+#endif
        public class ComboBox : ListControl
        {
                private DrawMode draw_mode = DrawMode.Normal;
@@ -67,15 +70,18 @@ namespace System.Windows.Forms
                private Rectangle button_area;
                private Rectangle listbox_area;
                private const int button_width = 16;
+#if NET_2_0
+               private AutoCompleteStringCollection auto_complete_custom_source = null;
+               private AutoCompleteMode auto_complete_mode = AutoCompleteMode.None;
+               private AutoCompleteSource auto_complete_source = AutoCompleteSource.None;
+#endif
 
                [ComVisible(true)]
                public class ChildAccessibleObject : AccessibleObject {
-                       private ComboBox        owner;
-                       private IntPtr          handle;
 
-                       public ChildAccessibleObject (ComboBox owner, IntPtr handle) {
-                               this.owner = owner;
-                               this.handle = handle;
+                       public ChildAccessibleObject (ComboBox owner, IntPtr handle)
+                               : base (owner)
+                       {
                        }
 
                        public override string Name {
@@ -109,11 +115,33 @@ namespace System.Windows.Forms
                        add { base.BackgroundImageChanged += value; }
                        remove { base.BackgroundImageChanged -= value; }
                }
-               
-               public event DrawItemEventHandler DrawItem;             
-               public event EventHandler DropDown;             
-               public event EventHandler DropDownStyleChanged;         
-               public event MeasureItemEventHandler MeasureItem;
+
+               static object DrawItemEvent = new object ();
+               static object DropDownEvent = new object ();
+               static object DropDownStyleChangedEvent = new object ();
+               static object MeasureItemEvent = new object ();
+               static object SelectedIndexChangedEvent = new object ();
+               static object SelectionChangeCommittedEvent = new object ();
+
+               public event DrawItemEventHandler DrawItem {
+                       add { Events.AddHandler (DrawItemEvent, value); }
+                       remove { Events.RemoveHandler (DrawItemEvent, value); }
+               }
+
+               public event EventHandler DropDown {
+                       add { Events.AddHandler (DropDownEvent, value); }
+                       remove { Events.RemoveHandler (DropDownEvent, value); }
+               }
+
+               public event EventHandler DropDownStyleChanged {
+                       add { Events.AddHandler (DropDownStyleChangedEvent, value); }
+                       remove { Events.RemoveHandler (DropDownStyleChangedEvent, value); }
+               }
+
+               public event MeasureItemEventHandler MeasureItem {
+                       add { Events.AddHandler (MeasureItemEvent, value); }
+                       remove { Events.RemoveHandler (MeasureItemEvent, value); }
+               }
                
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -122,11 +150,83 @@ namespace System.Windows.Forms
                        remove { base.Paint -= value; }
                }
                
-               public event EventHandler SelectedIndexChanged;         
-               public event EventHandler SelectionChangeCommitted;
+               public event EventHandler SelectedIndexChanged {
+                       add { Events.AddHandler (SelectedIndexChangedEvent, value); }
+                       remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
+               }
+
+               public event EventHandler SelectionChangeCommitted {
+                       add { Events.AddHandler (SelectionChangeCommittedEvent, value); }
+                       remove { Events.RemoveHandler (SelectionChangeCommittedEvent, value); }
+               }
+
                #endregion Events
 
                #region Public Properties
+#if NET_2_0
+               [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               [Localizable (true)]
+               [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design,
+                        "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
+               public AutoCompleteStringCollection AutoCompleteCustomSource { 
+                       get {
+                               if(auto_complete_custom_source == null) {
+                                       auto_complete_custom_source = new AutoCompleteStringCollection ();
+                                       auto_complete_custom_source.CollectionChanged += new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
+                               }
+                               return auto_complete_custom_source;
+                       }
+                       set {
+                               if(auto_complete_custom_source == value)
+                                       return;
+
+                               if(auto_complete_custom_source != null) //remove eventhandler from old collection
+                                       auto_complete_custom_source.CollectionChanged -= new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
+
+                               auto_complete_custom_source = value;
+
+                               if(auto_complete_custom_source != null)
+                                       auto_complete_custom_source.CollectionChanged += new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
+                       }
+               }
+
+               [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               [DefaultValue (AutoCompleteMode.None)]
+               public AutoCompleteMode AutoCompleteMode {
+                       get { return auto_complete_mode; }
+                       set {
+                               if(auto_complete_mode == value)
+                                       return;
+
+                               if((value < AutoCompleteMode.None) || (value > AutoCompleteMode.SuggestAppend))
+                                       throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for AutoCompleteMode", value));
+
+                               auto_complete_mode = value;
+                       }
+               }
+
+               [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               [DefaultValue (AutoCompleteSource.None)]
+               public AutoCompleteSource AutoCompleteSource {
+                       get { return auto_complete_source; }
+                       set {
+                               if(auto_complete_source == value)
+                                       return;
+
+                               if(!Enum.IsDefined (typeof (AutoCompleteSource), value))
+                                       throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for AutoCompleteSource", value));
+
+                               auto_complete_source = value;
+                       }
+               }
+#endif
                public override Color BackColor {
                        get { return base.BackColor; }
                        set {
@@ -192,7 +292,9 @@ namespace System.Windows.Forms
 
                                if (dropdown_style == value)
                                        return;                                 
-                                                                       
+
+                               SuspendLayout ();
+
                                if (dropdown_style == ComboBoxStyle.Simple) {
                                        if (listbox_ctrl != null) {                                             
                                                Controls.RemoveImplicit (listbox_ctrl);
@@ -214,8 +316,10 @@ namespace System.Windows.Forms
                                        
                                        CreateComboListBox ();
 
-                                       if (IsHandleCreated)
+                                       if (IsHandleCreated) {
                                                Controls.AddImplicit (listbox_ctrl);
+                                               listbox_ctrl.Visible = true;
+                                       }
                                } else {
                                        show_dropdown_button = true;
                                        button_state = ButtonState.Normal;
@@ -235,10 +339,11 @@ namespace System.Windows.Forms
                                        }
                                }
                                
+                               ResumeLayout ();
                                OnDropDownStyleChanged (EventArgs.Empty);
                                
-                               Layout ();
-                               UpdateBounds ();
+                               LayoutComboBox ();
+                               UpdateComboBoxBounds ();
                                Refresh ();
                        }
                }
@@ -255,17 +360,22 @@ namespace System.Windows.Forms
                                        return;
                                        
                                if (value < 1)
-                                       throw new ArgumentException ("The DropDownWidth value is less than one");
+#if NET_2_0
+                                       throw new ArgumentOutOfRangeException ("DropDownWidth",
+                                               "The DropDownWidth value is less than one.");
+#else
+                                       throw new ArgumentException ("The DropDownWidth value is less than one.");
+#endif
 
-                               dropdown_width = value;                         
+                               dropdown_width = value;
                        }
                }
                
                [Browsable (false)]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]              
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public bool DroppedDown {
                        get { 
-                               if (dropdown_style == ComboBoxStyle.Simple)                             
+                               if (dropdown_style == ComboBoxStyle.Simple)
                                        return true;
                                
                                return dropped_down;
@@ -305,7 +415,7 @@ namespace System.Windows.Forms
                                        return;
 
                                integral_height = value;
-                               UpdateBounds ();
+                               UpdateComboBoxBounds ();
                                Refresh ();
                        }
                }
@@ -320,21 +430,29 @@ namespace System.Windows.Forms
                                return item_height;
                        }
                        set {
-                               if (value < 0)
-                                       throw new ArgumentException ("The item height value is less than zero");
+                               if (value < 1)
+#if NET_2_0
+                                       throw new ArgumentOutOfRangeException ("ItemHeight",
+                                               "The item height value is less than one.");
+#else
+                                       throw new ArgumentException ("The item height value is less than one.");
+#endif
 
                                item_height_specified = true;
                                item_height = value;
                                if (IntegralHeight)
-                                       UpdateBounds ();
-                               Layout ();
+                                       UpdateComboBoxBounds ();
+                               LayoutComboBox ();
                                Refresh ();
                        }
                }
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                [Localizable (true)]
-               [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]                
+               [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+#if NET_2_0
+               [MergableProperty (false)]
+#endif
                public ComboBox.ObjectCollection Items {
                        get { return items; }
                }
@@ -385,6 +503,9 @@ namespace System.Windows.Forms
                public override int SelectedIndex {
                        get { return selected_index; }
                        set {
+                               if (selected_index == value)
+                                       return;
+
                                if (value <= -2 || value >= Items.Count)
                                        throw new ArgumentOutOfRangeException ("Index of out range");
                                selected_index = value;
@@ -396,14 +517,15 @@ namespace System.Windows.Forms
                                                SetControlText (GetItemText (Items [value]));
                                }
 
-                               OnSelectedValueChanged (new EventArgs ());
-                               OnSelectedIndexChanged  (new EventArgs ());
-                               OnSelectedItemChanged (new EventArgs ());
                                if (DropDownStyle == ComboBoxStyle.DropDownList)
                                        Invalidate ();
 
                                if (listbox_ctrl != null)
                                        listbox_ctrl.HighlightedIndex = value;
+
+                               OnSelectedValueChanged (new EventArgs ());
+                               OnSelectedIndexChanged (new EventArgs ());
+                               OnSelectedItemChanged (new EventArgs ());
                        }
                }
 
@@ -445,7 +567,8 @@ namespace System.Windows.Forms
                                if (dropdown_style == ComboBoxStyle.DropDownList) 
                                        return 0;
                                
-                               return textbox_ctrl.SelectionLength;
+                               int result = textbox_ctrl.SelectionLength;
+                               return result == -1 ? 0 : result;
                        }
                        set {
                                if (dropdown_style == ComboBoxStyle.DropDownList) 
@@ -490,7 +613,7 @@ namespace System.Windows.Forms
                                SelectedIndex = -1;
                                if (sorted) {
                                        Items.Sort ();
-                                       Layout ();
+                                       LayoutComboBox ();
                                }
                        }
                }
@@ -531,6 +654,9 @@ namespace System.Windows.Forms
                #endregion Public Properties
 
                #region Public Methods
+#if NET_2_0
+               [Obsolete ("This method has been deprecated")]
+#endif
                protected virtual void AddItemsCore (object[] value)
                {
                        
@@ -681,8 +807,9 @@ namespace System.Windows.Forms
                        switch (DrawMode) {
                        case DrawMode.OwnerDrawFixed:
                        case DrawMode.OwnerDrawVariable:
-                               if (DrawItem != null)
-                                       DrawItem (this, e);
+                               DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
+                               if (eh != null)
+                                       eh (this, e);
                                break;
                        default:
                                ThemeEngine.Current.DrawComboBoxItem (this, e);
@@ -692,14 +819,16 @@ namespace System.Windows.Forms
 
                protected virtual void OnDropDown (EventArgs e)
                {
-                       if (DropDown != null)
-                               DropDown (this, e);
+                       EventHandler eh = (EventHandler)(Events [DropDownEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnDropDownStyleChanged (EventArgs e)
                {
-                       if (DropDownStyleChanged != null)
-                               DropDownStyleChanged (this, e);
+                       EventHandler eh = (EventHandler)(Events [DropDownStyleChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected override void OnFontChanged (EventArgs e)
@@ -715,9 +844,9 @@ namespace System.Windows.Forms
                        }
 
                        if (IntegralHeight)
-                               UpdateBounds ();
+                               UpdateComboBoxBounds ();
 
-                       Layout ();
+                       LayoutComboBox ();
                }
 
                protected override void OnForeColorChanged (EventArgs e)
@@ -770,13 +899,15 @@ namespace System.Windows.Forms
                {
                        base.OnHandleCreated (e);
 
-                       if (listbox_ctrl != null)
+                       if (listbox_ctrl != null) {
                                Controls.AddImplicit (listbox_ctrl);
-                       
+                               listbox_ctrl.Visible = true;
+                       }
+
                        if (textbox_ctrl != null)
                                Controls.AddImplicit (textbox_ctrl);
 
-                       Layout ();
+                       LayoutComboBox ();
                }
 
                protected override void OnHandleDestroyed (EventArgs e)
@@ -795,8 +926,9 @@ namespace System.Windows.Forms
 
                protected virtual void OnMeasureItem (MeasureItemEventArgs e)
                {
-                       if (MeasureItem != null)
-                               MeasureItem (this, e);
+                       MeasureItemEventHandler eh = (MeasureItemEventHandler)(Events [MeasureItemEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected override void OnParentBackColorChanged (EventArgs e)
@@ -806,7 +938,7 @@ namespace System.Windows.Forms
 
                protected override void OnResize (EventArgs e)
                {                       
-                       Layout ();
+                       LayoutComboBox ();
                        if (listbox_ctrl != null)
                                listbox_ctrl.CalcListBoxArea ();
                }
@@ -815,8 +947,9 @@ namespace System.Windows.Forms
                {
                        base.OnSelectedIndexChanged (e);
 
-                       if (SelectedIndexChanged != null)
-                               SelectedIndexChanged (this, e);
+                       EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnSelectedItemChanged (EventArgs e)
@@ -831,8 +964,9 @@ namespace System.Windows.Forms
 
                protected virtual void OnSelectionChangeCommitted (EventArgs e)
                {
-                       if (SelectionChangeCommitted != null)
-                               SelectionChangeCommitted (this, e);
+                       EventHandler eh = (EventHandler)(Events [SelectionChangeCommittedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected override void RefreshItem (int index)
@@ -844,6 +978,41 @@ namespace System.Windows.Forms
                                item_heights.Remove (Items [index]);
                }
 
+#if NET_2_0
+               protected override bool ProcessKeyEventArgs (ref Message m)
+               {
+                       return base.ProcessKeyEventArgs (ref m);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected override void OnKeyDown (KeyEventArgs e)
+               {
+                       base.OnKeyDown (e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected override void OnValidating (CancelEventArgs e)
+               {
+                       base.OnValidating (e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected override void OnTextChanged (EventArgs e)
+               {
+                       base.OnTextChanged (e);
+               }
+
+               protected override void OnMouseLeave (EventArgs e)
+               {
+                       base.OnMouseLeave (e);
+               }
+               
+               protected override void OnMouseEnter (EventArgs e)
+               {
+                       base.OnMouseEnter (e);
+               }
+#endif
+
                public void Select (int start, int length)
                {
                        if (start < 0)
@@ -942,13 +1111,20 @@ namespace System.Windows.Forms
                #endregion Public Methods
 
                #region Private Methods
+#if NET_2_0
+               void OnAutoCompleteCustomSourceChanged(object sender, CollectionChangeEventArgs e) {
+                       if(auto_complete_source == AutoCompleteSource.CustomSource) {
+                               //FIXME: handle add, remove and refresh events in AutoComplete algorithm.
+                       }
+               }
+#endif
 
                internal override bool InternalCapture {
                        get { return Capture; }
                        set {}
                }
                
-               void Layout ()
+               void LayoutComboBox ()
                {                       
                        int border = ThemeEngine.Current.Border3DSize.Width;
 
@@ -1053,8 +1229,6 @@ namespace System.Windows.Forms
                        button_state = ButtonState.Pushed;                              
                        if (dropdown_style == ComboBoxStyle.DropDownList)
                                Invalidate (text_area);
-
-                       OnDropDown (EventArgs.Empty);
                }
                
                internal void DropDownListBoxFinished ()
@@ -1227,10 +1401,15 @@ namespace System.Windows.Forms
                        process_textchanged_event = true;
                }
                
-               void UpdateBounds ()
+               void UpdateComboBoxBounds ()
                {
-                       if (requested_height != -1)
-                               SetBounds (0, 0, 0, requested_height, BoundsSpecified.Height);
+                       if (requested_height == -1)
+                               return;
+
+                       // Save the requested height since set bounds can destroy it
+                       int save_height = requested_height;
+                       SetBounds (0, 0, 0, requested_height, BoundsSpecified.Height);
+                       requested_height = save_height;
                }
 
                private void UpdatedItems ()
@@ -1420,8 +1599,8 @@ namespace System.Windows.Forms
 
                                if (owner.Sorted) {
                                        int index = 0;
-                                       foreach (string s in object_items) {
-                                               if (String.Compare (item as String, s) < 0) {
+                                       foreach (object o in object_items) {
+                                               if (String.Compare (item.ToString (), o.ToString ()) < 0) {
                                                        object_items.Insert (index, item);
                                                        return index;
                                                }
@@ -1512,34 +1691,31 @@ namespace System.Windows.Forms
                                        set { }
                                }
 
-                               public bool FireMouseDown (MouseEventArgs e) 
+                               public void FireMouseDown (MouseEventArgs e) 
                                {
-                                       if (Visible) {
-                                               e = TranslateEvent (e);
-                                               if (ClientRectangle.Contains (e.X, e.Y)) {
-                                                       OnMouseDown (e);
-                                                       return true;
-                                               }
-                                       }
-                                       return false;
+                                       if (!Visible) 
+                                               return;
+
+                                       e = TranslateEvent (e);
+                                       OnMouseDown (e);
                                }       
                                
                                public void FireMouseUp (MouseEventArgs e) 
                                {
-                                       if (Visible) {
-                                               e = TranslateEvent (e);
-                                               if (ClientRectangle.Contains (e.X, e.Y))
-                                                       OnMouseUp (e);
-                                       }
+                                       if (!Visible)
+                                               return;
+
+                                       e = TranslateEvent (e);
+                                       OnMouseUp (e);
                                }
                                
                                public void FireMouseMove (MouseEventArgs e) 
                                {
-                                       if (Visible) {
-                                               e = TranslateEvent (e);
-                                               if (ClientRectangle.Contains (e.X, e.Y))
-                                                       OnMouseMove (e);
-                                       }
+                                       if (!Visible)
+                                               return;
+
+                                       e = TranslateEvent (e);
+                                       OnMouseMove (e);
                                }                       
                                
                                MouseEventArgs TranslateEvent (MouseEventArgs e)
@@ -1561,6 +1737,9 @@ namespace System.Windows.Forms
                                SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
                                SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
 
+                               this.is_visible = false;
+                               Hwnd.ObjectFromHandle (this.Handle).no_activate = true;
+
                                if (owner.DropDownStyle == ComboBoxStyle.Simple)
                                        InternalBorderStyle = BorderStyle.Fixed3D;
                                else
@@ -1634,6 +1813,8 @@ namespace System.Windows.Forms
                                        }
                                }
                                
+                               page_size = height / owner.ItemHeight;
+
                                if (owner.Items.Count <= owner.MaxDropDownItems) {                                      
                                        if (vscrollbar_ctrl != null)
                                                vscrollbar_ctrl.Visible = false;
@@ -1653,7 +1834,11 @@ namespace System.Windows.Forms
                                                        
                                        vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - BorderWidth - 1, 0);
 
-                                       vscrollbar_ctrl.Maximum = owner.Items.Count - (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items);
+                                       vscrollbar_ctrl.Maximum = owner.Items.Count - 2;
+                                       int large = (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items) - 1;
+                                       if (large < 0)
+                                               large = 0;
+                                       vscrollbar_ctrl.LargeChange = large;
                                        show_scrollbar = vscrollbar_ctrl.Visible = true;
 
                                        int hli = HighlightedIndex;
@@ -1672,7 +1857,6 @@ namespace System.Windows.Forms
                                        textarea_drawable.Width -= vscrollbar_ctrl.Width;
 
                                last_item = LastVisibleItem ();
-                               page_size = textarea_drawable.Height / owner.ItemHeight;
                        }                       
 
                        private void Draw (Rectangle clip, Graphics dc)
@@ -1711,7 +1895,7 @@ namespace System.Windows.Forms
                                        if (highlighted_index == value)
                                                return;
 
-                                       if (highlighted_index != -1)
+                                       if (highlighted_index != -1 && highlighted_index < this.owner.Items.Count)
                                                Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
                                        highlighted_index = value;
                                        if (highlighted_index != -1)
@@ -1790,10 +1974,23 @@ namespace System.Windows.Forms
                                Invalidate ();
                        }                       
 
+                       bool scrollbar_grabbed = false;
+
+                       bool InScrollBar {
+                               get {
+                                       if (vscrollbar_ctrl == null || !vscrollbar_ctrl.is_visible)
+                                               return false;
+
+                                       return vscrollbar_ctrl.Bounds.Contains (PointToClient (Control.MousePosition));
+                               }
+                       }
+
                        protected override void OnMouseDown (MouseEventArgs e)
                        {
-                               if (vscrollbar_ctrl != null)
+                               if (InScrollBar) {
                                        vscrollbar_ctrl.FireMouseDown (e);
+                                       scrollbar_grabbed = true;
+                               }
                        }
 
                        protected override void OnMouseMove (MouseEventArgs e)
@@ -1801,33 +1998,38 @@ namespace System.Windows.Forms
                                if (owner.DropDownStyle == ComboBoxStyle.Simple)
                                        return;
 
+                               if (scrollbar_grabbed || (!Capture && InScrollBar)) {
+                                       vscrollbar_ctrl.FireMouseMove (e);
+                                       return;
+                               }
+
                                Point pt = PointToClient (Control.MousePosition);
                                int index = IndexFromPointDisplayRectangle (pt.X, pt.Y);
 
-                               if (index != -1) {
+                               if (index != -1)
                                        HighlightedIndex = index;
-                                       return;
-                               }
-                               
-                               if (vscrollbar_ctrl != null)
-                                       vscrollbar_ctrl.FireMouseMove (e);
                        }
                        
                        protected override void OnMouseUp (MouseEventArgs e)
                        {
                                int index = IndexFromPointDisplayRectangle (e.X, e.Y);
 
+                               if (scrollbar_grabbed) {
+                                       vscrollbar_ctrl.FireMouseUp (e);
+                                       scrollbar_grabbed = false;
+                                       if (index != -1)
+                                               HighlightedIndex = index;
+                                       return;
+                               }
+
                                if (index == -1) {                                      
-                                       if (vscrollbar_ctrl == null || !vscrollbar_ctrl.FireMouseDown (e))
-                                               HideWindow ();
-                               } else {
-                                       owner.OnSelectionChangeCommitted (new EventArgs ());
-                                       owner.SelectedIndex = index;
-                                       HideWindow ();
+                                       HideWindow ();
+                                       return;
                                }
 
-                               if (vscrollbar_ctrl != null)
-                                       vscrollbar_ctrl.FireMouseUp (e);
+                               owner.SelectedIndex = index;
+                               owner.OnSelectionChangeCommitted (new EventArgs ());
+                               HideWindow ();
                        }
 
                        internal override void OnPaintInternal (PaintEventArgs pevent)
@@ -1860,7 +2062,7 @@ namespace System.Windows.Forms
                                if (delta == 0 || vscrollbar_ctrl == null || !vscrollbar_ctrl.Visible)
                                        return;
 
-                               int max = vscrollbar_ctrl.Maximum;//- (page_size) + 1;
+                               int max = owner.Items.Count - page_size;
 
                                int val = vscrollbar_ctrl.Value + delta;
                                if (val > max)
@@ -1904,3 +2106,4 @@ namespace System.Windows.Forms
        }
 }
 
+