* ComboBox.cs: page_size as well as vscrollbar.LargeChange should be 1
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ComboBox.cs
index d34a33305fd920aeed80a7a80a065e54fa392d9c..36a07edaa16737eb513e20cee7714d519d11d4fe 100644 (file)
@@ -70,6 +70,7 @@ namespace System.Windows.Forms
                private Rectangle button_area;
                private Rectangle listbox_area;
                private const int button_width = 16;
+               bool drop_down_button_entered;
 #if NET_2_0
                private AutoCompleteStringCollection auto_complete_custom_source = null;
                private AutoCompleteMode auto_complete_mode = AutoCompleteMode.None;
@@ -98,7 +99,7 @@ namespace System.Windows.Forms
                        items = new ObjectCollection (this);
                        DropDownStyle = ComboBoxStyle.DropDown;
                        item_height = FontHeight + 2;
-                       BackColor = ThemeEngine.Current.ColorWindow;
+                       background_color = ThemeEngine.Current.ColorWindow;
                        border_style = BorderStyle.None;
 
 #if NET_2_0
@@ -111,6 +112,7 @@ namespace System.Windows.Forms
                        MouseUp += new MouseEventHandler (OnMouseUpCB);
                        MouseMove += new MouseEventHandler (OnMouseMoveCB);
                        MouseWheel += new MouseEventHandler (OnMouseWheelCB);
+                       MouseLeave += new EventHandler (OnMouseLeave);
                        KeyDown +=new KeyEventHandler(OnKeyDownCB);
                }
 
@@ -400,11 +402,14 @@ namespace System.Windows.Forms
                                        show_dropdown_button = false;
                                        
                                        CreateComboListBox ();
-
-                                       if (IsHandleCreated) {
-                                               Controls.AddImplicit (listbox_ctrl);
-                                               listbox_ctrl.Visible = true;
-                                       }
+                                       Controls.AddImplicit (listbox_ctrl);
+                                       listbox_ctrl.Visible = true;
+
+                                       // This should give us a 150 default height
+                                       // for Simple mode if size hasn't been set
+                                       // (DefaultSize doesn't work for us in this case)
+                                       if (requested_height == -1)
+                                               requested_height = 150;
                                } else {
                                        show_dropdown_button = true;
                                        button_state = ButtonState.Normal;
@@ -417,7 +422,9 @@ namespace System.Windows.Forms
                                                textbox_ctrl.Text = GetItemText (selected_item);
                                        textbox_ctrl.BorderStyle = BorderStyle.None;
                                        textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
+                                       textbox_ctrl.KeyPress += new KeyPressEventHandler (OnTextKeyPress);
                                        textbox_ctrl.Click += new EventHandler (OnTextBoxClick);
+                                       textbox_ctrl.ContextMenu = ContextMenu;
 
                                        if (IsHandleCreated == true)
                                                Controls.AddImplicit (textbox_ctrl);
@@ -522,7 +529,7 @@ namespace System.Windows.Forms
                public int ItemHeight {
                        get {
                                if (item_height == -1) {
-                                       SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
+                                       SizeF sz = TextRenderer.MeasureString ("The quick brown Fox", Font);
                                        item_height = (int) sz.Height;
                                }
                                return item_height;
@@ -615,7 +622,7 @@ namespace System.Windows.Forms
                [Browsable (false)]
                public int PreferredHeight {
                        get {
-                               return ItemHeight + 5;
+                               return ItemHeight + 6;
                        }
                }
 
@@ -628,7 +635,7 @@ namespace System.Windows.Forms
                                        return;
 
                                if (value <= -2 || value >= Items.Count)
-                                       throw new ArgumentOutOfRangeException ("Index of out range");
+                                       throw new ArgumentOutOfRangeException ("SelectedIndex");
                                selected_index = value;
 
                                if (dropdown_style != ComboBoxStyle.DropDownList) {
@@ -668,9 +675,16 @@ namespace System.Windows.Forms
                public string SelectedText {
                        get {
                                if (dropdown_style == ComboBoxStyle.DropDownList)
-                                       return "";
+                                       return string.Empty;
                                        
-                               return textbox_ctrl.SelectedText;
+                               string retval = textbox_ctrl.SelectedText;
+                               
+#if ONLY_1_1
+                               // On 1.1, the textbox will return null, combobox returns ""
+                               if (retval == null && !textbox_ctrl.IsHandleCreated)
+                                       return string.Empty;
+#endif                                 
+                               return retval;
                        }
                        set {
                                if (dropdown_style == ComboBoxStyle.DropDownList)
@@ -942,6 +956,9 @@ namespace System.Windows.Forms
                protected override void OnBackColorChanged (EventArgs e)
                {
                        base.OnBackColorChanged (e);
+
+                       if (textbox_ctrl != null)
+                               textbox_ctrl.BackColor = BackColor;
                }
 
                protected override void OnDataSourceChanged (EventArgs e)
@@ -961,11 +978,17 @@ namespace System.Windows.Forms
                {
                        base.OnDisplayMemberChanged (e);
 
-                       if (DataManager == null || !IsHandleCreated)
+                       if (DataManager == null)
+                               return;
+
+                       if (selected_index != -1 && DropDownStyle != ComboBoxStyle.DropDownList)
+                               SetControlText (GetItemText (Items [selected_index]));
+
+                       if (!IsHandleCreated)
                                return;
 
-                       BindDataItems ();
                        SelectedIndex = DataManager.Position;
+                       Invalidate ();
                }
 
                protected virtual void OnDrawItem (DrawItemEventArgs e)
@@ -1014,7 +1037,7 @@ namespace System.Windows.Forms
                                textbox_ctrl.Font = Font;
                        
                        if (!item_height_specified) {
-                               SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
+                               SizeF sz = TextRenderer.MeasureString ("The quick brown Fox", Font);
                                item_height = (int) sz.Height;
                        }
 
@@ -1027,6 +1050,8 @@ namespace System.Windows.Forms
                protected override void OnForeColorChanged (EventArgs e)
                {
                        base.OnForeColorChanged (e);
+                       if (textbox_ctrl != null)
+                               textbox_ctrl.ForeColor = ForeColor;
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -1065,6 +1090,7 @@ namespace System.Windows.Forms
                                textbox_ctrl.SetSelectable (true);
                                textbox_ctrl.ActivateCaret (false);
                                textbox_ctrl.ShowSelection = false;
+                               textbox_ctrl.SelectionLength = 0;
                        }
 
                        base.OnLostFocus (e);
@@ -1074,15 +1100,13 @@ namespace System.Windows.Forms
                {
                        base.OnHandleCreated (e);
 
-                       if (listbox_ctrl != null) {
-                               Controls.AddImplicit (listbox_ctrl);
-                               listbox_ctrl.Visible = true;
-                       }
+                       SetBounds (Left, Top, Width, PreferredHeight, BoundsSpecified.None);
 
                        if (textbox_ctrl != null)
                                Controls.AddImplicit (textbox_ctrl);
 
                        LayoutComboBox ();
+                       UpdateComboBoxBounds ();
                }
 
                protected override void OnHandleDestroyed (EventArgs e)
@@ -1092,9 +1116,19 @@ namespace System.Windows.Forms
 
                protected override void OnKeyPress (KeyPressEventArgs e)
                {
-                       // int index = FindStringCaseInsensitive (e.KeyChar.ToString (), SelectedIndex);
-                       //if (index != -1)
-                       //      SelectedIndex = index;
+                       if (dropdown_style == ComboBoxStyle.DropDownList) {
+                               int index = FindStringCaseInsensitive (e.KeyChar.ToString (), SelectedIndex + 1);
+                               if (index != -1) {
+                                       SelectedIndex = index;
+                                       if (DroppedDown) { //Scroll into view
+                                               if (SelectedIndex >= listbox_ctrl.LastVisibleItem ())
+                                                       listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.LastVisibleItem () + 1);
+                                               // Or, selecting an item earlier in the list.
+                                               if (SelectedIndex < listbox_ctrl.FirstVisibleItem ())
+                                                       listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.FirstVisibleItem ());
+                                       }
+                               }
+                       }
 
                        base.OnKeyPress (e);
                }
@@ -1146,13 +1180,20 @@ namespace System.Windows.Forms
                protected override void RefreshItem (int index)
                {
                        if (index < 0 || index >= Items.Count)
-                               throw new ArgumentOutOfRangeException ("Index of out range");
+                               throw new ArgumentOutOfRangeException ("index");
                                
                        if (draw_mode == DrawMode.OwnerDrawVariable)
                                item_heights.Remove (Items [index]);
                }
 
 #if NET_2_0
+               protected override void RefreshItems ()
+               {
+                       for (int i = 0; i < Items.Count; i++) {
+                               RefreshItem (i);
+                       }
+               }
+
                public override void ResetText ()
                {
                        Text = String.Empty;
@@ -1208,6 +1249,13 @@ namespace System.Windows.Forms
                }
 #endif
 
+#if NET_2_0
+               protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
+               {
+                       base.ScaleControl (factor, specified);
+               }
+#endif
+
                public void Select (int start, int length)
                {
                        if (start < 0)
@@ -1321,7 +1369,7 @@ namespace System.Windows.Forms
                
                void LayoutComboBox ()
                {
-                       int border = ThemeEngine.Current.Border3DSize.Width + 1;
+                       int border = ThemeEngine.Current.Border3DSize.Width;
 
                        text_area = ClientRectangle;
                        text_area.Height = PreferredHeight;
@@ -1358,9 +1406,10 @@ namespace System.Windows.Forms
                        }
 
                        if (textbox_ctrl != null) {
-                               textbox_ctrl.Location = new Point (text_area.X + border, text_area.Y + border);
-                               textbox_ctrl.Width = text_area.Width - button_area.Width - border * 2;
-                               textbox_ctrl.Height = text_area.Height - border * 2;
+                               int text_border = border + 1;
+                               textbox_ctrl.Location = new Point (text_area.X + text_border, text_area.Y + text_border);
+                               textbox_ctrl.Width = text_area.Width - button_area.Width - text_border * 2;
+                               textbox_ctrl.Height = text_area.Height - text_border * 2;
                        }
 
                        if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
@@ -1386,6 +1435,9 @@ namespace System.Windows.Forms
                        is_flat = style == FlatStyle.Flat || style == FlatStyle.Popup;
 #endif
 
+                       if (!Enabled)
+                               dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), bounds);
+
                        if (DropDownStyle == ComboBoxStyle.Simple)
                                dc.FillRectangle (theme.ResPool.GetSolidBrush (Parent.BackColor), ClientRectangle);
 
@@ -1420,21 +1472,38 @@ namespace System.Windows.Forms
                        }
                        
                        if (show_dropdown_button) {
-                               dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area);
+                               ButtonState current_state;
+                               if (is_enabled)
+                                       current_state = button_state;
+                               else
+                                       current_state = ButtonState.Inactive;
+
+                               if (is_flat || theme.ComboBoxNormalDropDownButtonHasTransparentBackground (this, current_state))
+                                       dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area);
 
-                               if (!is_enabled)
-                                       button_state = ButtonState.Inactive;
-                               
                                if (is_flat) {
-                                       theme.DrawFlatStyleComboButton (dc, button_area, button_state);
+                                       theme.DrawFlatStyleComboButton (dc, button_area, current_state);
                                } else {
-                                       theme.CPDrawComboButton (dc, button_area, button_state);
+                                       theme.ComboBoxDrawNormalDropDownButton (this, dc, clip, button_area, current_state); 
                                }
                        }
                }
 
+               internal bool DropDownButtonEntered {
+                       get { return drop_down_button_entered; }
+                       private set {
+                               if (drop_down_button_entered == value)
+                                       return;
+                               drop_down_button_entered = value;
+                               if (ThemeEngine.Current.ComboBoxDropDownButtonHasHotElementStyle (this))
+                                       Invalidate (button_area);
+                       }
+               }
+
                internal void DropDownListBox ()
                {
+                       DropDownButtonEntered = false;
+
                        if (DropDownStyle == ComboBoxStyle.Simple)
                                return;
                        
@@ -1443,6 +1512,8 @@ namespace System.Windows.Forms
 
                        listbox_ctrl.Location = PointToScreen (new Point (text_area.X, text_area.Y + text_area.Height));
 
+                       FindMatchOrSetIndex(SelectedIndex);
+
                        if (listbox_ctrl.ShowWindow ())
                                dropped_down = true;
 
@@ -1462,6 +1533,17 @@ namespace System.Windows.Forms
 #if NET_2_0
                        OnDropDownClosed (EventArgs.Empty);
 #endif
+                       /*
+                        * Apples X11 looses override-redirect when doing a Unmap/Map on a previously mapped window
+                        * this causes the popup to appear under the main form.  This is horrible but necessary
+                        */
+                        
+                        // If the user opens a new form in an event, it will close our dropdown,
+                        // so we need a null check here
+                        if (listbox_ctrl != null) {
+                               listbox_ctrl.Dispose ();
+                               listbox_ctrl = null;
+                       }
                }
                
                private int FindStringCaseInsensitive (string search)
@@ -1479,11 +1561,16 @@ namespace System.Windows.Forms
                        return -1;
                }
 
+               // Search in the list for the substring, starting the search at the list 
+               // position specified, the search wraps thus covering all the list.
                internal int FindStringCaseInsensitive (string search, int start_index)
                {
                        if (search.Length == 0) {
                                return -1;
                        }
+                       // Accept from first item to after last item. i.e. all cases of (SelectedIndex+1).
+                       if (start_index < 0 || start_index > Items.Count)
+                               throw new ArgumentOutOfRangeException("start_index");
 
                        for (int i = 0; i < Items.Count; i++) {
                                int index = (i + start_index) % Items.Count;
@@ -1494,35 +1581,127 @@ namespace System.Windows.Forms
                        return -1;
                }
 
+               internal override bool IsInputCharInternal (char charCode)
+               {
+                       return true;
+               }
+
+               internal override ContextMenu ContextMenuInternal {
+                       get {
+                               return base.ContextMenuInternal;
+                       }
+                       set {
+                               base.ContextMenuInternal = value;
+                               if (textbox_ctrl != null) {
+                                       textbox_ctrl.ContextMenu = value;
+                               }
+                       }
+               }
+
+               internal void RestoreContextMenu ()
+               {
+                       textbox_ctrl.RestoreContextMenu ();
+               }
+
                private void OnKeyDownCB(object sender, KeyEventArgs e)
                {
                        if (Items.Count == 0)
                                return;
 
+                       int offset;
                        switch (e.KeyCode) 
                        {
                                case Keys.Up:
-                                       SelectedIndex = Math.Max(SelectedIndex-1, 0);
+                                       FindMatchOrSetIndex(Math.Max(SelectedIndex - 1, 0));
+
+                                       if (DroppedDown)
+                                               if (SelectedIndex < listbox_ctrl.FirstVisibleItem ())
+                                                       listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.FirstVisibleItem ());
                                        break;
        
                                case Keys.Down:
-                                       SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1);
+                                       if ((e.Modifiers & Keys.Alt) == Keys.Alt)
+                                               DropDownListBox ();
+                                       else
+                                               FindMatchOrSetIndex(Math.Min(SelectedIndex + 1, Items.Count - 1));
+                                               
+                                       if (DroppedDown)
+                                               if (SelectedIndex >= listbox_ctrl.LastVisibleItem ())
+                                                       listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.LastVisibleItem () + 1);
                                        break;
                                
                                case Keys.PageUp:
-                                       if (listbox_ctrl != null)
-                                               SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0);
+                                       offset = listbox_ctrl == null ? MaxDropDownItems - 1 : listbox_ctrl.page_size - 1;
+                                       if (offset < 1)
+                                               offset = 1;
+
+                                       SelectedIndex = Math.Max (SelectedIndex - offset, 0);
+
+                                       if (DroppedDown)
+                                               if (SelectedIndex < listbox_ctrl.FirstVisibleItem ())
+                                                       listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.FirstVisibleItem ());
                                        break;
        
                                case Keys.PageDown:
-                                       if (listbox_ctrl != null)
-                                               SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1);
+                                       if (SelectedIndex == -1) {
+                                               SelectedIndex = 0;
+                                               if (dropdown_style != ComboBoxStyle.Simple)
+                                                       return;
+                                       }
+
+                                       offset = listbox_ctrl == null ? MaxDropDownItems - 1 : listbox_ctrl.page_size - 1;
+                                       if (offset < 1)
+                                               offset = 1;
+
+                                       SelectedIndex = Math.Min (SelectedIndex + offset, Items.Count - 1);
+
+                                       if (DroppedDown)
+                                               if (SelectedIndex >= listbox_ctrl.LastVisibleItem ())
+                                                       listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.LastVisibleItem () + 1);
+                                       break;
+                                       
+                               case Keys.Escape:
+                                       DropDownListBoxFinished ();
+                                       break;
+                                       
+                               case Keys.Home:
+                                       if (dropdown_style == ComboBoxStyle.DropDownList) {
+                                               SelectedIndex = 0;
+
+                                               if (DroppedDown)
+                                                       if (SelectedIndex < listbox_ctrl.FirstVisibleItem ())
+                                                               listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.FirstVisibleItem ());
+                                       }
+                                       
+                                       break;
+                               case Keys.End:
+                                       if (dropdown_style == ComboBoxStyle.DropDownList) {
+                                               SelectedIndex = Items.Count - 1;
+
+                                               if (DroppedDown)
+                                                       if (SelectedIndex >= listbox_ctrl.LastVisibleItem ())
+                                                               listbox_ctrl.Scroll (SelectedIndex - listbox_ctrl.LastVisibleItem () + 1);
+                                       }
+                                       
                                        break;
-                               
                                default:
                                        break;
                        }
                }
+
+               // If no item is currently selected, and an item is found matching the text 
+               // in the textbox, then selected that item.  Otherwise the item at the given 
+               // index is selected.
+               private void FindMatchOrSetIndex(int index)
+               {
+                       int match = -1;
+                       if (SelectedIndex == -1 && Text.Length != 0)
+                               match = FindStringCaseInsensitive(Text);
+                       if (match != -1)
+                               SelectedIndex = match;
+                       else
+                               SelectedIndex = index;
+               }
                
                void OnMouseDownCB (object sender, MouseEventArgs e)
                {
@@ -1533,15 +1712,30 @@ namespace System.Windows.Forms
                                area = button_area;
 
                        if (area.Contains (e.X, e.Y)) {
-                               DropDownListBox ();
+                               if (Items.Count > 0)
+                                       DropDownListBox ();
+                               else {
+                                       button_state = ButtonState.Pushed;
+                                       OnDropDown (EventArgs.Empty);
+                               }
+                               
                                Invalidate (button_area);
                                Update ();
                        }
                        Capture = true;
                }
 
+               void OnMouseLeave (object sender, EventArgs e)
+               {
+                       if (show_dropdown_button)
+                               DropDownButtonEntered = false;
+               }
+
                void OnMouseMoveCB (object sender, MouseEventArgs e)
                {
+                       if (show_dropdown_button && !dropped_down)
+                               DropDownButtonEntered = button_area.Contains (e.Location);
+
                        if (DropDownStyle == ComboBoxStyle.Simple)
                                return;
 
@@ -1555,6 +1749,10 @@ namespace System.Windows.Forms
                void OnMouseUpCB (object sender, MouseEventArgs e)
                {
                        Capture = false;
+                       
+                       button_state = ButtonState.Normal;
+                       Invalidate (button_area);
+
                        OnClick (EventArgs.Empty);
 
                        if (dropped_down)
@@ -1597,7 +1795,7 @@ namespace System.Windows.Forms
                {
                        if (process_textchanged_event == false)
                                return; 
-                               
+
                        OnTextChanged (EventArgs.Empty);
 
                        int item = FindStringCaseInsensitive (textbox_ctrl.Text);
@@ -1616,11 +1814,17 @@ namespace System.Windows.Forms
 
                        base.Text = textbox_ctrl.Text;
                }
-               
+
+               private void OnTextKeyPress (object sender, KeyPressEventArgs e)
+               {
+                       selected_index = -1;
+               }
+
                internal void SetControlText (string s)
                {
                        process_textchanged_event = false;
                        textbox_ctrl.Text = s;
+                       textbox_ctrl.SelectAll ();
                        process_textchanged_event = true;
                }
                
@@ -1631,7 +1835,7 @@ namespace System.Windows.Forms
 
                        // Save the requested height since set bounds can destroy it
                        int save_height = requested_height;
-                       SetBounds (0, 0, 0, requested_height, BoundsSpecified.Height);
+                       SetBounds (bounds.X, bounds.Y, bounds.Width, requested_height, BoundsSpecified.Height);
                        requested_height = save_height;
                }
 
@@ -1672,13 +1876,13 @@ namespace System.Windows.Forms
                        public virtual object this [int index] {
                                get {
                                        if (index < 0 || index >= Count)
-                                               throw new ArgumentOutOfRangeException ("Index of out range");
+                                               throw new ArgumentOutOfRangeException ("index");
 
                                        return object_items[index];
                                }
                                set {
                                        if (index < 0 || index >= Count)
-                                               throw new ArgumentOutOfRangeException ("Index of out range");
+                                               throw new ArgumentOutOfRangeException ("index");
                                        if (value == null)
                                                throw new ArgumentNullException ("value");
 
@@ -1745,7 +1949,18 @@ namespace System.Windows.Forms
                                return object_items.Contains (value);
                        }
 
-                       public void CopyTo (object[] dest, int arrayIndex)
+#if NET_2_0
+                       public void CopyTo (object [] destination, int arrayIndex)
+                       {
+                               object_items.CopyTo (destination, arrayIndex);
+                       }
+
+                       void ICollection.CopyTo (Array destination, int index)
+                       {
+                               object_items.CopyTo (destination, index);
+                       }
+#else
+                       public void CopyTo (object [] dest, int arrayIndex)
                        {
                                object_items.CopyTo (dest, arrayIndex);
                        }
@@ -1754,6 +1969,7 @@ namespace System.Windows.Forms
                        {
                                object_items.CopyTo (dest, index);
                        }
+#endif
 
                        public IEnumerator GetEnumerator ()
                        {
@@ -1776,7 +1992,7 @@ namespace System.Windows.Forms
                        public void Insert (int index,  object item)
                        {
                                if (index < 0 || index > Count)
-                                       throw new ArgumentOutOfRangeException ("Index of out range");
+                                       throw new ArgumentOutOfRangeException ("index");
                                if (item == null)
                                        throw new ArgumentNullException ("item");
                                
@@ -1804,7 +2020,7 @@ namespace System.Windows.Forms
                        public void RemoveAt (int index)
                        {
                                if (index < 0 || index >= Count)
-                                       throw new ArgumentOutOfRangeException ("Index of out range");
+                                       throw new ArgumentOutOfRangeException ("index");
                                        
                                if (index == owner.SelectedIndex)
                                        owner.SelectedIndex = -1;
@@ -1825,6 +2041,13 @@ namespace System.Windows.Forms
                                        foreach (object o in object_items) {
                                                if (String.Compare (item.ToString (), o.ToString ()) < 0) {
                                                        object_items.Insert (index, item);
+                                                       
+                                                       // If we added the new item before the selectedindex
+                                                       // bump the selectedindex by one, behavior differs if
+                                                       // Handle has not been created.
+                                                       if (index <= owner.selected_index && owner.IsHandleCreated)
+                                                               owner.selected_index++;
+                                                               
                                                        return index;
                                                }
                                                index++;
@@ -1858,6 +2081,7 @@ namespace System.Windows.Forms
                        {
                                this.owner = owner;
                                ShowSelection = false;
+                               HideSelection = false;
                        }
 
                        internal void SetSelectable (bool selectable)
@@ -1896,6 +2120,8 @@ namespace System.Windows.Forms
                                        return owner.Focused;
                                }
                        }
+                       
+                       internal override bool ActivateOnShow { get { return false; } }
                }
 
                internal class ComboListBox : Control
@@ -1989,18 +2215,14 @@ namespace System.Windows.Forms
                                        if (owner == null || owner.DropDownStyle == ComboBoxStyle.Simple)
                                                return cp;
 
-                                       cp.Style ^= (int) WindowStyles.WS_CHILD;
-                                       cp.Style |= (int) WindowStyles.WS_POPUP;
+                                       cp.Style ^= (int)WindowStyles.WS_CHILD;
+                                       cp.Style ^= (int)WindowStyles.WS_VISIBLE;
+                                       cp.Style |= (int)WindowStyles.WS_POPUP;
                                        cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST;
                                        return cp;
                                }
                        }
 
-                       protected override void Select (bool directed, bool forward)
-                       {
-                               // Do nothing, we never want to be selected
-                       }
-
                        internal override bool InternalCapture {
                                get {
                                        return Capture;
@@ -2018,11 +2240,15 @@ namespace System.Windows.Forms
                        {
                                int width, height;
                                bool show_scrollbar = false;
-                               
+
                                if (owner.DropDownStyle == ComboBoxStyle.Simple) {
                                        Rectangle area = owner.listbox_area;
                                        width = area.Width;
                                        height = area.Height;
+
+                                       // No calculation needed
+                                       if (height <= 0 || width <= 0)
+                                               return;
                                }
                                else { // DropDown or DropDownList
                                        
@@ -2044,11 +2270,16 @@ namespace System.Windows.Forms
                                        }
                                }
                                
-                               page_size = height / owner.ItemHeight;
+                               page_size = Math.Max (height / owner.ItemHeight, 1);
+
+                               ComboBoxStyle dropdown_style = owner.DropDownStyle;
+                               if ((dropdown_style != ComboBoxStyle.Simple && owner.Items.Count <= owner.MaxDropDownItems)
+                                       || (dropdown_style == ComboBoxStyle.Simple && owner.Items.Count * owner.ItemHeight < height)) {
 
-                               if (owner.Items.Count <= owner.MaxDropDownItems) {
                                        if (vscrollbar_ctrl != null)
                                                vscrollbar_ctrl.Visible = false;
+                                       if (dropdown_style != ComboBoxStyle.Simple)
+                                               height = owner.ItemHeight * owner.items.Count;
                                } else {
                                        /* Need vertical scrollbar */
                                        if (vscrollbar_ctrl == null) {
@@ -2063,10 +2294,14 @@ namespace System.Windows.Forms
                                        
                                        vscrollbar_ctrl.Dock = DockStyle.Right;
 
-                                       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.Maximum = owner.Items.Count - 1;
+#if NET_2_0
+                                       int large = page_size;
+#else
+                                       int large = (dropdown_style == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items) - 1;
+#endif
+                                       if (large < 1)
+                                               large = 1;
                                        vscrollbar_ctrl.LargeChange = large;
                                        show_scrollbar = vscrollbar_ctrl.Visible = true;
 
@@ -2179,7 +2414,7 @@ namespace System.Windows.Forms
                                        Invalidate (GetItemDisplayRectangle (index, top_item));
                        }
 
-                       private int LastVisibleItem ()
+                       public int LastVisibleItem ()
                        {
                                Rectangle item_rect;
                                int top_y = textarea_drawable.Y + textarea_drawable.Height;
@@ -2203,6 +2438,11 @@ namespace System.Windows.Forms
                                Invalidate ();
                        }
 
+                       public int FirstVisibleItem ()
+                       {
+                               return top_item;
+                       }
+                       
                        bool scrollbar_grabbed = false;
 
                        bool InScrollBar {
@@ -2291,7 +2531,7 @@ namespace System.Windows.Forms
                                if (delta == 0 || vscrollbar_ctrl == null || !vscrollbar_ctrl.Visible)
                                        return;
 
-                               int max = owner.Items.Count - page_size;
+                               int max = vscrollbar_ctrl.Maximum - page_size + 1;
 
                                int val = vscrollbar_ctrl.Value + delta;
                                if (val > max)
@@ -2323,9 +2563,7 @@ namespace System.Windows.Forms
                        
                        protected override void WndProc(ref Message m) {
                                if (m.Msg == (int)Msg.WM_SETFOCUS) {
-                                       if (m.WParam != IntPtr.Zero) {
-                                               XplatUI.SetFocus(m.WParam);
-                                       }
+                                       owner.Select (false, true);
                                }
                                base.WndProc (ref m);
                        }