1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
24 // Mike Kestner <mkestner@novell.com>
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Reflection;
33 using System.ComponentModel.Design;
34 using System.ComponentModel.Design.Serialization;
35 using System.Runtime.InteropServices;
38 namespace System.Windows.Forms
41 [DefaultProperty("Items")]
42 [DefaultEvent("SelectedIndexChanged")]
43 [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44 public class ComboBox : ListControl
46 private DrawMode draw_mode = DrawMode.Normal;
47 private ComboBoxStyle dropdown_style = (ComboBoxStyle)(-1);
48 private int dropdown_width = -1;
49 private int selected_index = -1;
50 internal ObjectCollection items = null;
51 private bool suspend_ctrlupdate;
52 private int maxdrop_items = 8;
53 private bool integral_height = true;
55 private int max_length;
56 private ComboListBox listbox_ctrl;
57 private TextBox textbox_ctrl;
58 private bool item_height_specified = false;
59 private int item_height;
60 private int requested_height = -1;
61 private Hashtable item_heights;
62 private bool show_dropdown_button = false;
63 private ButtonState button_state = ButtonState.Normal;
64 private bool dropped_down;
65 private Rectangle text_area;
66 private Rectangle button_area;
67 private Rectangle listbox_area;
68 private const int button_width = 16;
71 public class ChildAccessibleObject : AccessibleObject {
72 private ComboBox owner;
73 private IntPtr handle;
75 public ChildAccessibleObject (ComboBox owner, IntPtr handle) {
80 public override string Name {
89 items = new ObjectCollection (this);
90 DropDownStyle = ComboBoxStyle.DropDown;
91 item_height = FontHeight + 2;
92 BackColor = ThemeEngine.Current.ColorWindow;
93 border_style = BorderStyle.None;
96 MouseDown += new MouseEventHandler (OnMouseDownCB);
97 MouseUp += new MouseEventHandler (OnMouseUpCB);
98 MouseMove += new MouseEventHandler (OnMouseMoveCB);
99 KeyDown +=new KeyEventHandler(OnKeyDownCB);
105 [EditorBrowsable (EditorBrowsableState.Never)]
106 public new event EventHandler BackgroundImageChanged {
107 add { base.BackgroundImageChanged += value; }
108 remove { base.BackgroundImageChanged -= value; }
111 public event DrawItemEventHandler DrawItem;
112 public event EventHandler DropDown;
113 public event EventHandler DropDownStyleChanged;
114 public event MeasureItemEventHandler MeasureItem;
117 [EditorBrowsable (EditorBrowsableState.Never)]
118 public new event PaintEventHandler Paint {
119 add { base.Paint += value; }
120 remove { base.Paint -= value; }
123 public event EventHandler SelectedIndexChanged;
124 public event EventHandler SelectionChangeCommitted;
127 #region Public Properties
128 public override Color BackColor {
129 get { return base.BackColor; }
131 if (base.BackColor == value)
134 base.BackColor = value;
140 [EditorBrowsable (EditorBrowsableState.Never)]
141 public override Image BackgroundImage {
142 get { return base.BackgroundImage; }
144 if (base.BackgroundImage == value)
147 base.BackgroundImage = value;
152 protected override CreateParams CreateParams {
153 get { return base.CreateParams;}
156 protected override Size DefaultSize {
157 get { return new Size (121, 21); }
160 [RefreshProperties(RefreshProperties.Repaint)]
161 [DefaultValue (DrawMode.Normal)]
162 public DrawMode DrawMode {
163 get { return draw_mode; }
166 if (!Enum.IsDefined (typeof (DrawMode), value))
167 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
169 if (draw_mode == value)
172 if (draw_mode == DrawMode.OwnerDrawVariable)
175 if (draw_mode == DrawMode.OwnerDrawVariable)
176 item_heights = new Hashtable ();
181 [DefaultValue (ComboBoxStyle.DropDown)]
182 [RefreshProperties(RefreshProperties.Repaint)]
183 public ComboBoxStyle DropDownStyle {
184 get { return dropdown_style; }
188 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
189 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
191 if (dropdown_style == value)
194 if (dropdown_style == ComboBoxStyle.Simple) {
195 if (listbox_ctrl != null) {
196 Controls.RemoveImplicit (listbox_ctrl);
197 listbox_ctrl.Dispose ();
202 dropdown_style = value;
204 if (dropdown_style == ComboBoxStyle.DropDownList && textbox_ctrl != null) {
205 Controls.RemoveImplicit (textbox_ctrl);
206 textbox_ctrl.Dispose ();
210 if (dropdown_style == ComboBoxStyle.Simple) {
211 show_dropdown_button = false;
213 CreateComboListBox ();
216 Controls.AddImplicit (listbox_ctrl);
218 show_dropdown_button = true;
219 button_state = ButtonState.Normal;
222 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
223 textbox_ctrl = new FixedSizeTextBox ();
224 if (SelectedItem != null)
225 textbox_ctrl.Text = GetItemText (SelectedItem);
226 textbox_ctrl.BorderStyle = BorderStyle.None;
227 textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
228 textbox_ctrl.KeyPress += new KeyPressEventHandler(textbox_ctrl_KeyPress);
229 textbox_ctrl.KeyDown += new KeyEventHandler (OnKeyDownCB);
230 textbox_ctrl.GotFocus += new EventHandler(textbox_ctrl_GotFocus);
231 textbox_ctrl.LostFocus += new EventHandler(textbox_ctrl_LostFocus);
232 textbox_ctrl.MouseDown += new MouseEventHandler(textbox_ctrl_MouseDown);
233 textbox_ctrl.MouseMove += new MouseEventHandler(textbox_ctrl_MouseMove);
234 textbox_ctrl.MouseUp += new MouseEventHandler(textbox_ctrl_MouseUp);
236 if (IsHandleCreated == true) {
237 Controls.AddImplicit (textbox_ctrl);
241 OnDropDownStyleChanged (EventArgs.Empty);
249 public int DropDownWidth {
251 if (dropdown_width == -1)
254 return dropdown_width;
257 if (dropdown_width == value)
261 throw new ArgumentException ("The DropDownWidth value is less than one");
263 dropdown_width = value;
268 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
269 public bool DroppedDown {
271 if (dropdown_style == ComboBoxStyle.Simple)
277 if (dropdown_style == ComboBoxStyle.Simple || dropped_down == value)
283 listbox_ctrl.Hide ();
287 public override bool Focused {
288 get { return base.Focused; }
291 public override Color ForeColor {
292 get { return base.ForeColor; }
294 if (base.ForeColor == value)
297 base.ForeColor = value;
302 [DefaultValue (true)]
304 public bool IntegralHeight {
305 get { return integral_height; }
307 if (integral_height == value)
310 integral_height = value;
317 public int ItemHeight {
319 if (item_height == -1) {
320 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
321 item_height = (int) sz.Height;
327 throw new ArgumentException ("The item height value is less than zero");
329 item_height_specified = true;
338 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
340 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
341 public ComboBox.ObjectCollection Items {
342 get { return items; }
347 public int MaxDropDownItems {
348 get { return maxdrop_items; }
350 if (maxdrop_items == value)
353 maxdrop_items = value;
359 public int MaxLength {
360 get { return max_length; }
362 if (max_length == value)
367 if (dropdown_style != ComboBoxStyle.DropDownList) {
373 textbox_ctrl.MaxLength = value;
378 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
380 public int PreferredHeight {
382 return ItemHeight + 5;
387 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
388 public override int SelectedIndex {
389 get { return selected_index; }
391 if (value <= -2 || value >= Items.Count)
392 throw new ArgumentOutOfRangeException ("Index of out range");
394 selected_index = value;
396 if (dropdown_style != ComboBoxStyle.DropDownList) {
397 if (selected_index == -1)
398 SetControlText (String.Empty);
400 SetControlText (GetItemText (items [value]));
405 OnSelectedValueChanged (new EventArgs ());
406 OnSelectedIndexChanged (new EventArgs ());
407 OnSelectedItemChanged (new EventArgs ());
409 if (DropDownStyle == ComboBoxStyle.DropDownList)
412 if (listbox_ctrl != null)
413 listbox_ctrl.HighlightedIndex = value;
418 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
420 public object SelectedItem {
422 if (selected_index == -1)
424 return items [selected_index];
427 if (items [selected_index] == value)
433 SelectedIndex = items.IndexOf (value);
438 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
439 public string SelectedText {
441 if (dropdown_style == ComboBoxStyle.DropDownList)
444 return textbox_ctrl.SelectedText;
447 if (dropdown_style == ComboBoxStyle.DropDownList)
450 textbox_ctrl.SelectedText = value;
455 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
456 public int SelectionLength {
458 if (dropdown_style == ComboBoxStyle.DropDownList)
461 return textbox_ctrl.SelectionLength;
464 if (dropdown_style == ComboBoxStyle.DropDownList)
467 if (textbox_ctrl.SelectionLength == value)
470 textbox_ctrl.SelectionLength = value;
475 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
476 public int SelectionStart {
478 if (dropdown_style == ComboBoxStyle.DropDownList)
481 return textbox_ctrl.SelectionStart;
484 if (dropdown_style == ComboBoxStyle.DropDownList)
487 if (textbox_ctrl.SelectionStart == value)
490 textbox_ctrl.SelectionStart = value;
494 [DefaultValue (false)]
496 get { return sorted; }
508 public override string Text {
510 if (dropdown_style != ComboBoxStyle.DropDownList) {
511 if (textbox_ctrl != null) {
512 return textbox_ctrl.Text;
516 if (SelectedItem != null)
517 return GetItemText (SelectedItem);
527 int index = FindString (value);
530 SelectedIndex = index;
533 if (dropdown_style != ComboBoxStyle.DropDownList)
534 textbox_ctrl.Text = GetItemText (value);
538 #endregion Public Properties
540 #region Public Methods
541 protected virtual void AddItemsCore (object[] value)
546 public void BeginUpdate ()
548 suspend_ctrlupdate = true;
551 protected override void Dispose (bool disposing)
554 if (listbox_ctrl != null) {
555 listbox_ctrl.Dispose ();
556 Controls.RemoveImplicit (listbox_ctrl);
560 if (textbox_ctrl != null) {
561 Controls.RemoveImplicit (textbox_ctrl);
562 textbox_ctrl.Dispose ();
567 base.Dispose (disposing);
570 public void EndUpdate ()
572 suspend_ctrlupdate = false;
577 public int FindString (string s)
579 return FindString (s, -1);
582 public int FindString (string s, int startIndex)
584 if (Items.Count == 0)
585 return -1; // No exception throwing if empty
587 if (startIndex < -1 || startIndex >= Items.Count - 1)
588 throw new ArgumentOutOfRangeException ("Index of out range");
591 for (int i = startIndex; i < Items.Count; i++) {
592 if ((GetItemText (Items[i])).StartsWith (s))
599 public int FindStringExact (string s)
601 return FindStringExact (s, -1);
604 public int FindStringExact (string s, int startIndex)
606 if (Items.Count == 0)
607 return -1; // No exception throwing if empty
609 if (startIndex < -1 || startIndex >= Items.Count - 1)
610 throw new ArgumentOutOfRangeException ("Index of out range");
613 for (int i = startIndex; i < Items.Count; i++) {
614 if ((GetItemText (Items[i])).Equals (s))
621 public int GetItemHeight (int index)
623 if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated) {
625 if (index < 0 || index >= Items.Count )
626 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
628 object item = Items [index];
629 if (item_heights.Contains (item))
630 return (int) item_heights [item];
632 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
633 OnMeasureItem (args);
634 item_heights [item] = args.ItemHeight;
635 return args.ItemHeight;
641 protected override bool IsInputKey (Keys keyData)
655 protected override void OnBackColorChanged (EventArgs e)
657 base.OnBackColorChanged (e);
660 protected override void OnDataSourceChanged (EventArgs e)
662 base.OnDataSourceChanged (e);
663 BindDataItems (items);
665 if (DataSource == null || DataManager == null) {
669 SelectedIndex = DataManager.Position;
673 protected override void OnDisplayMemberChanged (EventArgs e)
675 base.OnDisplayMemberChanged (e);
677 if (DataManager == null || !IsHandleCreated)
680 BindDataItems (items);
681 SelectedIndex = DataManager.Position;
684 protected virtual void OnDrawItem (DrawItemEventArgs e)
687 case DrawMode.OwnerDrawFixed:
688 case DrawMode.OwnerDrawVariable:
689 if (DrawItem != null)
693 ThemeEngine.Current.DrawComboBoxItem (this, e);
698 protected virtual void OnDropDown (EventArgs e)
700 if (DropDown != null)
704 protected virtual void OnDropDownStyleChanged (EventArgs e)
706 if (DropDownStyleChanged != null)
707 DropDownStyleChanged (this, e);
710 protected override void OnFontChanged (EventArgs e)
712 base.OnFontChanged (e);
714 if (textbox_ctrl != null)
715 textbox_ctrl.Font = Font;
717 if (!item_height_specified) {
718 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
719 item_height = (int) sz.Height;
728 protected override void OnForeColorChanged (EventArgs e)
730 base.OnForeColorChanged (e);
733 [EditorBrowsable(EditorBrowsableState.Advanced)]
734 protected override void OnGotFocus (EventArgs e) {
737 if (dropdown_style == ComboBoxStyle.Simple)
738 listbox_ctrl.Focus ();
739 else if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl != null)
740 textbox_ctrl.Focus ();
744 [EditorBrowsable(EditorBrowsableState.Advanced)]
745 protected override void OnLostFocus (EventArgs e) {
746 base.OnLostFocus (e);
749 protected override void OnHandleCreated (EventArgs e)
751 base.OnHandleCreated (e);
753 if (listbox_ctrl != null)
754 Controls.AddImplicit (listbox_ctrl);
756 if (textbox_ctrl != null)
757 Controls.AddImplicit (textbox_ctrl);
762 protected override void OnHandleDestroyed (EventArgs e)
764 base.OnHandleDestroyed (e);
767 protected override void OnKeyPress (KeyPressEventArgs e)
769 int index= FindStringCaseInsensitive (e.KeyChar.ToString (), SelectedIndex + 1);
772 SelectedIndex = index;
777 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
779 if (MeasureItem != null)
780 MeasureItem (this, e);
783 protected override void OnParentBackColorChanged (EventArgs e)
785 base.OnParentBackColorChanged (e);
788 protected override void OnResize (EventArgs e)
791 if (listbox_ctrl != null)
792 listbox_ctrl.CalcListBoxArea ();
795 protected override void OnSelectedIndexChanged (EventArgs e)
797 base.OnSelectedIndexChanged (e);
799 if (SelectedIndexChanged != null)
800 SelectedIndexChanged (this, e);
803 protected virtual void OnSelectedItemChanged (EventArgs e)
808 protected override void OnSelectedValueChanged (EventArgs e)
810 base.OnSelectedValueChanged (e);
813 protected virtual void OnSelectionChangeCommitted (EventArgs e)
815 if (SelectionChangeCommitted != null)
816 SelectionChangeCommitted (this, e);
819 protected override void RefreshItem (int index)
821 if (index < 0 || index >= Items.Count)
822 throw new ArgumentOutOfRangeException ("Index of out range");
824 if (draw_mode == DrawMode.OwnerDrawVariable)
825 item_heights.Remove (Items [index]);
828 public void Select (int start, int length)
831 throw new ArgumentException ("Start cannot be less than zero");
834 throw new ArgumentException ("length cannot be less than zero");
836 if (dropdown_style == ComboBoxStyle.DropDownList)
839 textbox_ctrl.Select (start, length);
842 public void SelectAll ()
844 if (dropdown_style == ComboBoxStyle.DropDownList)
847 textbox_ctrl.SelectAll ();
850 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
852 if ((specified & BoundsSpecified.Height) != 0) {
853 requested_height = height;
855 if (DropDownStyle == ComboBoxStyle.Simple && height > PreferredHeight) {
856 if (IntegralHeight) {
857 int border = ThemeEngine.Current.Border3DSize.Height;
858 int lb_height = height - PreferredHeight - 2;
859 if (lb_height - 2 * border > ItemHeight) {
860 int partial = (lb_height - 2 * border) % ItemHeight;
863 height = PreferredHeight;
866 height = PreferredHeight;
869 base.SetBoundsCore (x, y, width, height, specified);
872 protected override void SetItemCore (int index, object value)
874 if (index < 0 || index >= Items.Count)
877 Items[index] = value;
880 protected override void SetItemsCore (IList value)
885 Items.AddRange (value);
891 public override string ToString ()
893 return base.ToString () + ", Items.Count:" + Items.Count;
896 protected override void WndProc (ref Message m)
898 switch ((Msg) m.Msg) {
899 case Msg.WM_MOUSE_LEAVE:
900 Point location = PointToClient (Control.MousePosition);
901 if (ClientRectangle.Contains (location))
907 base.WndProc (ref m);
910 #endregion Public Methods
912 #region Private Methods
914 internal override bool InternalCapture {
915 get { return Capture; }
919 private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e)
924 private void textbox_ctrl_GotFocus(object sender, EventArgs e )
929 private void textbox_ctrl_LostFocus(object sender, EventArgs e )
934 private void textbox_ctrl_MouseDown(object sender, MouseEventArgs e )
939 private void textbox_ctrl_MouseMove(object sender, MouseEventArgs e )
944 private void textbox_ctrl_MouseUp(object sender, MouseEventArgs e )
951 int border = ThemeEngine.Current.Border3DSize.Width;
953 text_area = ClientRectangle;
954 text_area.Height = PreferredHeight;
956 listbox_area = ClientRectangle;
957 listbox_area.Y = text_area.Bottom + 3;
958 listbox_area.Height -= (text_area.Height + 2);
960 Rectangle prev_button_area = button_area;
962 if (DropDownStyle == ComboBoxStyle.Simple)
963 button_area = Rectangle.Empty;
965 button_area = text_area;
966 button_area.X = text_area.Right - button_width - border;
967 button_area.Y = text_area.Y + border;
968 button_area.Width = button_width;
969 button_area.Height = text_area.Height - 2 * border;
972 if (button_area != prev_button_area) {
973 prev_button_area.Y -= border;
974 prev_button_area.Width += border;
975 prev_button_area.Height += 2 * border;
976 Invalidate (prev_button_area);
977 Invalidate (button_area);
980 if (textbox_ctrl != null) {
981 textbox_ctrl.Location = new Point (text_area.X + border, text_area.Y + border);
982 textbox_ctrl.Width = text_area.Width - button_area.Width - border * 2;
983 textbox_ctrl.Height = text_area.Height - border * 2;
986 if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
987 listbox_ctrl.Location = listbox_area.Location;
988 listbox_ctrl.CalcListBoxArea ();
992 private void CreateComboListBox ()
994 listbox_ctrl = new ComboListBox (this);
995 if (selected_index != -1)
996 listbox_ctrl.HighlightedIndex = selected_index;
999 internal void Draw (Rectangle clip, Graphics dc)
1001 Theme theme = ThemeEngine.Current;
1003 if (DropDownStyle == ComboBoxStyle.Simple)
1004 dc.FillRectangle (theme.ResPool.GetSolidBrush (Parent.BackColor), ClientRectangle);
1006 if (clip.IntersectsWith (text_area))
1007 ControlPaint.DrawBorder3D (dc, text_area, Border3DStyle.Sunken);
1009 int border = theme.Border3DSize.Width;
1011 // No edit control, we paint the edit ourselves
1012 if (dropdown_style == ComboBoxStyle.DropDownList) {
1013 DrawItemState state = DrawItemState.None;
1014 Rectangle item_rect = text_area;
1015 item_rect.X += border;
1016 item_rect.Y += border;
1017 item_rect.Width -= (button_area.Width + 2 * border);
1018 item_rect.Height -= 2 * border;
1021 state = DrawItemState.Selected;
1022 state |= DrawItemState.Focus;
1025 state |= DrawItemState.ComboBoxEdit;
1026 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, ForeColor, BackColor));
1029 if (show_dropdown_button) {
1030 dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area);
1033 button_state = ButtonState.Inactive;
1035 theme.CPDrawComboButton (dc, button_area, button_state);
1039 internal void DropDownListBox ()
1041 if (DropDownStyle == ComboBoxStyle.Simple)
1044 if (listbox_ctrl == null)
1045 CreateComboListBox ();
1047 listbox_ctrl.Location = PointToScreen (new Point (text_area.X, text_area.Y + text_area.Height));
1049 if (listbox_ctrl.ShowWindow ())
1050 dropped_down = true;
1052 button_state = ButtonState.Pushed;
1053 if (dropdown_style == ComboBoxStyle.DropDownList)
1054 Invalidate (text_area);
1056 OnDropDown (EventArgs.Empty);
1059 internal void DropDownListBoxFinished ()
1061 if (DropDownStyle == ComboBoxStyle.Simple)
1064 button_state = ButtonState.Normal;
1065 Invalidate (button_area);
1066 dropped_down = false;
1069 private int FindStringCaseInsensitive (string search)
1071 if (search.Length == 0) {
1075 for (int i = 0; i < Items.Count; i++)
1077 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1084 internal int FindStringCaseInsensitive (string search, int start_index)
1086 if (search.Length == 0) {
1090 for (int i = 0; i < Items.Count; i++) {
1091 int index = (i + start_index) % Items.Count;
1092 if (String.Compare (GetItemText (Items [index]), 0, search, 0, search.Length, true) == 0)
1099 private void OnKeyDownCB(object sender, KeyEventArgs e)
1101 if (Items.Count == 0)
1107 SelectedIndex = Math.Max(SelectedIndex-1, 0);
1111 SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1);
1115 if (listbox_ctrl != null)
1116 SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0);
1120 if (listbox_ctrl != null)
1121 SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1);
1129 void OnMouseDownCB (object sender, MouseEventArgs e)
1132 if (DropDownStyle == ComboBoxStyle.DropDownList)
1133 area = ClientRectangle;
1137 if (area.Contains (e.X, e.Y)) {
1139 Invalidate (button_area);
1145 void OnMouseMoveCB (object sender, MouseEventArgs e)
1147 if (DropDownStyle == ComboBoxStyle.Simple)
1150 if (listbox_ctrl != null && listbox_ctrl.Visible) {
1151 Point location = listbox_ctrl.PointToClient (Control.MousePosition);
1152 if (listbox_ctrl.ClientRectangle.Contains (location))
1153 listbox_ctrl.Capture = true;
1157 void OnMouseUpCB (object sender, MouseEventArgs e)
1160 OnClick (EventArgs.Empty);
1163 listbox_ctrl.Capture = true;
1166 internal override void OnPaintInternal (PaintEventArgs pevent)
1168 if (suspend_ctrlupdate)
1171 Draw (ClientRectangle, pevent.Graphics);
1174 private void OnTextChangedEdit (object sender, EventArgs e)
1176 int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1178 if (item == -1 && listbox_ctrl != null) {
1179 listbox_ctrl.SetTopItem (item);
1180 listbox_ctrl.HighlightedIndex = item;
1183 base.Text = textbox_ctrl.Text;
1186 internal void SetControlText (string s)
1188 textbox_ctrl.Text = s;
1191 void UpdateBounds ()
1193 if (requested_height != -1)
1194 SetBoundsCore (0, 0, 0, requested_height, BoundsSpecified.Height);
1197 private void UpdatedItems ()
1199 if (listbox_ctrl != null) {
1200 listbox_ctrl.UpdateLastVisibleItem ();
1201 listbox_ctrl.CalcListBoxArea ();
1202 listbox_ctrl.Refresh ();
1206 #endregion Private Methods
1208 [ListBindableAttribute (false)]
1209 public class ObjectCollection : IList, ICollection, IEnumerable
1212 private ComboBox owner;
1213 internal ArrayList object_items = new ArrayList ();
1215 public ObjectCollection (ComboBox owner)
1220 #region Public Properties
1222 get { return object_items.Count; }
1225 public bool IsReadOnly {
1226 get { return false; }
1230 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1231 public virtual object this [int index] {
1233 if (index < 0 || index >= Count)
1234 throw new ArgumentOutOfRangeException ("Index of out range");
1236 return object_items[index];
1239 if (index < 0 || index >= Count)
1240 throw new ArgumentOutOfRangeException ("Index of out range");
1242 object_items[index] = value;
1246 bool ICollection.IsSynchronized {
1247 get { return false; }
1250 object ICollection.SyncRoot {
1251 get { return this; }
1254 bool IList.IsFixedSize {
1255 get { return false; }
1258 #endregion Public Properties
1260 #region Private Properties
1261 internal ArrayList ObjectItems {
1262 get { return object_items;}
1264 object_items = value;
1268 #endregion Private Properties
1270 #region Public Methods
1271 public int Add (object item)
1275 idx = AddItem (item);
1276 owner.UpdatedItems ();
1280 public void AddRange (object[] items)
1282 foreach (object mi in items)
1285 owner.UpdatedItems ();
1288 public void Clear ()
1290 owner.selected_index = -1;
1291 object_items.Clear ();
1292 owner.UpdatedItems ();
1296 public bool Contains (object obj)
1298 return object_items.Contains (obj);
1301 public void CopyTo (object[] dest, int arrayIndex)
1303 object_items.CopyTo (dest, arrayIndex);
1306 void ICollection.CopyTo (Array dest, int index)
1308 object_items.CopyTo (dest, index);
1311 public IEnumerator GetEnumerator ()
1313 return object_items.GetEnumerator ();
1316 int IList.Add (object item)
1321 public int IndexOf (object value)
1323 return object_items.IndexOf (value);
1326 public void Insert (int index, object item)
1328 if (index < 0 || index > Count)
1329 throw new ArgumentOutOfRangeException ("Index of out range");
1331 owner.BeginUpdate ();
1333 object_items.Insert (index, item);
1335 owner.EndUpdate (); // Calls UpdatedItems
1338 public void Remove (object value)
1340 if (IndexOf (value) == owner.SelectedIndex)
1341 owner.SelectedItem = null;
1343 RemoveAt (IndexOf (value));
1347 public void RemoveAt (int index)
1349 if (index < 0 || index >= Count)
1350 throw new ArgumentOutOfRangeException ("Index of out range");
1352 if (index == owner.SelectedIndex)
1353 owner.SelectedItem = null;
1355 object_items.RemoveAt (index);
1356 owner.UpdatedItems ();
1358 #endregion Public Methods
1360 #region Private Methods
1361 private int AddItem (object item)
1363 int cnt = object_items.Count;
1364 object_items.Add (item);
1368 internal void AddRange (IList items)
1370 foreach (object mi in items)
1373 owner.UpdatedItems ();
1376 #endregion Private Methods
1379 internal class ComboListBox : Control
1381 private ComboBox owner;
1382 private VScrollBarLB vscrollbar_ctrl;
1383 private int top_item; /* First item that we show the in the current page */
1384 private int last_item; /* Last visible item */
1385 internal int page_size; /* Number of listbox items per page */
1386 private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
1388 internal enum ItemNavigation
1398 class VScrollBarLB : VScrollBar
1400 public VScrollBarLB ()
1404 internal override bool InternalCapture {
1405 get { return Capture; }
1409 public bool FireMouseDown (MouseEventArgs e)
1412 e = TranslateEvent (e);
1413 if (ClientRectangle.Contains (e.X, e.Y)) {
1421 public void FireMouseUp (MouseEventArgs e)
1424 e = TranslateEvent (e);
1425 if (ClientRectangle.Contains (e.X, e.Y))
1430 public void FireMouseMove (MouseEventArgs e)
1433 e = TranslateEvent (e);
1434 if (ClientRectangle.Contains (e.X, e.Y))
1439 MouseEventArgs TranslateEvent (MouseEventArgs e)
1441 Point loc = PointToClient (Control.MousePosition);
1442 return new MouseEventArgs (e.Button, e.Clicks, loc.X, loc.Y, e.Delta);
1446 public ComboListBox (ComboBox owner)
1453 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1454 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1455 MouseMove += new MouseEventHandler (OnMouseMovePUW);
1456 MouseWheel += new MouseEventHandler (OnMouseWheelCLB);
1457 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1458 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1459 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1461 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1462 InternalBorderStyle = BorderStyle.Fixed3D;
1464 InternalBorderStyle = BorderStyle.FixedSingle;
1467 protected override CreateParams CreateParams
1470 CreateParams cp = base.CreateParams;
1471 if (owner == null || owner.DropDownStyle == ComboBoxStyle.Simple)
1474 cp.Style ^= (int) WindowStyles.WS_CHILD;
1475 cp.Style |= (int) WindowStyles.WS_POPUP;
1476 cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST;
1481 internal override bool InternalCapture {
1490 protected override void OnLostFocus(EventArgs e) {
1494 base.OnLostFocus (e);
1500 switch (border_style) {
1501 case BorderStyle.Fixed3D:
1502 return ThemeEngine.Current.Border3DSize.Width;
1504 return ThemeEngine.Current.BorderSize.Width;
1509 #region Private Methods
1510 // Calcs the listbox area
1511 internal void CalcListBoxArea ()
1514 bool show_scrollbar = false;
1516 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1517 Rectangle area = owner.listbox_area;
1519 height = area.Height;
1521 else { // DropDown or DropDownList
1523 width = owner.DropDownWidth;
1524 int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
1526 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1528 for (int i = 0; i < count; i++) {
1529 height += owner.GetItemHeight (i);
1533 height = owner.ItemHeight * count;
1537 if (owner.Items.Count <= owner.MaxDropDownItems) {
1538 if (vscrollbar_ctrl != null)
1539 vscrollbar_ctrl.Visible = false;
1541 /* Need vertical scrollbar */
1542 if (vscrollbar_ctrl == null) {
1543 vscrollbar_ctrl = new VScrollBarLB ();
1544 vscrollbar_ctrl.Minimum = 0;
1545 vscrollbar_ctrl.SmallChange = 1;
1546 vscrollbar_ctrl.LargeChange = 1;
1547 vscrollbar_ctrl.Maximum = 0;
1548 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1549 Controls.AddImplicit (vscrollbar_ctrl);
1552 vscrollbar_ctrl.Height = height - 2 * BorderWidth;
1554 vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - BorderWidth - 1, 0);
1556 vscrollbar_ctrl.Maximum = owner.Items.Count - (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items);
1557 show_scrollbar = vscrollbar_ctrl.Visible = true;
1559 int hli = HighlightedIndex;
1561 hli = Math.Min (hli, vscrollbar_ctrl.Maximum);
1562 vscrollbar_ctrl.Value = hli;
1566 Size = new Size (width, height);
1567 textarea_drawable = ClientRectangle;
1568 textarea_drawable.Width = width;
1569 textarea_drawable.Height = height;
1571 if (vscrollbar_ctrl != null && show_scrollbar)
1572 textarea_drawable.Width -= vscrollbar_ctrl.Width;
1574 last_item = LastVisibleItem ();
1575 page_size = textarea_drawable.Height / owner.ItemHeight;
1578 private void Draw (Rectangle clip, Graphics dc)
1580 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (owner.BackColor), clip);
1582 if (owner.Items.Count > 0) {
1584 for (int i = top_item; i <= last_item; i++) {
1585 Rectangle item_rect = GetItemDisplayRectangle (i, top_item);
1587 if (!clip.IntersectsWith (item_rect))
1590 DrawItemState state = DrawItemState.None;
1592 if (i == HighlightedIndex) {
1593 state |= DrawItemState.Selected;
1595 if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1596 state |= DrawItemState.Focus;
1600 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1601 i, state, owner.ForeColor, owner.BackColor));
1606 private int highlighted_index = -1;
1607 public int HighlightedIndex {
1608 get { return highlighted_index; }
1610 if (highlighted_index != -1)
1611 Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
1612 highlighted_index = value;
1614 Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
1616 // Scroll if we need to
1617 if (vscrollbar_ctrl != null) {
1618 int max = (owner.Items.Count <= owner.MaxDropDownItems) ?
1619 owner.Items.Count : owner.MaxDropDownItems;
1621 if (value > max + vscrollbar_ctrl.Value - 1) {
1622 vscrollbar_ctrl.Value += (value - (max + vscrollbar_ctrl.Value - 1));
1623 } else if (value < vscrollbar_ctrl.Value) {
1624 vscrollbar_ctrl.Value = value;
1630 private Rectangle GetItemDisplayRectangle (int index, int top_index)
1632 if (index < 0 || index >= owner.Items.Count)
1633 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1635 Rectangle item_rect = new Rectangle ();
1636 int height = owner.GetItemHeight (index);
1639 item_rect.Width = textarea_drawable.Width;
1640 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1642 for (int i = top_index; i < index; i++)
1643 item_rect.Y += owner.GetItemHeight (i);
1645 item_rect.Y = height * (index - top_index);
1647 item_rect.Height = height;
1651 public void HideWindow ()
1653 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1658 owner.DropDownListBoxFinished ();
1661 private int IndexFromPointDisplayRectangle (int x, int y)
1663 for (int i = top_item; i <= last_item; i++) {
1664 if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1671 protected override bool IsInputKey (Keys keyData)
1673 return owner.IsInputKey (keyData);
1676 private int LastVisibleItem ()
1678 Rectangle item_rect;
1679 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1682 for (i = top_item; i < owner.Items.Count; i++) {
1683 item_rect = GetItemDisplayRectangle (i, top_item);
1684 if (item_rect.Y + item_rect.Height > top_y) {
1691 private void NavigateItemVisually (ItemNavigation navigation)
1695 switch (navigation) {
1696 case ItemNavigation.Next:
1697 if (HighlightedIndex + 1 < owner.Items.Count) {
1698 if (HighlightedIndex + 1 > last_item) {
1700 vscrollbar_ctrl.Value = top_item;
1702 item = HighlightedIndex + 1;
1706 case ItemNavigation.Previous:
1707 if (HighlightedIndex > 0) {
1708 if (HighlightedIndex - 1 < top_item) {
1710 vscrollbar_ctrl.Value = top_item;
1712 item = HighlightedIndex - 1;
1716 case ItemNavigation.NextPage:
1717 if (HighlightedIndex + page_size - 1 >= owner.Items.Count) {
1718 top_item = owner.Items.Count - page_size;
1719 vscrollbar_ctrl.Value = top_item;
1720 item = owner.Items.Count - 1;
1722 if (HighlightedIndex + page_size - 1 > last_item) {
1723 top_item = HighlightedIndex;
1724 vscrollbar_ctrl.Value = HighlightedIndex;
1726 item = HighlightedIndex + page_size - 1;
1730 case ItemNavigation.PreviousPage:
1731 if (HighlightedIndex - page_size - 1 <= 0) {
1733 vscrollbar_ctrl.Value = top_item;
1736 if (HighlightedIndex - page_size - 1 < top_item) {
1737 top_item = HighlightedIndex - page_size - 1;
1738 vscrollbar_ctrl.Value = top_item;
1740 item = HighlightedIndex - page_size - 1;
1749 HighlightedIndex = item;
1750 owner.OnSelectionChangeCommitted (new EventArgs ());
1751 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1752 owner.SetControlText (owner.GetItemText (owner.Items[item]));
1756 private void OnKeyDownPUW (object sender, KeyEventArgs e)
1758 switch (e.KeyCode) {
1760 NavigateItemVisually (ItemNavigation.Previous);
1764 NavigateItemVisually (ItemNavigation.Next);
1768 NavigateItemVisually (ItemNavigation.PreviousPage);
1772 NavigateItemVisually (ItemNavigation.NextPage);
1777 protected override void OnKeyPress (KeyPressEventArgs e)
1779 int index = owner.FindStringCaseInsensitive (e.KeyChar.ToString (),
1780 owner.SelectedIndex + 1);
1783 owner.SelectedIndex = index;
1786 public void SetTopItem (int item)
1788 if (top_item == item)
1791 UpdateLastVisibleItem ();
1795 private void OnMouseDownPUW (object sender, MouseEventArgs e)
1797 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1800 if (vscrollbar_ctrl == null || !vscrollbar_ctrl.FireMouseDown (e))
1803 owner.OnSelectionChangeCommitted (new EventArgs ());
1804 owner.SelectedIndex = index;
1805 HighlightedIndex = index;
1809 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1810 owner.OnMouseDown (e);
1811 owner.textbox_ctrl.Focus ();
1815 private void OnMouseMovePUW (object sender, MouseEventArgs e)
1817 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1818 owner.OnMouseMove (e);
1822 Point pt = PointToClient (Control.MousePosition);
1823 int index = IndexFromPointDisplayRectangle (pt.X, pt.Y);
1826 HighlightedIndex = index;
1830 if (vscrollbar_ctrl != null)
1831 vscrollbar_ctrl.FireMouseMove (e);
1834 private void OnMouseUpPUW (object sender, MouseEventArgs e)
1836 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1837 owner.OnMouseUp (e);
1841 if (vscrollbar_ctrl != null)
1842 vscrollbar_ctrl.FireMouseUp (e);
1845 internal override void OnPaintInternal (PaintEventArgs pevent)
1847 Draw (pevent.ClipRectangle,pevent.Graphics);
1850 public bool ShowWindow ()
1852 if (owner.DropDownStyle == ComboBoxStyle.Simple && owner.Items.Count == 0)
1855 HighlightedIndex = owner.SelectedIndex;
1861 owner.OnDropDown (EventArgs.Empty);
1865 public void UpdateLastVisibleItem ()
1867 last_item = LastVisibleItem ();
1870 private void Scroll (int delta)
1872 if (delta == 0 || !vscrollbar_ctrl.Visible)
1875 int max = vscrollbar_ctrl.Maximum;//- (page_size) + 1;
1877 int val = vscrollbar_ctrl.Value + delta;
1880 else if (val < vscrollbar_ctrl.Minimum)
1881 val = vscrollbar_ctrl.Minimum;
1882 vscrollbar_ctrl.Value = val;
1885 private void OnMouseWheelCLB (object sender, MouseEventArgs me)
1887 if (owner.Items.Count == 0)
1890 int lines = me.Delta / 120 * SystemInformation.MouseWheelScrollLines;
1895 private void VerticalScrollEvent (object sender, EventArgs e)
1897 if (top_item == vscrollbar_ctrl.Value)
1900 top_item = vscrollbar_ctrl.Value;
1901 UpdateLastVisibleItem ();
1905 #endregion Private Methods