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-2005 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
31 using System.Collections;
32 using System.ComponentModel;
33 using System.Reflection;
34 using System.ComponentModel.Design;
35 using System.ComponentModel.Design.Serialization;
36 using System.Runtime.InteropServices;
39 namespace System.Windows.Forms
42 [DefaultProperty("Items")]
43 [DefaultEvent("SelectedIndexChanged")]
44 [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 public class ComboBox : ListControl
47 private DrawMode draw_mode;
48 private ComboBoxStyle dropdown_style;
49 private int dropdown_width;
50 private int preferred_height;
51 private int selected_index;
52 private object selected_item;
53 internal ObjectCollection items = null;
54 private bool suspend_ctrlupdate;
55 private int maxdrop_items;
56 private bool integral_height;
58 internal ComboBoxInfo combobox_info;
59 private readonly int def_button_width = 16;
61 private int max_length;
62 private ComboListBox listbox_ctrl;
63 private TextBox textbox_ctrl;
64 private bool process_textchanged_event;
67 public class ChildAccessibleObject : AccessibleObject {
68 private ComboBox owner;
69 private IntPtr handle;
71 public ChildAccessibleObject (ComboBox owner, IntPtr handle) {
76 public override string Name {
85 internal class ComboBoxInfo
87 internal int item_height; /* Item's height */
88 internal Rectangle textarea; /* Rectangle of the editable text area */
89 internal Rectangle textarea_drawable; /* Rectangle of the editable text area - decorations - button if present*/
90 internal Rectangle button_rect;
91 internal bool show_button; /* Is the DropDown button shown? */
92 internal ButtonState button_status; /* Drop button status */
93 internal Rectangle listbox_area; /* ListBox area in Simple combox, not used in the rest */
94 internal bool droppeddown; /* Is the associated ListBox dropped down? */
95 internal int combosimple_height; /* Simple default height */
97 public ComboBoxInfo ()
99 button_status = ButtonState.Normal;
103 combosimple_height = 150;
107 internal class ComboBoxItem
110 internal int ItemHeight; /* Only used for OwnerDrawVariable */
112 public ComboBoxItem (int index)
121 items = new ObjectCollection (this);
124 combobox_info = new ComboBoxInfo ();
125 combobox_info.item_height = FontHeight + 2;
126 dropdown_style = (ComboBoxStyle)(-1);
127 DropDownStyle = ComboBoxStyle.DropDown;
128 BackColor = ThemeEngine.Current.ColorWindow;
129 draw_mode = DrawMode.Normal;
131 selected_item = null;
133 suspend_ctrlupdate = false;
137 integral_height = true;
138 process_textchanged_event = true;
140 border_style = BorderStyle.Fixed3D;
142 CalcPreferredHeight ();
145 MouseDown += new MouseEventHandler (OnMouseDownCB);
146 MouseUp += new MouseEventHandler (OnMouseUpCB);
147 MouseMove += new MouseEventHandler (OnMouseMoveCB);
148 KeyDown +=new KeyEventHandler(OnKeyDownCB);
154 [EditorBrowsable (EditorBrowsableState.Never)]
155 public new event EventHandler BackgroundImageChanged {
156 add { base.BackgroundImageChanged += value; }
157 remove { base.BackgroundImageChanged -= value; }
160 public event DrawItemEventHandler DrawItem;
161 public event EventHandler DropDown;
162 public event EventHandler DropDownStyleChanged;
163 public event MeasureItemEventHandler MeasureItem;
166 [EditorBrowsable (EditorBrowsableState.Never)]
167 public new event PaintEventHandler Paint {
168 add { base.Paint += value; }
169 remove { base.Paint -= value; }
172 public event EventHandler SelectedIndexChanged;
173 public event EventHandler SelectionChangeCommitted;
176 #region Public Properties
177 public override Color BackColor {
178 get { return base.BackColor; }
180 if (base.BackColor == value)
183 base.BackColor = value;
189 [EditorBrowsable (EditorBrowsableState.Never)]
190 public override Image BackgroundImage {
191 get { return base.BackgroundImage; }
193 if (base.BackgroundImage == value)
196 base.BackgroundImage = value;
201 protected override CreateParams CreateParams {
202 get { return base.CreateParams;}
205 protected override Size DefaultSize {
206 get { return new Size (121, 21); }
209 [RefreshProperties(RefreshProperties.Repaint)]
210 [DefaultValue (DrawMode.Normal)]
211 public DrawMode DrawMode {
212 get { return draw_mode; }
215 if (!Enum.IsDefined (typeof (DrawMode), value))
216 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
218 if (draw_mode == value)
226 [DefaultValue (ComboBoxStyle.DropDown)]
227 [RefreshProperties(RefreshProperties.Repaint)]
228 public ComboBoxStyle DropDownStyle {
229 get { return dropdown_style; }
233 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
234 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
236 if (dropdown_style == value)
239 if (dropdown_style == ComboBoxStyle.Simple) {
240 if (listbox_ctrl != null) {
241 Controls.RemoveImplicit (listbox_ctrl);
242 listbox_ctrl.Dispose ();
247 if (dropdown_style != ComboBoxStyle.DropDownList && value == ComboBoxStyle.DropDownList) {
248 if (textbox_ctrl != null) {
249 Controls.RemoveImplicit (textbox_ctrl);
250 textbox_ctrl.Dispose ();
255 dropdown_style = value;
257 if (dropdown_style == ComboBoxStyle.Simple) {
258 CBoxInfo.show_button = false;
260 CreateComboListBox ();
262 if (IsHandleCreated == true) {
263 Controls.AddImplicit (listbox_ctrl);
267 CBoxInfo.show_button = true;
268 CBoxInfo.button_status = ButtonState.Normal;
271 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
272 textbox_ctrl = new FixedSizeTextBox ();
273 textbox_ctrl.BorderStyle = BorderStyle.None;
274 textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
275 textbox_ctrl.KeyPress += new KeyPressEventHandler(textbox_ctrl_KeyPress);
276 textbox_ctrl.KeyDown += new KeyEventHandler (OnKeyDownCB);
277 textbox_ctrl.GotFocus += new EventHandler(textbox_ctrl_GotFocus);
278 textbox_ctrl.LostFocus += new EventHandler(textbox_ctrl_LostFocus);
280 if (IsHandleCreated == true) {
281 Controls.AddImplicit (textbox_ctrl);
285 if (DropDownStyleChanged != null)
286 DropDownStyleChanged (this, EventArgs.Empty);
293 public int DropDownWidth {
295 if (dropdown_width == -1)
298 return dropdown_width;
301 if (dropdown_width == value)
305 throw new ArgumentException ("The DropDownWidth value is less than one");
307 dropdown_width = value;
312 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
313 public bool DroppedDown {
315 if (dropdown_style == ComboBoxStyle.Simple)
318 return CBoxInfo.droppeddown;
321 if (dropdown_style == ComboBoxStyle.Simple)
329 listbox_ctrl.Hide ();
332 if (DropDown != null)
333 DropDown (this, EventArgs.Empty);
337 public override bool Focused {
338 get { return base.Focused; }
341 public override Color ForeColor {
342 get { return base.ForeColor; }
344 if (base.ForeColor == value)
347 base.ForeColor = value;
352 [DefaultValue (true)]
354 public bool IntegralHeight {
355 get { return integral_height; }
357 if (integral_height == value)
360 integral_height = value;
366 public int ItemHeight {
367 get { return combobox_info.item_height; }
370 throw new ArgumentException ("The item height value is less than zero");
372 combobox_info.item_height = value;
378 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
380 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
381 public ComboBox.ObjectCollection Items {
382 get { return items; }
387 public int MaxDropDownItems {
388 get { return maxdrop_items; }
390 if (maxdrop_items == value)
393 maxdrop_items = value;
399 public int MaxLength {
400 get { return max_length; }
402 if (max_length == value)
407 if (dropdown_style != ComboBoxStyle.DropDownList) {
413 textbox_ctrl.MaxLength = value;
418 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
420 public int PreferredHeight {
421 get { return preferred_height; }
425 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
426 public override int SelectedIndex {
427 get { return selected_index; }
429 if (value <= -2 || value >= Items.Count)
430 throw new ArgumentOutOfRangeException ("Index of out range");
432 if (selected_index == value)
435 selected_index = value;
437 if (dropdown_style != ComboBoxStyle.DropDownList) {
438 if (selected_index != -1) {
439 SetControlText (GetItemText (Items[selected_index]));
445 OnSelectedIndexChanged (new EventArgs ());
446 OnSelectedValueChanged (new EventArgs ());
447 OnSelectedItemChanged (new EventArgs ());
453 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
455 public object SelectedItem {
457 if (selected_index !=-1 && Items !=null && Items.Count > 0)
458 return Items[selected_index];
463 int index = Items.IndexOf (value);
468 if (selected_index == index)
471 selected_index = index;
473 if (dropdown_style != ComboBoxStyle.DropDownList) {
474 SetControlText (GetItemText (Items[selected_index]));
477 OnSelectedItemChanged (new EventArgs ());
483 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
484 public string SelectedText {
486 if (dropdown_style == ComboBoxStyle.DropDownList)
489 return textbox_ctrl.SelectedText;
492 if (dropdown_style == ComboBoxStyle.DropDownList) {
496 textbox_ctrl.SelectedText = value;
501 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
502 public int SelectionLength {
504 if (dropdown_style == ComboBoxStyle.DropDownList)
507 return textbox_ctrl.SelectionLength;
510 if (dropdown_style == ComboBoxStyle.DropDownList)
513 if (textbox_ctrl.SelectionLength == value)
516 textbox_ctrl.SelectionLength = value;
521 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
522 public int SelectionStart {
524 if (dropdown_style == ComboBoxStyle.DropDownList)
527 return textbox_ctrl.SelectionStart;
530 if (dropdown_style == ComboBoxStyle.DropDownList)
533 if (textbox_ctrl.SelectionStart == value)
536 textbox_ctrl.SelectionStart = value;
540 [DefaultValue (false)]
542 get { return sorted; }
554 public override string Text {
556 if (dropdown_style != ComboBoxStyle.DropDownList) {
557 if (textbox_ctrl != null) {
558 return textbox_ctrl.Text;
562 if (SelectedItem != null) {
563 return GetItemText (SelectedItem);
574 int index = FindString (value);
577 SelectedIndex = index;
581 if (dropdown_style != ComboBoxStyle.DropDownList) {
582 textbox_ctrl.Text = GetItemText (value);
587 #endregion Public Properties
589 #region Private Properties
590 internal ComboBoxInfo CBoxInfo {
591 get { return combobox_info; }
594 #endregion Private Properties
596 #region Public Methods
597 protected virtual void AddItemsCore (object[] value)
602 public void BeginUpdate ()
604 suspend_ctrlupdate = true;
607 protected override void Dispose (bool disposing)
609 if (disposing == true) {
610 if (listbox_ctrl != null) {
611 listbox_ctrl.Dispose ();
612 Controls.RemoveImplicit (listbox_ctrl);
616 if (textbox_ctrl != null) {
617 Controls.RemoveImplicit (textbox_ctrl);
618 textbox_ctrl.Dispose ();
623 base.Dispose (disposing);
626 public void EndUpdate ()
628 suspend_ctrlupdate = false;
632 public int FindString (string s)
634 return FindString (s, -1);
637 public int FindString (string s, int startIndex)
639 if (Items.Count == 0)
640 return -1; // No exception throwing if empty
642 if (startIndex < -1 || startIndex >= Items.Count - 1)
643 throw new ArgumentOutOfRangeException ("Index of out range");
646 for (int i = startIndex; i < Items.Count; i++) {
647 if ((GetItemText (Items[i])).StartsWith (s))
654 public int FindStringExact (string s)
656 return FindStringExact (s, -1);
659 public int FindStringExact (string s, int startIndex)
661 if (Items.Count == 0)
662 return -1; // No exception throwing if empty
664 if (startIndex < -1 || startIndex >= Items.Count - 1)
665 throw new ArgumentOutOfRangeException ("Index of out range");
668 for (int i = startIndex; i < Items.Count; i++) {
669 if ((GetItemText (Items[i])).Equals (s))
676 public int GetItemHeight (int index)
678 if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {
680 if (index < 0 || index >= Items.Count )
681 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
683 if ((Items.GetComboBoxItem (index)).ItemHeight != -1) {
684 return (Items.GetComboBoxItem (index)).ItemHeight;
687 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
688 OnMeasureItem (args);
689 (Items.GetComboBoxItem (index)).ItemHeight = args.ItemHeight;
690 return args.ItemHeight;
696 protected override bool IsInputKey (Keys keyData)
710 protected override void OnBackColorChanged (EventArgs e)
712 base.OnBackColorChanged (e);
715 protected override void OnDataSourceChanged (EventArgs e)
717 base.OnDataSourceChanged (e);
718 BindDataItems (items);
720 if (DataSource == null || DataManager == null) {
724 SelectedIndex = DataManager.Position;
728 protected override void OnDisplayMemberChanged (EventArgs e)
730 base.OnDisplayMemberChanged (e);
732 if (DataManager == null || !IsHandleCreated)
735 BindDataItems (items);
736 SelectedIndex = DataManager.Position;
739 protected virtual void OnDrawItem (DrawItemEventArgs e)
741 if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) {
746 ThemeEngine.Current.DrawComboBoxItem (this, e);
749 protected virtual void OnDropDown (EventArgs e)
751 if (DropDown != null)
755 protected virtual void OnDropDownStyleChanged (EventArgs e)
757 if (DropDownStyleChanged != null)
758 DropDownStyleChanged (this, e);
761 protected override void OnFontChanged (EventArgs e)
763 base.OnFontChanged (e);
764 CalcPreferredHeight ();
766 if (textbox_ctrl != null) {
767 textbox_ctrl.Font = Font;
770 combobox_info.item_height = FontHeight + 2;
774 protected override void OnForeColorChanged (EventArgs e)
776 base.OnForeColorChanged (e);
779 [EditorBrowsable(EditorBrowsableState.Advanced)]
780 protected override void OnGotFocus (EventArgs e) {
785 [EditorBrowsable(EditorBrowsableState.Advanced)]
786 protected override void OnLostFocus (EventArgs e) {
791 protected override void OnHandleCreated (EventArgs e)
793 base.OnHandleCreated (e);
795 if (listbox_ctrl != null) {
796 Controls.AddImplicit (listbox_ctrl);
798 // if (dropdown_style == ComboBoxStyle.Simple)
799 // Height = combobox_info.combosimple_height;
803 if (textbox_ctrl != null) {
804 Controls.AddImplicit (textbox_ctrl);
810 protected override void OnHandleDestroyed (EventArgs e)
812 base.OnHandleDestroyed (e);
815 protected override void OnKeyPress (KeyPressEventArgs e)
820 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
822 if (MeasureItem != null)
823 MeasureItem (this, e);
826 protected override void OnParentBackColorChanged (EventArgs e)
828 base.OnParentBackColorChanged (e);
831 protected override void OnResize (EventArgs e)
834 AdjustHeightForDropDown ();
836 if (listbox_ctrl != null)
837 listbox_ctrl.CalcListBoxArea ();
842 protected override void OnSelectedIndexChanged (EventArgs e)
844 base.OnSelectedIndexChanged (e);
846 if (SelectedIndexChanged != null)
847 SelectedIndexChanged (this, e);
850 protected virtual void OnSelectedItemChanged (EventArgs e)
855 protected override void OnSelectedValueChanged (EventArgs e)
857 base.OnSelectedValueChanged (e);
860 protected virtual void OnSelectionChangeCommitted (EventArgs e)
862 if (SelectionChangeCommitted != null)
863 SelectionChangeCommitted (this, e);
866 protected override void RefreshItem (int index)
868 if (index < 0 || index >= Items.Count)
869 throw new ArgumentOutOfRangeException ("Index of out range");
871 if (draw_mode == DrawMode.OwnerDrawVariable) {
872 (Items.GetComboBoxItem (index)).ItemHeight = -1;
876 public void Select (int start, int lenght)
879 throw new ArgumentException ("Start cannot be less than zero");
882 throw new ArgumentException ("Start cannot be less than zero");
884 if (dropdown_style == ComboBoxStyle.DropDownList)
887 textbox_ctrl.Select (start, lenght);
890 public void SelectAll ()
892 if (dropdown_style == ComboBoxStyle.DropDownList)
895 textbox_ctrl.SelectAll ();
898 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
900 base.SetBoundsCore (x, y, width, height, specified);
903 protected override void SetItemCore (int index, object value)
905 if (index < 0 || index >= Items.Count)
908 Items[index] = value;
911 protected override void SetItemsCore (IList value)
913 Items.AddRange (value);
916 public override string ToString ()
918 return base.ToString () + ", Items.Count:" + Items.Count;
921 protected override void WndProc (ref Message m)
923 base.WndProc (ref m);
927 #endregion Public Methods
929 #region Private Methods
931 private void AdjustHeightForDropDown ()
933 if (dropdown_style == ComboBoxStyle.Simple)
936 int new_height = preferred_height;
938 if (Height == new_height)
944 private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e)
949 private void textbox_ctrl_GotFocus(object sender, EventArgs e )
954 private void textbox_ctrl_LostFocus(object sender, EventArgs e )
959 // Calcs the text area size
960 internal void CalcTextArea ()
962 combobox_info.textarea = ClientRectangle;
965 combobox_info.textarea.Height = ItemHeight + 2;
966 combobox_info.textarea_drawable = combobox_info.textarea;
968 RectangleF bounds = ClientRectangle;
969 combobox_info.listbox_area = new Rectangle ((int)bounds.X, (int)bounds.Y,
970 (int)bounds.Width, (int)bounds.Height);
972 if (CBoxInfo.show_button) {
973 combobox_info.textarea_drawable.Width -= def_button_width;
975 combobox_info.button_rect = new Rectangle (combobox_info.textarea_drawable.X + combobox_info.textarea_drawable.Width,
976 combobox_info.textarea_drawable.Y, def_button_width, combobox_info.textarea_drawable.Height - 2);
980 if (dropdown_style != ComboBoxStyle.DropDownList) { /* There is an edit control*/
981 if (textbox_ctrl != null) {
982 textbox_ctrl.Location = new Point (combobox_info.textarea_drawable.X, combobox_info.textarea_drawable.Y);
983 textbox_ctrl.Size = new Size (combobox_info.textarea_drawable.Width, combobox_info.textarea_drawable.Height);
987 if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
988 listbox_ctrl.Location = new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
989 combobox_info.textarea.Height);
990 listbox_ctrl.CalcListBoxArea ();
994 private void CreateComboListBox ()
996 listbox_ctrl = new ComboListBox (this);
999 internal void Draw (Rectangle clip, Graphics dc)
1001 // No edit control, we paint the edit ourselfs
1002 if (dropdown_style == ComboBoxStyle.DropDownList) {
1003 DrawItemState state = DrawItemState.None;
1004 Rectangle item_rect = combobox_info.textarea_drawable;
1005 item_rect.Height = ItemHeight + 2;
1007 if (has_focus == true) {
1008 state = DrawItemState.Selected;
1009 state |= DrawItemState.Focus;
1012 state |= DrawItemState.ComboBoxEdit;
1013 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect,
1014 selected_index, state, ForeColor, BackColor));
1017 if (DropDownStyle == ComboBoxStyle.Simple && clip.IntersectsWith (combobox_info.listbox_area) == true) {
1018 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
1019 combobox_info.listbox_area);
1022 if (CBoxInfo.show_button) {
1023 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl),
1024 combobox_info.button_rect);
1027 combobox_info.button_status = ButtonState.Inactive;
1029 ThemeEngine.Current.CPDrawComboButton (dc,
1030 combobox_info.button_rect, combobox_info.button_status);
1034 internal void DropDownListBox ()
1036 if (DropDownStyle == ComboBoxStyle.Simple)
1039 if (listbox_ctrl == null) {
1040 CreateComboListBox ();
1043 listbox_ctrl.Location = PointToScreen (new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
1044 combobox_info.textarea.Height));
1046 if (listbox_ctrl.ShowWindow () == true) {
1047 CBoxInfo.droppeddown = true;
1050 combobox_info.button_status = ButtonState.Pushed;
1051 if (dropdown_style == ComboBoxStyle.DropDownList) {
1052 Invalidate (combobox_info.textarea_drawable);
1056 internal void DropDownListBoxFinished ()
1058 if (DropDownStyle == ComboBoxStyle.Simple)
1061 combobox_info.button_status = ButtonState.Normal;
1062 Invalidate (combobox_info.button_rect);
1063 CBoxInfo.droppeddown = false;
1067 private int FindStringCaseInsensitive (string search)
1069 if (search.Length == 0) {
1073 for (int i = 0; i < Items.Count; i++)
1075 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1082 private void OnKeyDownCB(object sender, KeyEventArgs e)
1087 SelectedIndex = Math.Max(SelectedIndex-1, 0);
1091 SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1);
1095 if (listbox_ctrl != null)
1096 SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0);
1100 if (listbox_ctrl != null)
1101 SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1);
1109 internal virtual void OnMouseDownCB (object sender, MouseEventArgs e)
1111 /* Click On button*/
1114 if (dropdown_style == ComboBoxStyle.DropDownList) {
1115 hit_rect = combobox_info.textarea;
1117 hit_rect = combobox_info.button_rect;
1120 if (hit_rect.Contains (e.X, e.Y)) {
1121 if (clicked == false) {
1125 listbox_ctrl.Hide ();
1126 DropDownListBoxFinished ();
1129 Invalidate (combobox_info.button_rect);
1133 private void CalcPreferredHeight ()
1135 preferred_height = Font.Height;
1137 switch (border_style) {
1138 case BorderStyle.None:
1139 preferred_height += 3;
1141 case BorderStyle.FixedSingle:
1142 case BorderStyle.Fixed3D:
1143 preferred_height += 6;
1151 internal virtual void OnMouseMoveCB (object sender, MouseEventArgs e)
1153 /* When there are no items, act as a regular button */
1154 if (clicked == true && Items.Count == 0 &&
1155 combobox_info.button_rect.Contains (e.X, e.Y) == false) {
1156 DropDownListBoxFinished ();
1160 internal virtual void OnMouseUpCB (object sender, MouseEventArgs e)
1162 /* Click on button*/
1163 if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) {
1164 DropDownListBoxFinished ();
1168 internal override void OnPaintInternal (PaintEventArgs pevent)
1170 if (suspend_ctrlupdate)
1173 Draw (ClientRectangle, pevent.Graphics);
1176 private void OnTextChangedEdit (object sender, EventArgs e)
1178 if (process_textchanged_event == false)
1181 int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1186 if (listbox_ctrl != null) {
1187 listbox_ctrl.SetTopItem (item);
1188 listbox_ctrl.SetHighLightedItem (Items[item]);
1192 internal void SetControlText (string s)
1194 process_textchanged_event = false;
1195 textbox_ctrl.Text = s;
1196 process_textchanged_event = true;
1199 private void UpdatedItems ()
1201 if (listbox_ctrl != null) {
1202 listbox_ctrl.UpdateLastVisibleItem ();
1203 listbox_ctrl.CalcListBoxArea ();
1204 listbox_ctrl.Refresh ();
1208 #endregion Private Methods
1212 ComboBox.ObjectCollection
1214 [ListBindableAttribute (false)]
1215 public class ObjectCollection : IList, ICollection, IEnumerable
1218 private ComboBox owner;
1219 internal ArrayList object_items = new ArrayList ();
1220 internal ArrayList combobox_items = new ArrayList ();
1222 public ObjectCollection (ComboBox owner)
1227 #region Public Properties
1229 get { return object_items.Count; }
1232 public bool IsReadOnly {
1233 get { return false; }
1237 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1238 public virtual object this [int index] {
1240 if (index < 0 || index >= Count)
1241 throw new ArgumentOutOfRangeException ("Index of out range");
1243 return object_items[index];
1246 if (index < 0 || index >= Count)
1247 throw new ArgumentOutOfRangeException ("Index of out range");
1249 object_items[index] = value;
1253 bool ICollection.IsSynchronized {
1254 get { return false; }
1257 object ICollection.SyncRoot {
1258 get { return this; }
1261 bool IList.IsFixedSize {
1262 get { return false; }
1265 #endregion Public Properties
1267 #region Private Properties
1268 internal ArrayList ObjectItems {
1269 get { return object_items;}
1271 object_items = value;
1275 internal ArrayList ListBoxItems {
1276 get { return combobox_items;}
1278 combobox_items = value;
1281 #endregion Private Properties
1283 #region Public Methods
1284 public int Add (object item)
1288 idx = AddItem (item);
1289 owner.UpdatedItems ();
1293 public void AddRange (object[] items)
1295 foreach (object mi in items)
1298 owner.UpdatedItems ();
1301 public void Clear ()
1303 owner.selected_index = -1;
1304 object_items.Clear ();
1305 combobox_items.Clear ();
1306 owner.UpdatedItems ();
1310 public bool Contains (object obj)
1312 return object_items.Contains (obj);
1315 public void CopyTo (object[] dest, int arrayIndex)
1317 object_items.CopyTo (dest, arrayIndex);
1320 void ICollection.CopyTo (Array dest, int index)
1322 object_items.CopyTo (dest, index);
1325 public IEnumerator GetEnumerator ()
1327 return object_items.GetEnumerator ();
1330 int IList.Add (object item)
1335 public int IndexOf (object value)
1337 return object_items.IndexOf (value);
1340 public void Insert (int index, object item)
1342 if (index < 0 || index > Count)
1343 throw new ArgumentOutOfRangeException ("Index of out range");
1345 ObjectCollection new_items = new ObjectCollection (owner);
1346 object sel_item = owner.SelectedItem;
1348 owner.BeginUpdate ();
1350 for (int i = 0; i < index; i++) {
1351 new_items.AddItem (ObjectItems[i]);
1354 new_items.AddItem (item);
1356 for (int i = index; i < Count; i++){
1357 new_items.AddItem (ObjectItems[i]);
1360 ObjectItems = new_items.ObjectItems;
1361 ListBoxItems = new_items.ListBoxItems;
1363 if (sel_item != null) {
1364 int idx = IndexOf (sel_item);
1365 owner.selected_index = idx;
1366 owner.listbox_ctrl.SetHighLightedItem (owner.Items[idx]);
1369 owner.EndUpdate (); // Calls UpdatedItems
1372 public void Remove (object value)
1374 if (IndexOf (value) == owner.SelectedIndex)
1375 owner.SelectedItem = null;
1377 RemoveAt (IndexOf (value));
1381 public void RemoveAt (int index)
1383 if (index < 0 || index >= Count)
1384 throw new ArgumentOutOfRangeException ("Index of out range");
1386 if (index == owner.SelectedIndex)
1387 owner.SelectedItem = null;
1389 object_items.RemoveAt (index);
1390 combobox_items.RemoveAt (index);
1391 owner.UpdatedItems ();
1393 #endregion Public Methods
1395 #region Private Methods
1396 private int AddItem (object item)
1398 int cnt = object_items.Count;
1399 object_items.Add (item);
1400 combobox_items.Add (new ComboBox.ComboBoxItem (cnt));
1404 internal void AddRange (IList items)
1406 foreach (object mi in items)
1409 owner.UpdatedItems ();
1412 internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
1414 if (index < 0 || index >= Count)
1415 throw new ArgumentOutOfRangeException ("Index of out range");
1417 return (ComboBox.ComboBoxItem) combobox_items[index];
1420 internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
1422 if (index < 0 || index >= Count)
1423 throw new ArgumentOutOfRangeException ("Index of out range");
1425 combobox_items[index] = item;
1428 #endregion Private Methods
1434 internal class ComboListBox : Control
1436 private ComboBox owner;
1437 private VScrollBarLB vscrollbar_ctrl;
1438 private int top_item; /* First item that we show the in the current page */
1439 private int last_item; /* Last visible item */
1440 public object highlighted_item; /* Item that is currently selected */
1441 internal int page_size; /* Number of listbox items per page */
1442 private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
1444 internal enum ItemNavigation
1454 class VScrollBarLB : VScrollBar
1456 public VScrollBarLB ()
1460 public void FireMouseDown (MouseEventArgs e)
1465 public void FireMouseUp (MouseEventArgs e)
1470 public void FireMouseMove (MouseEventArgs e)
1477 public ComboListBox (ComboBox owner)
1483 highlighted_item = null;
1485 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1486 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1487 MouseMove += new MouseEventHandler (OnMouseMovePUW);
1488 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1489 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1490 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1492 border_style = BorderStyle.FixedSingle;
1495 protected override CreateParams CreateParams
1498 CreateParams cp = base.CreateParams;
1499 if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) {
1500 cp.Style ^= (int) WindowStyles.WS_CHILD;
1501 cp.Style |= (int) WindowStyles.WS_POPUP;
1502 cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST;
1508 #region Private Methods
1509 // Calcs the listbox area
1510 internal void CalcListBoxArea ()
1513 int item_height = owner.ItemHeight;
1514 bool show_scrollbar = false;
1516 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1517 width = owner.CBoxInfo.listbox_area.Width;
1518 height = owner.CBoxInfo.listbox_area.Height;
1520 if (owner.IntegralHeight == true) {
1521 int remaining = (height % (item_height - 2));
1523 if (remaining > 0) {
1524 height -= remaining;
1528 else { // DropDown or DropDownList
1530 width = owner.DropDownWidth;
1531 int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
1533 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1535 for (int i = 0; i < count; i++) {
1536 height += owner.GetItemHeight (i);
1540 height = (item_height - 2) * count;
1544 if (owner.Items.Count <= owner.MaxDropDownItems) {
1546 /* Does not need vertical scrollbar*/
1547 if (vscrollbar_ctrl != null) {
1548 vscrollbar_ctrl.Visible = false;
1552 /* Need vertical scrollbar */
1553 if (vscrollbar_ctrl == null) {
1554 vscrollbar_ctrl = new VScrollBarLB ();
1555 vscrollbar_ctrl.Minimum = 0;
1556 vscrollbar_ctrl.SmallChange = 1;
1557 vscrollbar_ctrl.LargeChange = 1;
1558 vscrollbar_ctrl.Maximum = 0;
1559 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1561 Controls.AddImplicit (vscrollbar_ctrl);
1564 vscrollbar_ctrl.Height = height;
1566 vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width , 0);
1568 vscrollbar_ctrl.Maximum = owner.Items.Count - (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items);
1569 show_scrollbar = vscrollbar_ctrl.Visible = true;
1571 int hli = GetHighLightedIndex ();
1573 hli = Math.Min (hli, vscrollbar_ctrl.Maximum);
1574 vscrollbar_ctrl.Value = hli;
1578 Size = new Size (width, height);
1579 textarea_drawable = ClientRectangle;
1580 textarea_drawable.Width = width;
1581 textarea_drawable.Height = height;
1583 if (vscrollbar_ctrl != null && show_scrollbar)
1584 textarea_drawable.Width -= vscrollbar_ctrl.Width;
1586 last_item = LastVisibleItem ();
1587 page_size = textarea_drawable.Height / (item_height - 2);
1590 private void Draw (Rectangle clip, Graphics dc)
1592 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
1593 (owner.BackColor), clip);
1595 if (owner.Items.Count > 0) {
1596 Rectangle item_rect;
1597 DrawItemState state = DrawItemState.None;
1599 for (int i = top_item; i <= last_item; i++) {
1600 item_rect = GetItemDisplayRectangle (i, top_item);
1602 if (clip.IntersectsWith (item_rect) == false)
1606 state = DrawItemState.None;
1608 if (i == GetHighLightedIndex () ) {
1609 state |= DrawItemState.Selected;
1611 if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1612 state |= DrawItemState.Focus;
1616 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1617 i, state, owner.ForeColor, owner.BackColor));
1622 public int GetHighLightedIndex ()
1624 return owner.Items.IndexOf (highlighted_item);
1627 public object GetHighLightedItem ()
1629 return highlighted_item;
1632 private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
1634 if (index < 0 || index >= owner.Items.Count)
1635 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1637 Rectangle item_rect = new Rectangle ();
1638 int height = owner.GetItemHeight (index);
1641 item_rect.Width = textarea_drawable.Width;
1642 item_rect.Y = ((height - 2) * (index - first_displayble));
1644 if (owner.dropdown_style == ComboBoxStyle.Simple)
1647 item_rect.Height = height;
1651 public void HideWindow ()
1653 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1658 highlighted_item = -1;
1659 owner.DropDownListBoxFinished ();
1662 private int IndexFromPointDisplayRectangle (int x, int y)
1664 for (int i = top_item; i <= last_item; i++) {
1665 if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1672 protected override bool IsInputKey (Keys keyData)
1674 return owner.IsInputKey (keyData);
1677 private int LastVisibleItem ()
1679 Rectangle item_rect;
1680 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1683 for (i = top_item; i < owner.Items.Count; i++) {
1684 item_rect = GetItemDisplayRectangle (i, top_item);
1685 if (item_rect.Y + item_rect.Height > top_y) {
1692 private void NavigateItemVisually (ItemNavigation navigation)
1696 switch (navigation) {
1697 case ItemNavigation.Next: {
1698 if (GetHighLightedIndex () + 1 < owner.Items.Count) {
1700 if (GetHighLightedIndex () + 1 > last_item) {
1702 vscrollbar_ctrl.Value = top_item;
1704 item = GetHighLightedIndex () + 1;
1709 case ItemNavigation.Previous: {
1710 if (GetHighLightedIndex () > 0) {
1712 if (GetHighLightedIndex () - 1 < top_item) {
1714 vscrollbar_ctrl.Value = top_item;
1716 item = GetHighLightedIndex () - 1;
1721 case ItemNavigation.NextPage: {
1722 if (GetHighLightedIndex () + page_size - 1 >= owner.Items.Count) {
1723 top_item = owner.Items.Count - page_size;
1724 vscrollbar_ctrl.Value = top_item;
1725 item = owner.Items.Count - 1;
1728 if (GetHighLightedIndex () + page_size - 1 > last_item) {
1729 top_item = GetHighLightedIndex ();
1730 vscrollbar_ctrl.Value = GetHighLightedIndex ();
1733 item = GetHighLightedIndex () + page_size - 1;
1738 case ItemNavigation.PreviousPage: {
1740 /* Go to the first item*/
1741 if (GetHighLightedIndex () - (page_size - 1) <= 0) {
1744 vscrollbar_ctrl.Value = top_item;
1747 else { /* One page back */
1748 if (GetHighLightedIndex () - (page_size - 1) < top_item) {
1749 top_item = GetHighLightedIndex () - (page_size - 1);
1750 vscrollbar_ctrl.Value = top_item;
1753 item = GetHighLightedIndex () - (page_size - 1);
1764 SetHighLightedItem (owner.Items[item]);
1766 owner.OnSelectionChangeCommitted (new EventArgs ());
1768 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1769 owner.SetControlText (owner.GetItemText (owner.Items[item]));
1774 private void OnKeyDownPUW (object sender, KeyEventArgs e)
1776 switch (e.KeyCode) {
1778 NavigateItemVisually (ItemNavigation.Previous);
1782 NavigateItemVisually (ItemNavigation.Next);
1786 NavigateItemVisually (ItemNavigation.PreviousPage);
1790 NavigateItemVisually (ItemNavigation.NextPage);
1798 public void SetHighLightedItem (object item)
1800 Rectangle invalidate = Rectangle.Empty;
1803 if (GetHighLightedItem () == item)
1807 hli = GetHighLightedIndex ();
1809 invalidate = GetItemDisplayRectangle (hli, top_item);
1812 highlighted_item = item;
1814 if (highlighted_item != null) {
1816 invalidate = Rectangle.Union (invalidate,
1817 GetItemDisplayRectangle (GetHighLightedIndex (), top_item));
1821 if (ClientRectangle.IntersectsWith (invalidate))
1822 Invalidate (invalidate);
1825 public void SetTopItem (int item)
1828 UpdateLastVisibleItem ();
1832 private void OnMouseDownPUW (object sender, MouseEventArgs e)
1834 Rectangle scrollbar_screenrect;
1835 Point mouse_screen, scrollbar_screen;
1836 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1838 /* Click on an element ? */
1839 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1841 owner.SelectedIndex = index;
1842 SetHighLightedItem (owner.Items[index]);
1843 owner.OnSelectionChangeCommitted (new EventArgs ());
1848 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1852 /* Reroute event to scrollbar */
1853 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1854 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1855 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1856 scrollbar_screenrect.X = scrollbar_screen.X;
1857 scrollbar_screenrect.Y = scrollbar_screen.Y;
1859 if (scrollbar_screenrect.Contains (mouse_screen)){
1860 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1861 vscrollbar_ctrl.FireMouseDown (new MouseEventArgs (e.Button, e.Clicks,
1862 pnt_client.X, pnt_client.Y, e.Delta));
1863 } else { /* Click in a non-client area*/
1866 } else { /* Click in a non-client area*/
1871 private void OnMouseMovePUW (object sender, MouseEventArgs e)
1873 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1876 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1879 SetHighLightedItem (owner.Items[index]);
1883 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1886 /* Reroute event to scrollbar */
1887 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1888 Rectangle scrollbar_screenrect;
1889 Point mouse_screen, scrollbar_screen;
1890 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1892 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1893 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1894 scrollbar_screenrect.X = scrollbar_screen.X;
1895 scrollbar_screenrect.Y = scrollbar_screen.Y;
1897 if (scrollbar_screenrect.Contains (mouse_screen)){
1898 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1900 vscrollbar_ctrl.FireMouseMove (new MouseEventArgs (e.Button, e.Clicks,
1901 pnt_client.X, pnt_client.Y, e.Delta));
1906 private void OnMouseUpPUW (object sender, MouseEventArgs e)
1908 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1911 /* Reroute event to scrollbar */
1912 Rectangle scrollbar_screenrect;
1913 Point mouse_screen, scrollbar_screen;
1914 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1916 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1917 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1918 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1919 scrollbar_screenrect.X = scrollbar_screen.X;
1920 scrollbar_screenrect.Y = scrollbar_screen.Y;
1922 if (scrollbar_screenrect.Contains (mouse_screen)){
1923 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1925 vscrollbar_ctrl.FireMouseUp (new MouseEventArgs (e.Button, e.Clicks,
1926 pnt_client.X, pnt_client.Y, e.Delta));
1931 internal override void OnPaintInternal (PaintEventArgs pevent)
1933 Draw (pevent.ClipRectangle,pevent.Graphics);
1936 public bool ShowWindow ()
1938 if (owner.DropDownStyle == ComboBoxStyle.Simple && owner.Items.Count == 0)
1941 SetHighLightedItem (owner.SelectedItem);
1946 if (owner.DropDownStyle != ComboBoxStyle.Simple) {
1952 if (owner.DropDown != null) {
1953 owner.DropDown (owner, EventArgs.Empty);
1959 public void UpdateLastVisibleItem ()
1961 last_item = LastVisibleItem ();
1965 private void VerticalScrollEvent (object sender, EventArgs e)
1967 if (top_item == vscrollbar_ctrl.Value)
1970 top_item = vscrollbar_ctrl.Value;
1971 UpdateLastVisibleItem ();
1975 #endregion Private Methods