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 object selected_item = null;
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 process_textchanged_event = true;
59 private bool item_height_specified = false;
60 private int item_height;
61 private int requested_height = -1;
62 private Hashtable item_heights;
63 private bool show_dropdown_button = false;
64 private ButtonState button_state = ButtonState.Normal;
65 private bool dropped_down;
66 private Rectangle text_area;
67 private Rectangle button_area;
68 private Rectangle listbox_area;
69 private const int button_width = 16;
72 public class ChildAccessibleObject : AccessibleObject {
73 private ComboBox owner;
74 private IntPtr handle;
76 public ChildAccessibleObject (ComboBox owner, IntPtr handle) {
81 public override string Name {
90 items = new ObjectCollection (this);
91 DropDownStyle = ComboBoxStyle.DropDown;
92 item_height = FontHeight + 2;
93 BackColor = ThemeEngine.Current.ColorWindow;
94 border_style = BorderStyle.None;
97 MouseDown += new MouseEventHandler (OnMouseDownCB);
98 MouseUp += new MouseEventHandler (OnMouseUpCB);
99 MouseMove += new MouseEventHandler (OnMouseMoveCB);
100 KeyDown +=new KeyEventHandler(OnKeyDownCB);
106 [EditorBrowsable (EditorBrowsableState.Never)]
107 public new event EventHandler BackgroundImageChanged {
108 add { base.BackgroundImageChanged += value; }
109 remove { base.BackgroundImageChanged -= value; }
112 public event DrawItemEventHandler DrawItem;
113 public event EventHandler DropDown;
114 public event EventHandler DropDownStyleChanged;
115 public event MeasureItemEventHandler MeasureItem;
118 [EditorBrowsable (EditorBrowsableState.Never)]
119 public new event PaintEventHandler Paint {
120 add { base.Paint += value; }
121 remove { base.Paint -= value; }
124 public event EventHandler SelectedIndexChanged;
125 public event EventHandler SelectionChangeCommitted;
128 #region Public Properties
129 public override Color BackColor {
130 get { return base.BackColor; }
132 if (base.BackColor == value)
135 base.BackColor = value;
141 [EditorBrowsable (EditorBrowsableState.Never)]
142 public override Image BackgroundImage {
143 get { return base.BackgroundImage; }
145 if (base.BackgroundImage == value)
148 base.BackgroundImage = value;
153 protected override CreateParams CreateParams {
154 get { return base.CreateParams;}
157 protected override Size DefaultSize {
158 get { return new Size (121, 21); }
161 [RefreshProperties(RefreshProperties.Repaint)]
162 [DefaultValue (DrawMode.Normal)]
163 public DrawMode DrawMode {
164 get { return draw_mode; }
167 if (!Enum.IsDefined (typeof (DrawMode), value))
168 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
170 if (draw_mode == value)
173 if (draw_mode == DrawMode.OwnerDrawVariable)
176 if (draw_mode == DrawMode.OwnerDrawVariable)
177 item_heights = new Hashtable ();
182 [DefaultValue (ComboBoxStyle.DropDown)]
183 [RefreshProperties(RefreshProperties.Repaint)]
184 public ComboBoxStyle DropDownStyle {
185 get { return dropdown_style; }
189 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
190 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
192 if (dropdown_style == value)
195 if (dropdown_style == ComboBoxStyle.Simple) {
196 if (listbox_ctrl != null) {
197 Controls.RemoveImplicit (listbox_ctrl);
198 listbox_ctrl.Dispose ();
203 dropdown_style = value;
205 if (dropdown_style == ComboBoxStyle.DropDownList && textbox_ctrl != null) {
206 Controls.RemoveImplicit (textbox_ctrl);
207 textbox_ctrl.Dispose ();
211 if (dropdown_style == ComboBoxStyle.Simple) {
212 show_dropdown_button = false;
214 CreateComboListBox ();
217 Controls.AddImplicit (listbox_ctrl);
219 show_dropdown_button = true;
220 button_state = ButtonState.Normal;
223 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
224 textbox_ctrl = new FixedSizeTextBox ();
225 if (selected_item != null)
226 textbox_ctrl.Text = GetItemText (selected_item);
227 textbox_ctrl.BorderStyle = BorderStyle.None;
228 textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
229 textbox_ctrl.KeyPress += new KeyPressEventHandler(textbox_ctrl_KeyPress);
230 textbox_ctrl.KeyDown += new KeyEventHandler (OnKeyDownCB);
231 textbox_ctrl.GotFocus += new EventHandler(textbox_ctrl_GotFocus);
232 textbox_ctrl.LostFocus += new EventHandler(textbox_ctrl_LostFocus);
233 textbox_ctrl.MouseDown += new MouseEventHandler(textbox_ctrl_MouseDown);
234 textbox_ctrl.MouseMove += new MouseEventHandler(textbox_ctrl_MouseMove);
235 textbox_ctrl.MouseUp += new MouseEventHandler(textbox_ctrl_MouseUp);
237 if (IsHandleCreated == true) {
238 Controls.AddImplicit (textbox_ctrl);
242 OnDropDownStyleChanged (EventArgs.Empty);
250 public int DropDownWidth {
252 if (dropdown_width == -1)
255 return dropdown_width;
258 if (dropdown_width == value)
262 throw new ArgumentException ("The DropDownWidth value is less than one");
264 dropdown_width = value;
269 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
270 public bool DroppedDown {
272 if (dropdown_style == ComboBoxStyle.Simple)
278 if (dropdown_style == ComboBoxStyle.Simple || dropped_down == value)
284 listbox_ctrl.Hide ();
288 public override bool Focused {
289 get { return base.Focused; }
292 public override Color ForeColor {
293 get { return base.ForeColor; }
295 if (base.ForeColor == value)
298 base.ForeColor = value;
303 [DefaultValue (true)]
305 public bool IntegralHeight {
306 get { return integral_height; }
308 if (integral_height == value)
311 integral_height = value;
318 public int ItemHeight {
320 if (item_height == -1) {
321 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
322 item_height = (int) sz.Height;
328 throw new ArgumentException ("The item height value is less than zero");
330 item_height_specified = true;
339 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
341 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
342 public ComboBox.ObjectCollection Items {
343 get { return items; }
348 public int MaxDropDownItems {
349 get { return maxdrop_items; }
351 if (maxdrop_items == value)
354 maxdrop_items = value;
360 public int MaxLength {
361 get { return max_length; }
363 if (max_length == value)
368 if (dropdown_style != ComboBoxStyle.DropDownList) {
374 textbox_ctrl.MaxLength = value;
379 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
381 public int PreferredHeight {
383 return ItemHeight + 5;
388 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
389 public override int SelectedIndex {
390 get { return Items.IndexOf (selected_item); }
392 if (value <= -2 || value >= Items.Count)
393 throw new ArgumentOutOfRangeException ("Index of out range");
397 item = Items [value];
404 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
406 public object SelectedItem {
407 get { return selected_item; }
409 if (selected_item == value)
412 selected_item = value;
414 if (dropdown_style != ComboBoxStyle.DropDownList) {
415 if (selected_item == null)
418 SetControlText (GetItemText (selected_item));
423 OnSelectedValueChanged (new EventArgs ());
424 OnSelectedIndexChanged (new EventArgs ());
425 OnSelectedItemChanged (new EventArgs ());
426 if (DropDownStyle == ComboBoxStyle.DropDownList)
429 if (listbox_ctrl != null)
430 listbox_ctrl.HighlightedItem = value;
435 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
436 public string SelectedText {
438 if (dropdown_style == ComboBoxStyle.DropDownList)
441 return textbox_ctrl.SelectedText;
444 if (dropdown_style == ComboBoxStyle.DropDownList)
447 textbox_ctrl.SelectedText = value;
452 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
453 public int SelectionLength {
455 if (dropdown_style == ComboBoxStyle.DropDownList)
458 return textbox_ctrl.SelectionLength;
461 if (dropdown_style == ComboBoxStyle.DropDownList)
464 if (textbox_ctrl.SelectionLength == value)
467 textbox_ctrl.SelectionLength = value;
472 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
473 public int SelectionStart {
475 if (dropdown_style == ComboBoxStyle.DropDownList)
478 return textbox_ctrl.SelectionStart;
481 if (dropdown_style == ComboBoxStyle.DropDownList)
484 if (textbox_ctrl.SelectionStart == value)
487 textbox_ctrl.SelectionStart = value;
491 [DefaultValue (false)]
493 get { return sorted; }
505 public override string Text {
507 if (dropdown_style != ComboBoxStyle.DropDownList) {
508 if (textbox_ctrl != null) {
509 return textbox_ctrl.Text;
513 if (SelectedItem != null)
514 return GetItemText (SelectedItem);
524 int index = FindString (value);
527 SelectedIndex = index;
531 if (dropdown_style != ComboBoxStyle.DropDownList)
532 textbox_ctrl.Text = GetItemText (value);
536 #endregion Public Properties
538 #region Public Methods
539 protected virtual void AddItemsCore (object[] value)
544 public void BeginUpdate ()
546 suspend_ctrlupdate = true;
549 protected override void Dispose (bool disposing)
552 if (listbox_ctrl != null) {
553 listbox_ctrl.Dispose ();
554 Controls.RemoveImplicit (listbox_ctrl);
558 if (textbox_ctrl != null) {
559 Controls.RemoveImplicit (textbox_ctrl);
560 textbox_ctrl.Dispose ();
565 base.Dispose (disposing);
568 public void EndUpdate ()
570 suspend_ctrlupdate = false;
575 public int FindString (string s)
577 return FindString (s, -1);
580 public int FindString (string s, int startIndex)
582 if (Items.Count == 0)
583 return -1; // No exception throwing if empty
585 if (startIndex < -1 || startIndex >= Items.Count - 1)
586 throw new ArgumentOutOfRangeException ("Index of out range");
589 for (int i = startIndex; i < Items.Count; i++) {
590 if ((GetItemText (Items[i])).StartsWith (s))
597 public int FindStringExact (string s)
599 return FindStringExact (s, -1);
602 public int FindStringExact (string s, int startIndex)
604 if (Items.Count == 0)
605 return -1; // No exception throwing if empty
607 if (startIndex < -1 || startIndex >= Items.Count - 1)
608 throw new ArgumentOutOfRangeException ("Index of out range");
611 for (int i = startIndex; i < Items.Count; i++) {
612 if ((GetItemText (Items[i])).Equals (s))
619 public int GetItemHeight (int index)
621 if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated) {
623 if (index < 0 || index >= Items.Count )
624 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
626 object item = Items [index];
627 if (item_heights.Contains (item))
628 return (int) item_heights [item];
630 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
631 OnMeasureItem (args);
632 item_heights [item] = args.ItemHeight;
633 return args.ItemHeight;
639 protected override bool IsInputKey (Keys keyData)
653 protected override void OnBackColorChanged (EventArgs e)
655 base.OnBackColorChanged (e);
658 protected override void OnDataSourceChanged (EventArgs e)
660 base.OnDataSourceChanged (e);
661 BindDataItems (items);
663 if (DataSource == null || DataManager == null) {
667 SelectedIndex = DataManager.Position;
671 protected override void OnDisplayMemberChanged (EventArgs e)
673 base.OnDisplayMemberChanged (e);
675 if (DataManager == null || !IsHandleCreated)
678 BindDataItems (items);
679 SelectedIndex = DataManager.Position;
682 protected virtual void OnDrawItem (DrawItemEventArgs e)
685 case DrawMode.OwnerDrawFixed:
686 case DrawMode.OwnerDrawVariable:
687 if (DrawItem != null)
691 ThemeEngine.Current.DrawComboBoxItem (this, e);
696 protected virtual void OnDropDown (EventArgs e)
698 if (DropDown != null)
702 protected virtual void OnDropDownStyleChanged (EventArgs e)
704 if (DropDownStyleChanged != null)
705 DropDownStyleChanged (this, e);
708 protected override void OnFontChanged (EventArgs e)
710 base.OnFontChanged (e);
712 if (textbox_ctrl != null)
713 textbox_ctrl.Font = Font;
715 if (!item_height_specified) {
716 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
717 item_height = (int) sz.Height;
726 protected override void OnForeColorChanged (EventArgs e)
728 base.OnForeColorChanged (e);
731 [EditorBrowsable(EditorBrowsableState.Advanced)]
732 protected override void OnGotFocus (EventArgs e) {
737 [EditorBrowsable(EditorBrowsableState.Advanced)]
738 protected override void OnLostFocus (EventArgs e) {
743 protected override void OnHandleCreated (EventArgs e)
745 base.OnHandleCreated (e);
747 if (listbox_ctrl != null)
748 Controls.AddImplicit (listbox_ctrl);
750 if (textbox_ctrl != null)
751 Controls.AddImplicit (textbox_ctrl);
756 protected override void OnHandleDestroyed (EventArgs e)
758 base.OnHandleDestroyed (e);
761 protected override void OnKeyPress (KeyPressEventArgs e)
766 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
768 if (MeasureItem != null)
769 MeasureItem (this, e);
772 protected override void OnParentBackColorChanged (EventArgs e)
774 base.OnParentBackColorChanged (e);
777 protected override void OnResize (EventArgs e)
780 if (listbox_ctrl != null)
781 listbox_ctrl.CalcListBoxArea ();
784 protected override void OnSelectedIndexChanged (EventArgs e)
786 base.OnSelectedIndexChanged (e);
788 if (SelectedIndexChanged != null)
789 SelectedIndexChanged (this, e);
792 protected virtual void OnSelectedItemChanged (EventArgs e)
797 protected override void OnSelectedValueChanged (EventArgs e)
799 base.OnSelectedValueChanged (e);
802 protected virtual void OnSelectionChangeCommitted (EventArgs e)
804 if (SelectionChangeCommitted != null)
805 SelectionChangeCommitted (this, e);
808 protected override void RefreshItem (int index)
810 if (index < 0 || index >= Items.Count)
811 throw new ArgumentOutOfRangeException ("Index of out range");
813 if (draw_mode == DrawMode.OwnerDrawVariable)
814 item_heights.Remove (Items [index]);
817 public void Select (int start, int length)
820 throw new ArgumentException ("Start cannot be less than zero");
823 throw new ArgumentException ("length cannot be less than zero");
825 if (dropdown_style == ComboBoxStyle.DropDownList)
828 textbox_ctrl.Select (start, length);
831 public void SelectAll ()
833 if (dropdown_style == ComboBoxStyle.DropDownList)
836 textbox_ctrl.SelectAll ();
839 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
841 if ((specified & BoundsSpecified.Height) != 0) {
842 requested_height = height;
844 if (DropDownStyle == ComboBoxStyle.Simple && height > PreferredHeight) {
845 if (IntegralHeight) {
846 int border = ThemeEngine.Current.Border3DSize.Height;
847 int lb_height = height - PreferredHeight - 2;
848 if (lb_height - 2 * border > ItemHeight) {
849 int partial = (lb_height - 2 * border) % ItemHeight;
852 height = PreferredHeight;
855 height = PreferredHeight;
858 base.SetBoundsCore (x, y, width, height, specified);
861 protected override void SetItemCore (int index, object value)
863 if (index < 0 || index >= Items.Count)
866 Items[index] = value;
869 protected override void SetItemsCore (IList value)
871 Items.AddRange (value);
874 public override string ToString ()
876 return base.ToString () + ", Items.Count:" + Items.Count;
879 protected override void WndProc (ref Message m)
881 switch ((Msg) m.Msg) {
882 case Msg.WM_MOUSE_LEAVE:
883 Point location = PointToClient (Control.MousePosition);
884 if (ClientRectangle.Contains (location))
890 base.WndProc (ref m);
893 #endregion Public Methods
895 #region Private Methods
897 internal override bool InternalCapture {
898 get { return Capture; }
902 private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e)
907 private void textbox_ctrl_GotFocus(object sender, EventArgs e )
912 private void textbox_ctrl_LostFocus(object sender, EventArgs e )
917 private void textbox_ctrl_MouseDown(object sender, MouseEventArgs e )
922 private void textbox_ctrl_MouseMove(object sender, MouseEventArgs e )
927 private void textbox_ctrl_MouseUp(object sender, MouseEventArgs e )
934 int border = ThemeEngine.Current.Border3DSize.Width;
936 text_area = ClientRectangle;
937 text_area.Height = PreferredHeight;
939 listbox_area = ClientRectangle;
940 listbox_area.Y = text_area.Bottom + 3;
941 listbox_area.Height -= (text_area.Height + 2);
943 Rectangle prev_button_area = button_area;
945 if (DropDownStyle == ComboBoxStyle.Simple)
946 button_area = Rectangle.Empty;
948 button_area = text_area;
949 button_area.X = text_area.Right - button_width - border;
950 button_area.Y = text_area.Y + border;
951 button_area.Width = button_width;
952 button_area.Height = text_area.Height - 2 * border;
955 if (button_area != prev_button_area) {
956 prev_button_area.Y -= border;
957 prev_button_area.Width += border;
958 prev_button_area.Height += 2 * border;
959 Invalidate (prev_button_area);
960 Invalidate (button_area);
963 if (textbox_ctrl != null) {
964 textbox_ctrl.Location = new Point (text_area.X + border, text_area.Y + border);
965 textbox_ctrl.Width = text_area.Width - button_area.Width - border * 2;
966 textbox_ctrl.Height = text_area.Height - border * 2;
969 if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
970 listbox_ctrl.Location = listbox_area.Location;
971 listbox_ctrl.CalcListBoxArea ();
975 private void CreateComboListBox ()
977 listbox_ctrl = new ComboListBox (this);
978 if (selected_item != null)
979 listbox_ctrl.HighlightedItem = selected_item;
982 internal void Draw (Rectangle clip, Graphics dc)
984 Theme theme = ThemeEngine.Current;
986 if (DropDownStyle == ComboBoxStyle.Simple)
987 dc.FillRectangle (theme.ResPool.GetSolidBrush (Parent.BackColor), ClientRectangle);
989 if (clip.IntersectsWith (text_area))
990 ControlPaint.DrawBorder3D (dc, text_area, Border3DStyle.Sunken);
992 int border = theme.Border3DSize.Width;
994 // No edit control, we paint the edit ourselves
995 if (dropdown_style == ComboBoxStyle.DropDownList) {
996 DrawItemState state = DrawItemState.None;
997 Rectangle item_rect = text_area;
998 item_rect.X += border;
999 item_rect.Y += border;
1000 item_rect.Width -= (button_area.Width + 2 * border);
1001 item_rect.Height -= 2 * border;
1004 state = DrawItemState.Selected;
1005 state |= DrawItemState.Focus;
1008 state |= DrawItemState.ComboBoxEdit;
1009 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, ForeColor, BackColor));
1012 if (show_dropdown_button) {
1013 dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area);
1016 button_state = ButtonState.Inactive;
1018 theme.CPDrawComboButton (dc, button_area, button_state);
1022 internal void DropDownListBox ()
1024 if (DropDownStyle == ComboBoxStyle.Simple)
1027 if (listbox_ctrl == null)
1028 CreateComboListBox ();
1030 listbox_ctrl.Location = PointToScreen (new Point (text_area.X, text_area.Y + text_area.Height));
1032 if (listbox_ctrl.ShowWindow ())
1033 dropped_down = true;
1035 button_state = ButtonState.Pushed;
1036 if (dropdown_style == ComboBoxStyle.DropDownList)
1037 Invalidate (text_area);
1039 OnDropDown (EventArgs.Empty);
1042 internal void DropDownListBoxFinished ()
1044 if (DropDownStyle == ComboBoxStyle.Simple)
1047 button_state = ButtonState.Normal;
1048 Invalidate (button_area);
1049 dropped_down = false;
1052 private int FindStringCaseInsensitive (string search)
1054 if (search.Length == 0) {
1058 for (int i = 0; i < Items.Count; i++)
1060 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1067 private void OnKeyDownCB(object sender, KeyEventArgs e)
1069 if (Items.Count == 0)
1075 SelectedIndex = Math.Max(SelectedIndex-1, 0);
1079 SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1);
1083 if (listbox_ctrl != null)
1084 SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0);
1088 if (listbox_ctrl != null)
1089 SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1);
1097 void OnMouseDownCB (object sender, MouseEventArgs e)
1100 if (DropDownStyle == ComboBoxStyle.DropDownList)
1101 area = ClientRectangle;
1105 if (area.Contains (e.X, e.Y)) {
1107 Invalidate (button_area);
1113 void OnMouseMoveCB (object sender, MouseEventArgs e)
1115 if (DropDownStyle == ComboBoxStyle.Simple)
1118 if (listbox_ctrl != null && listbox_ctrl.Visible) {
1119 Point location = listbox_ctrl.PointToClient (Control.MousePosition);
1120 if (listbox_ctrl.ClientRectangle.Contains (location))
1121 listbox_ctrl.Capture = true;
1125 void OnMouseUpCB (object sender, MouseEventArgs e)
1128 OnClick (EventArgs.Empty);
1131 listbox_ctrl.Capture = true;
1134 internal override void OnPaintInternal (PaintEventArgs pevent)
1136 if (suspend_ctrlupdate)
1139 Draw (ClientRectangle, pevent.Graphics);
1142 private void OnTextChangedEdit (object sender, EventArgs e)
1144 if (process_textchanged_event == false)
1147 int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1152 if (listbox_ctrl != null) {
1153 listbox_ctrl.SetTopItem (item);
1154 listbox_ctrl.HighlightedItem = Items [item];
1158 internal void SetControlText (string s)
1160 process_textchanged_event = false;
1161 textbox_ctrl.Text = s;
1162 process_textchanged_event = true;
1165 void UpdateBounds ()
1167 if (requested_height != -1)
1168 SetBoundsCore (0, 0, 0, requested_height, BoundsSpecified.Height);
1171 private void UpdatedItems ()
1173 if (listbox_ctrl != null) {
1174 listbox_ctrl.UpdateLastVisibleItem ();
1175 listbox_ctrl.CalcListBoxArea ();
1176 listbox_ctrl.Refresh ();
1180 #endregion Private Methods
1182 [ListBindableAttribute (false)]
1183 public class ObjectCollection : IList, ICollection, IEnumerable
1186 private ComboBox owner;
1187 internal ArrayList object_items = new ArrayList ();
1189 public ObjectCollection (ComboBox owner)
1194 #region Public Properties
1196 get { return object_items.Count; }
1199 public bool IsReadOnly {
1200 get { return false; }
1204 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1205 public virtual object this [int index] {
1207 if (index < 0 || index >= Count)
1208 throw new ArgumentOutOfRangeException ("Index of out range");
1210 return object_items[index];
1213 if (index < 0 || index >= Count)
1214 throw new ArgumentOutOfRangeException ("Index of out range");
1216 object_items[index] = value;
1220 bool ICollection.IsSynchronized {
1221 get { return false; }
1224 object ICollection.SyncRoot {
1225 get { return this; }
1228 bool IList.IsFixedSize {
1229 get { return false; }
1232 #endregion Public Properties
1234 #region Private Properties
1235 internal ArrayList ObjectItems {
1236 get { return object_items;}
1238 object_items = value;
1242 #endregion Private Properties
1244 #region Public Methods
1245 public int Add (object item)
1249 idx = AddItem (item);
1250 owner.UpdatedItems ();
1254 public void AddRange (object[] items)
1256 foreach (object mi in items)
1259 owner.UpdatedItems ();
1262 public void Clear ()
1264 owner.selected_item = null;
1265 object_items.Clear ();
1266 owner.UpdatedItems ();
1270 public bool Contains (object obj)
1272 return object_items.Contains (obj);
1275 public void CopyTo (object[] dest, int arrayIndex)
1277 object_items.CopyTo (dest, arrayIndex);
1280 void ICollection.CopyTo (Array dest, int index)
1282 object_items.CopyTo (dest, index);
1285 public IEnumerator GetEnumerator ()
1287 return object_items.GetEnumerator ();
1290 int IList.Add (object item)
1295 public int IndexOf (object value)
1297 return object_items.IndexOf (value);
1300 public void Insert (int index, object item)
1302 if (index < 0 || index > Count)
1303 throw new ArgumentOutOfRangeException ("Index of out range");
1305 owner.BeginUpdate ();
1307 object_items.Insert (index, item);
1309 owner.EndUpdate (); // Calls UpdatedItems
1312 public void Remove (object value)
1314 if (IndexOf (value) == owner.SelectedIndex)
1315 owner.SelectedItem = null;
1317 RemoveAt (IndexOf (value));
1321 public void RemoveAt (int index)
1323 if (index < 0 || index >= Count)
1324 throw new ArgumentOutOfRangeException ("Index of out range");
1326 if (index == owner.SelectedIndex)
1327 owner.SelectedItem = null;
1329 object_items.RemoveAt (index);
1330 owner.UpdatedItems ();
1332 #endregion Public Methods
1334 #region Private Methods
1335 private int AddItem (object item)
1337 int cnt = object_items.Count;
1338 object_items.Add (item);
1342 internal void AddRange (IList items)
1344 foreach (object mi in items)
1347 owner.UpdatedItems ();
1350 #endregion Private Methods
1353 internal class ComboListBox : Control
1355 private ComboBox owner;
1356 private VScrollBarLB vscrollbar_ctrl;
1357 private int top_item; /* First item that we show the in the current page */
1358 private int last_item; /* Last visible item */
1359 internal int page_size; /* Number of listbox items per page */
1360 private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
1362 internal enum ItemNavigation
1372 class VScrollBarLB : VScrollBar
1374 public VScrollBarLB ()
1378 internal override bool InternalCapture {
1379 get { return Capture; }
1383 public bool FireMouseDown (MouseEventArgs e)
1386 e = TranslateEvent (e);
1387 if (ClientRectangle.Contains (e.X, e.Y)) {
1395 public void FireMouseUp (MouseEventArgs e)
1398 e = TranslateEvent (e);
1399 if (ClientRectangle.Contains (e.X, e.Y))
1404 public void FireMouseMove (MouseEventArgs e)
1407 e = TranslateEvent (e);
1408 if (ClientRectangle.Contains (e.X, e.Y))
1413 MouseEventArgs TranslateEvent (MouseEventArgs e)
1415 Point loc = PointToClient (Control.MousePosition);
1416 return new MouseEventArgs (e.Button, e.Clicks, loc.X, loc.Y, e.Delta);
1420 public ComboListBox (ComboBox owner)
1427 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1428 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1429 MouseMove += new MouseEventHandler (OnMouseMovePUW);
1430 MouseWheel += new MouseEventHandler (OnMouseWheelCLB);
1431 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1432 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1433 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1435 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1436 InternalBorderStyle = BorderStyle.Fixed3D;
1438 InternalBorderStyle = BorderStyle.FixedSingle;
1441 protected override CreateParams CreateParams
1444 CreateParams cp = base.CreateParams;
1445 if (owner == null || owner.DropDownStyle == ComboBoxStyle.Simple)
1448 cp.Style ^= (int) WindowStyles.WS_CHILD;
1449 cp.Style |= (int) WindowStyles.WS_POPUP;
1450 cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST;
1455 internal override bool InternalCapture {
1464 protected override void OnLostFocus(EventArgs e) {
1468 base.OnLostFocus (e);
1474 switch (border_style) {
1475 case BorderStyle.Fixed3D:
1476 return ThemeEngine.Current.Border3DSize.Width;
1478 return ThemeEngine.Current.BorderSize.Width;
1483 #region Private Methods
1484 // Calcs the listbox area
1485 internal void CalcListBoxArea ()
1488 bool show_scrollbar = false;
1490 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1491 Rectangle area = owner.listbox_area;
1493 height = area.Height;
1495 else { // DropDown or DropDownList
1497 width = owner.DropDownWidth;
1498 int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
1500 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1502 for (int i = 0; i < count; i++) {
1503 height += owner.GetItemHeight (i);
1507 height = owner.ItemHeight * count;
1511 if (owner.Items.Count <= owner.MaxDropDownItems) {
1512 if (vscrollbar_ctrl != null)
1513 vscrollbar_ctrl.Visible = false;
1515 /* Need vertical scrollbar */
1516 if (vscrollbar_ctrl == null) {
1517 vscrollbar_ctrl = new VScrollBarLB ();
1518 vscrollbar_ctrl.Minimum = 0;
1519 vscrollbar_ctrl.SmallChange = 1;
1520 vscrollbar_ctrl.LargeChange = 1;
1521 vscrollbar_ctrl.Maximum = 0;
1522 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1523 Controls.AddImplicit (vscrollbar_ctrl);
1526 vscrollbar_ctrl.Height = height - 2 * BorderWidth;
1528 vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - BorderWidth - 1, 0);
1530 vscrollbar_ctrl.Maximum = owner.Items.Count - (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items);
1531 show_scrollbar = vscrollbar_ctrl.Visible = true;
1533 int hli = HighlightedIndex;
1535 hli = Math.Min (hli, vscrollbar_ctrl.Maximum);
1536 vscrollbar_ctrl.Value = hli;
1540 Size = new Size (width, height);
1541 textarea_drawable = ClientRectangle;
1542 textarea_drawable.Width = width;
1543 textarea_drawable.Height = height;
1545 if (vscrollbar_ctrl != null && show_scrollbar)
1546 textarea_drawable.Width -= vscrollbar_ctrl.Width;
1548 last_item = LastVisibleItem ();
1549 page_size = textarea_drawable.Height / owner.ItemHeight;
1552 private void Draw (Rectangle clip, Graphics dc)
1554 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (owner.BackColor), clip);
1556 if (owner.Items.Count > 0) {
1558 for (int i = top_item; i <= last_item; i++) {
1559 Rectangle item_rect = GetItemDisplayRectangle (i, top_item);
1561 if (!clip.IntersectsWith (item_rect))
1564 DrawItemState state = DrawItemState.None;
1566 if (i == HighlightedIndex) {
1567 state |= DrawItemState.Selected;
1569 if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1570 state |= DrawItemState.Focus;
1574 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1575 i, state, owner.ForeColor, owner.BackColor));
1580 public int HighlightedIndex {
1581 get { return owner.Items.IndexOf (highlighted_item); }
1585 item = owner.Items [value];
1586 HighlightedItem = item;
1590 object highlighted_item = null;
1592 public object HighlightedItem {
1593 get { return highlighted_item; }
1595 if (highlighted_item == value)
1598 int index = owner.Items.IndexOf (highlighted_item);
1600 Invalidate (GetItemDisplayRectangle (index, top_item));
1601 highlighted_item = value;
1602 index = owner.Items.IndexOf (highlighted_item);
1604 Invalidate (GetItemDisplayRectangle (index, top_item));
1608 private Rectangle GetItemDisplayRectangle (int index, int top_index)
1610 if (index < 0 || index >= owner.Items.Count)
1611 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1613 Rectangle item_rect = new Rectangle ();
1614 int height = owner.GetItemHeight (index);
1617 item_rect.Width = textarea_drawable.Width;
1618 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1620 for (int i = top_index; i < index; i++)
1621 item_rect.Y += owner.GetItemHeight (i);
1623 item_rect.Y = height * (index - top_index);
1625 item_rect.Height = height;
1629 public void HideWindow ()
1631 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1636 owner.DropDownListBoxFinished ();
1639 private int IndexFromPointDisplayRectangle (int x, int y)
1641 for (int i = top_item; i <= last_item; i++) {
1642 if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1649 protected override bool IsInputKey (Keys keyData)
1651 return owner.IsInputKey (keyData);
1654 private int LastVisibleItem ()
1656 Rectangle item_rect;
1657 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1660 for (i = top_item; i < owner.Items.Count; i++) {
1661 item_rect = GetItemDisplayRectangle (i, top_item);
1662 if (item_rect.Y + item_rect.Height > top_y) {
1669 private void NavigateItemVisually (ItemNavigation navigation)
1673 switch (navigation) {
1674 case ItemNavigation.Next:
1675 if (HighlightedIndex + 1 < owner.Items.Count) {
1676 if (HighlightedIndex + 1 > last_item) {
1678 vscrollbar_ctrl.Value = top_item;
1680 item = HighlightedIndex + 1;
1684 case ItemNavigation.Previous:
1685 if (HighlightedIndex > 0) {
1686 if (HighlightedIndex - 1 < top_item) {
1688 vscrollbar_ctrl.Value = top_item;
1690 item = HighlightedIndex - 1;
1694 case ItemNavigation.NextPage:
1695 if (HighlightedIndex + page_size - 1 >= owner.Items.Count) {
1696 top_item = owner.Items.Count - page_size;
1697 vscrollbar_ctrl.Value = top_item;
1698 item = owner.Items.Count - 1;
1700 if (HighlightedIndex + page_size - 1 > last_item) {
1701 top_item = HighlightedIndex;
1702 vscrollbar_ctrl.Value = HighlightedIndex;
1704 item = HighlightedIndex + page_size - 1;
1708 case ItemNavigation.PreviousPage:
1709 if (HighlightedIndex - page_size - 1 <= 0) {
1711 vscrollbar_ctrl.Value = top_item;
1714 if (HighlightedIndex - page_size - 1 < top_item) {
1715 top_item = HighlightedIndex - page_size - 1;
1716 vscrollbar_ctrl.Value = top_item;
1718 item = HighlightedIndex - page_size - 1;
1727 HighlightedIndex = item;
1728 owner.OnSelectionChangeCommitted (new EventArgs ());
1729 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1730 owner.SetControlText (owner.GetItemText (owner.Items[item]));
1734 private void OnKeyDownPUW (object sender, KeyEventArgs e)
1736 switch (e.KeyCode) {
1738 NavigateItemVisually (ItemNavigation.Previous);
1742 NavigateItemVisually (ItemNavigation.Next);
1746 NavigateItemVisually (ItemNavigation.PreviousPage);
1750 NavigateItemVisually (ItemNavigation.NextPage);
1758 public void SetTopItem (int item)
1760 if (top_item == item)
1763 UpdateLastVisibleItem ();
1767 private void OnMouseDownPUW (object sender, MouseEventArgs e)
1769 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1772 if (vscrollbar_ctrl == null || !vscrollbar_ctrl.FireMouseDown (e))
1775 owner.OnSelectionChangeCommitted (new EventArgs ());
1776 owner.SelectedIndex = index;
1777 HighlightedIndex = index;
1781 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1782 owner.OnMouseDown (e);
1783 owner.textbox_ctrl.Focus ();
1787 private void OnMouseMovePUW (object sender, MouseEventArgs e)
1789 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1790 owner.OnMouseMove (e);
1794 Point pt = PointToClient (Control.MousePosition);
1795 int index = IndexFromPointDisplayRectangle (pt.X, pt.Y);
1798 HighlightedIndex = index;
1802 if (vscrollbar_ctrl != null)
1803 vscrollbar_ctrl.FireMouseMove (e);
1806 private void OnMouseUpPUW (object sender, MouseEventArgs e)
1808 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1809 owner.OnMouseUp (e);
1813 if (vscrollbar_ctrl != null)
1814 vscrollbar_ctrl.FireMouseUp (e);
1817 internal override void OnPaintInternal (PaintEventArgs pevent)
1819 Draw (pevent.ClipRectangle,pevent.Graphics);
1822 public bool ShowWindow ()
1824 if (owner.DropDownStyle == ComboBoxStyle.Simple && owner.Items.Count == 0)
1827 HighlightedIndex = owner.SelectedIndex;
1833 owner.OnDropDown (EventArgs.Empty);
1837 public void UpdateLastVisibleItem ()
1839 last_item = LastVisibleItem ();
1842 private void Scroll (int delta)
1844 if (delta == 0 || !vscrollbar_ctrl.Visible)
1847 int max = vscrollbar_ctrl.Maximum;//- (page_size) + 1;
1849 int val = vscrollbar_ctrl.Value + delta;
1852 else if (val < vscrollbar_ctrl.Minimum)
1853 val = vscrollbar_ctrl.Minimum;
1854 vscrollbar_ctrl.Value = val;
1857 private void OnMouseWheelCLB (object sender, MouseEventArgs me)
1859 if (owner.Items.Count == 0)
1862 int lines = me.Delta / 120 * SystemInformation.MouseWheelScrollLines;
1867 private void VerticalScrollEvent (object sender, EventArgs e)
1869 if (top_item == vscrollbar_ctrl.Value)
1872 top_item = vscrollbar_ctrl.Value;
1873 UpdateLastVisibleItem ();
1877 #endregion Private Methods