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 const int preferred_height = 20;
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;
65 private bool has_focus;
68 public class ChildAccessibleObject : AccessibleObject {
69 private ComboBox owner;
70 private IntPtr handle;
72 public ChildAccessibleObject (ComboBox owner, IntPtr handle) {
77 public override string Name {
86 internal class ComboBoxInfo
88 internal int item_height; /* Item's height */
89 internal Rectangle textarea; /* Rectangle of the editable text area */
90 internal Rectangle textarea_drawable; /* Rectangle of the editable text area - decorations - button if present*/
91 internal Rectangle button_rect;
92 internal bool show_button; /* Is the DropDown button shown? */
93 internal ButtonState button_status; /* Drop button status */
94 internal int original_height; /* Control's height is recalculated for not Simple Styles */
95 internal Rectangle listbox_area; /* ListBox area in Simple combox, not used in the rest */
96 internal bool droppeddown; /* Is the associated ListBox dropped down? */
97 internal int combosimple_height; /* Simple default height */
99 public ComboBoxInfo ()
101 button_status = ButtonState.Normal;
105 original_height = -1;
106 combosimple_height = 150;
110 internal class ComboBoxItem
113 internal int ItemHeight; /* Only used for OwnerDrawVariable */
115 public ComboBoxItem (int index)
124 items = new ObjectCollection (this);
127 combobox_info = new ComboBoxInfo ();
128 combobox_info.item_height = FontHeight + 2;
129 dropdown_style = (ComboBoxStyle)(-1);
130 DropDownStyle = ComboBoxStyle.DropDown;
131 BackColor = ThemeEngine.Current.ColorWindow;
132 draw_mode = DrawMode.Normal;
134 selected_item = null;
136 suspend_ctrlupdate = false;
140 integral_height = true;
141 process_textchanged_event = true;
145 MouseDown += new MouseEventHandler (OnMouseDownCB);
146 MouseUp += new MouseEventHandler (OnMouseUpCB);
147 MouseMove += new MouseEventHandler (OnMouseMoveCB);
153 [EditorBrowsable (EditorBrowsableState.Never)]
154 public new event EventHandler BackgroundImageChanged;
156 public event DrawItemEventHandler DrawItem;
157 public event EventHandler DropDown;
158 public event EventHandler DropDownStyleChanged;
159 public event MeasureItemEventHandler MeasureItem;
162 [EditorBrowsable (EditorBrowsableState.Never)]
163 public new event PaintEventHandler Paint;
165 public event EventHandler SelectedIndexChanged;
166 public event EventHandler SelectionChangeCommitted;
169 #region Public Properties
170 public override Color BackColor {
171 get { return base.BackColor; }
173 if (base.BackColor == value)
176 base.BackColor = value;
182 [EditorBrowsable (EditorBrowsableState.Never)]
183 public override Image BackgroundImage {
184 get { return base.BackgroundImage; }
186 if (base.BackgroundImage == value)
189 base.BackgroundImage = value;
191 if (BackgroundImageChanged != null)
192 BackgroundImageChanged (this, EventArgs.Empty);
198 protected override CreateParams CreateParams {
199 get { return base.CreateParams;}
202 protected override Size DefaultSize {
203 get { return new Size (121, PreferredHeight); }
206 [RefreshProperties(RefreshProperties.Repaint)]
207 [DefaultValue (DrawMode.Normal)]
208 public DrawMode DrawMode {
209 get { return draw_mode; }
212 if (!Enum.IsDefined (typeof (DrawMode), value))
213 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
215 if (draw_mode == value)
223 [DefaultValue (ComboBoxStyle.DropDown)]
224 [RefreshProperties(RefreshProperties.Repaint)]
225 public ComboBoxStyle DropDownStyle {
226 get { return dropdown_style; }
230 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
231 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
233 if (dropdown_style == value)
236 if (dropdown_style == ComboBoxStyle.Simple) {
237 if (listbox_ctrl != null) {
238 Controls.RemoveImplicit (listbox_ctrl);
239 listbox_ctrl.Dispose ();
244 if (dropdown_style != ComboBoxStyle.DropDownList && value == ComboBoxStyle.DropDownList) {
245 if (textbox_ctrl != null) {
246 Controls.RemoveImplicit (textbox_ctrl);
247 textbox_ctrl.Dispose ();
252 dropdown_style = value;
254 if (dropdown_style == ComboBoxStyle.Simple) {
255 CBoxInfo.show_button = false;
256 Height = combobox_info.combosimple_height;
258 CreateComboListBox ();
260 if (IsHandleCreated == true) {
261 Controls.AddImplicit (listbox_ctrl);
265 CBoxInfo.show_button = true;
266 CBoxInfo.button_status = ButtonState.Normal;
269 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
270 textbox_ctrl = new TextBox ();
271 textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
272 textbox_ctrl.KeyPress += new KeyPressEventHandler(textbox_ctrl_KeyPress);
274 if (IsHandleCreated == true) {
275 Controls.AddImplicit (textbox_ctrl);
279 if (DropDownStyleChanged != null)
280 DropDownStyleChanged (this, EventArgs.Empty);
287 public int DropDownWidth {
289 if (dropdown_width == -1)
292 return dropdown_width;
295 if (dropdown_width == value)
299 throw new ArgumentException ("The DropDownWidth value is less than one");
301 dropdown_width = value;
306 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307 public bool DroppedDown {
309 if (dropdown_style == ComboBoxStyle.Simple)
312 return CBoxInfo.droppeddown;
315 if (dropdown_style == ComboBoxStyle.Simple)
323 listbox_ctrl.Hide ();
326 if (DropDown != null)
327 DropDown (this, EventArgs.Empty);
331 public override bool Focused {
332 get { return base.Focused; }
335 public override Color ForeColor {
336 get { return base.ForeColor; }
338 if (base.ForeColor == value)
341 base.ForeColor = value;
346 [DefaultValue (true)]
348 public bool IntegralHeight {
349 get { return integral_height; }
351 if (integral_height == value)
354 integral_height = value;
360 public virtual int ItemHeight {
361 get { return combobox_info.item_height; }
364 throw new ArgumentException ("The item height value is less than zero");
366 combobox_info.item_height = value;
372 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
374 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
375 public ComboBox.ObjectCollection Items {
376 get { return items; }
381 public int MaxDropDownItems {
382 get { return maxdrop_items; }
384 if (maxdrop_items == value)
387 maxdrop_items = value;
393 public int MaxLength {
394 get { return max_length; }
396 if (max_length == value)
401 if (dropdown_style != ComboBoxStyle.DropDownList) {
407 textbox_ctrl.MaxLength = value;
412 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
414 public int PreferredHeight {
415 get { return preferred_height; }
419 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
420 public override int SelectedIndex {
421 get { return selected_index; }
423 if (value <= -2 || value >= Items.Count)
424 throw new ArgumentOutOfRangeException ("Index of out range");
426 if (selected_index == value)
429 selected_index = value;
431 if (dropdown_style != ComboBoxStyle.DropDownList) {
432 SetControlText (GetItemText (Items[selected_index]));
435 OnSelectedIndexChanged (new EventArgs ());
436 OnSelectedValueChanged (new EventArgs ());
437 OnSelectedItemChanged (new EventArgs ());
443 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
445 public object SelectedItem {
447 if (selected_index !=-1 && Items !=null && Items.Count > 0)
448 return Items[selected_index];
453 int index = Items.IndexOf (value);
458 if (selected_index == index)
461 selected_index = index;
463 if (dropdown_style != ComboBoxStyle.DropDownList) {
464 SetControlText (GetItemText (Items[selected_index]));
467 OnSelectedItemChanged (new EventArgs ());
473 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
474 public string SelectedText {
476 if (dropdown_style == ComboBoxStyle.DropDownList)
479 return textbox_ctrl.SelectedText;
482 if (dropdown_style == ComboBoxStyle.DropDownList) {
486 textbox_ctrl.SelectedText = value;
491 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
492 public int SelectionLength {
494 if (dropdown_style == ComboBoxStyle.DropDownList)
497 return textbox_ctrl.SelectionLength;
500 if (dropdown_style == ComboBoxStyle.DropDownList)
503 if (textbox_ctrl.SelectionLength == value)
506 textbox_ctrl.SelectionLength = value;
511 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
512 public int SelectionStart {
514 if (dropdown_style == ComboBoxStyle.DropDownList)
517 return textbox_ctrl.SelectionStart;
520 if (dropdown_style == ComboBoxStyle.DropDownList)
523 if (textbox_ctrl.SelectionStart == value)
526 textbox_ctrl.SelectionStart = value;
530 [DefaultValue (false)]
532 get { return sorted; }
544 public override string Text {
546 if (dropdown_style != ComboBoxStyle.DropDownList) {
547 if (textbox_ctrl != null) {
548 return textbox_ctrl.Text;
552 if (SelectedItem != null) {
553 return GetItemText (SelectedItem);
564 int index = FindString (value);
567 SelectedIndex = index;
571 if (dropdown_style != ComboBoxStyle.DropDownList) {
572 textbox_ctrl.Text = GetItemText (value);
577 #endregion Public Properties
579 #region Private Properties
580 internal ComboBoxInfo CBoxInfo {
581 get { return combobox_info; }
584 #endregion Private Properties
586 #region Public Methods
587 protected virtual void AddItemsCore (object[] value)
592 public void BeginUpdate ()
594 suspend_ctrlupdate = true;
597 protected override void Dispose (bool disposing)
599 if (disposing == true) {
600 if (listbox_ctrl != null) {
601 listbox_ctrl.Dispose ();
602 Controls.RemoveImplicit (listbox_ctrl);
606 if (textbox_ctrl != null) {
607 Controls.RemoveImplicit (textbox_ctrl);
608 textbox_ctrl.Dispose ();
613 base.Dispose (disposing);
616 public void EndUpdate ()
618 suspend_ctrlupdate = false;
622 public int FindString (string s)
624 return FindString (s, -1);
627 public int FindString (string s, int startIndex)
629 if (Items.Count == 0)
630 return -1; // No exception throwing if empty
632 if (startIndex < -1 || startIndex >= Items.Count - 1)
633 throw new ArgumentOutOfRangeException ("Index of out range");
636 for (int i = startIndex; i < Items.Count; i++) {
637 if ((GetItemText (Items[i])).StartsWith (s))
644 public int FindStringExact (string s)
646 return FindStringExact (s, -1);
649 public int FindStringExact (string s, int startIndex)
651 if (Items.Count == 0)
652 return -1; // No exception throwing if empty
654 if (startIndex < -1 || startIndex >= Items.Count - 1)
655 throw new ArgumentOutOfRangeException ("Index of out range");
658 for (int i = startIndex; i < Items.Count; i++) {
659 if ((GetItemText (Items[i])).Equals (s))
666 public int GetItemHeight (int index)
668 if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {
670 if (index < 0 || index >= Items.Count )
671 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
673 if ((Items.GetComboBoxItem (index)).ItemHeight != -1) {
674 return (Items.GetComboBoxItem (index)).ItemHeight;
677 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
678 OnMeasureItem (args);
679 (Items.GetComboBoxItem (index)).ItemHeight = args.ItemHeight;
680 return args.ItemHeight;
686 protected override bool IsInputKey (Keys keyData)
700 protected override void OnBackColorChanged (EventArgs e)
702 base.OnBackColorChanged (e);
705 protected override void OnDataSourceChanged (EventArgs e)
707 base.OnDataSourceChanged (e);
708 BindDataItems (items);
710 if (DataSource == null || DataManager == null) {
714 SelectedIndex = DataManager.Position;
718 protected override void OnDisplayMemberChanged (EventArgs e)
720 base.OnDisplayMemberChanged (e);
722 if (DataManager == null || !IsHandleCreated)
725 BindDataItems (items);
726 SelectedIndex = DataManager.Position;
729 protected virtual void OnDrawItem (DrawItemEventArgs e)
731 if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) {
736 ThemeEngine.Current.DrawComboBoxItem (this, e);
739 protected virtual void OnDropDown (EventArgs e)
741 if (DropDown != null)
745 protected virtual void OnDropDownStyleChanged (EventArgs e)
747 if (DropDownStyleChanged != null)
748 DropDownStyleChanged (this, e);
751 protected override void OnFontChanged (EventArgs e)
753 base.OnFontChanged (e);
755 if (textbox_ctrl != null) {
756 textbox_ctrl.Font = Font;
759 combobox_info.item_height = FontHeight + 2;
763 protected override void OnForeColorChanged (EventArgs e)
765 base.OnForeColorChanged (e);
768 [EditorBrowsable(EditorBrowsableState.Advanced)]
769 protected override void OnGotFocus (EventArgs e) {
774 [EditorBrowsable(EditorBrowsableState.Advanced)]
775 protected override void OnLostFocus (EventArgs e) {
780 protected override void OnHandleCreated (EventArgs e)
782 base.OnHandleCreated (e);
784 if (listbox_ctrl != null) {
785 Controls.AddImplicit (listbox_ctrl);
786 Height = combobox_info.combosimple_height;
789 if (textbox_ctrl != null) {
790 Controls.AddImplicit (textbox_ctrl);
796 protected override void OnHandleDestroyed (EventArgs e)
798 base.OnHandleDestroyed (e);
801 protected override void OnKeyPress (KeyPressEventArgs e)
806 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
808 if (MeasureItem != null)
809 MeasureItem (this, e);
812 protected override void OnParentBackColorChanged (EventArgs e)
814 base.OnParentBackColorChanged (e);
817 protected override void OnResize (EventArgs e)
820 AdjustHeightForDropDown ();
824 protected override void OnSelectedIndexChanged (EventArgs e)
826 base.OnSelectedIndexChanged (e);
828 if (SelectedIndexChanged != null)
829 SelectedIndexChanged (this, e);
832 protected virtual void OnSelectedItemChanged (EventArgs e)
837 protected override void OnSelectedValueChanged (EventArgs e)
839 base.OnSelectedValueChanged (e);
842 protected virtual void OnSelectionChangeCommitted (EventArgs e)
844 if (SelectionChangeCommitted != null)
845 SelectionChangeCommitted (this, e);
848 protected override void RefreshItem (int index)
850 if (index < 0 || index >= Items.Count)
851 throw new ArgumentOutOfRangeException ("Index of out range");
853 if (draw_mode == DrawMode.OwnerDrawVariable) {
854 (Items.GetComboBoxItem (index)).ItemHeight = -1;
858 public void Select (int start, int lenght)
861 throw new ArgumentException ("Start cannot be less than zero");
864 throw new ArgumentException ("Start cannot be less than zero");
866 if (dropdown_style == ComboBoxStyle.DropDownList)
869 textbox_ctrl.Select (start, lenght);
872 public void SelectAll ()
874 if (dropdown_style == ComboBoxStyle.DropDownList)
877 textbox_ctrl.SelectAll ();
880 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
882 if ((specified & BoundsSpecified.Height) != 0)
883 combobox_info.combosimple_height = height;
885 base.SetBoundsCore (x, y, width, height, specified);
888 protected override void SetItemCore (int index, object value)
890 if (index < 0 || index >= Items.Count)
893 Items[index] = value;
896 protected override void SetItemsCore (IList value)
898 Items.AddRange (value);
901 public override string ToString ()
903 return base.ToString () + ", Items.Count:" + Items.Count;
906 protected override void WndProc (ref Message m)
909 switch ((Msg) m.Msg) {
912 PaintEventArgs paint_event;
913 paint_event = XplatUI.PaintEventStart (Handle, true);
914 OnPaintCB (paint_event);
915 XplatUI.PaintEventEnd (Handle, true);
919 case Msg.WM_ERASEBKGND:
920 m.Result = (IntPtr) 1;
927 base.WndProc (ref m);
931 #endregion Public Methods
933 #region Private Methods
935 private void AdjustHeightForDropDown ()
937 if (dropdown_style == ComboBoxStyle.Simple)
940 int new_height = combobox_info.item_height + ThemeEngine.Current.DrawComboBoxEditDecorationTop () +
941 ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2;
943 if (Height == new_height)
946 combobox_info.original_height = Height;
950 private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e)
955 // Calcs the text area size
956 internal void CalcTextArea ()
958 combobox_info.textarea = ClientRectangle;
961 combobox_info.textarea.Height = ItemHeight + ThemeEngine.Current.DrawComboBoxEditDecorationTop () +
962 ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2;
963 // TODO: Does the +2 change at different font resolutions?
965 /* Edit area - minus decorations (text drawable area) */
966 combobox_info.textarea_drawable = combobox_info.textarea;
967 combobox_info.textarea_drawable.Y += ThemeEngine.Current.DrawComboBoxEditDecorationTop ();
968 combobox_info.textarea_drawable.X += ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
969 combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationBottom ();
970 combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationTop();
971 combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationRight ();
972 combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
974 /* Non-drawable area */
975 Region area = new Region (ClientRectangle);
976 area.Exclude (combobox_info.textarea);
977 RectangleF bounds = area.GetBounds (DeviceContext);
978 combobox_info.listbox_area = new Rectangle ((int)bounds.X, (int)bounds.Y,
979 (int)bounds.Width, (int)bounds.Height);
981 if (CBoxInfo.show_button) {
982 combobox_info.textarea_drawable.Width -= def_button_width;
984 combobox_info.button_rect = new Rectangle (combobox_info.textarea_drawable.X + combobox_info.textarea_drawable.Width,
985 combobox_info.textarea_drawable.Y, def_button_width, combobox_info.textarea_drawable.Height);
989 if (dropdown_style != ComboBoxStyle.DropDownList) { /* There is an edit control*/
990 if (textbox_ctrl != null) {
991 textbox_ctrl.Location = new Point (combobox_info.textarea_drawable.X, combobox_info.textarea_drawable.Y);
992 textbox_ctrl.Size = new Size (combobox_info.textarea_drawable.Width, combobox_info.textarea_drawable.Height);
996 if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
997 listbox_ctrl.Location = new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
998 combobox_info.textarea.Height);
999 listbox_ctrl.CalcListBoxArea ();
1005 private void CreateComboListBox ()
1007 listbox_ctrl = new ComboListBox (this);
1010 internal void Draw (Rectangle clip, Graphics dc)
1012 // No edit control, we paint the edit ourselfs
1013 if (dropdown_style == ComboBoxStyle.DropDownList) {
1014 DrawItemState state = DrawItemState.None;
1015 Rectangle item_rect = combobox_info.textarea_drawable;
1016 item_rect.Height = ItemHeight + 2;
1018 if (has_focus == true) {
1019 state = DrawItemState.Selected;
1020 state |= DrawItemState.Focus;
1023 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect,
1024 selected_index, state, ForeColor, BackColor));
1027 if (DropDownStyle == ComboBoxStyle.Simple && clip.IntersectsWith (combobox_info.listbox_area) == true) {
1028 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
1029 combobox_info.listbox_area);
1032 if (CBoxInfo.show_button) {
1033 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl),
1034 combobox_info.button_rect);
1036 ThemeEngine.Current.CPDrawComboButton (dc,
1037 combobox_info.button_rect, combobox_info.button_status);
1040 ThemeEngine.Current.DrawComboBoxEditDecorations (dc, this, combobox_info.textarea);
1043 internal void DropDownListBox ()
1045 if (DropDownStyle == ComboBoxStyle.Simple)
1048 if (listbox_ctrl == null) {
1049 CreateComboListBox ();
1052 listbox_ctrl.Location = PointToScreen (new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
1053 combobox_info.textarea.Height));
1055 if (listbox_ctrl.ShowWindow () == true) {
1056 CBoxInfo.droppeddown = true;
1059 combobox_info.button_status = ButtonState.Pushed;
1060 if (dropdown_style == ComboBoxStyle.DropDownList) {
1061 Invalidate (combobox_info.textarea_drawable);
1065 internal void DropDownListBoxFinished ()
1067 if (DropDownStyle == ComboBoxStyle.Simple)
1070 combobox_info.button_status = ButtonState.Normal;
1071 Invalidate (combobox_info.button_rect);
1072 CBoxInfo.droppeddown = false;
1076 private int FindStringCaseInsensitive (string search)
1078 for (int i = 0; i < Items.Count; i++)
1080 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1087 internal virtual void OnMouseDownCB (object sender, MouseEventArgs e)
1089 /* Click On button*/
1092 if (dropdown_style == ComboBoxStyle.DropDownList) {
1093 hit_rect = combobox_info.textarea;
1095 hit_rect = combobox_info.button_rect;
1098 if (hit_rect.Contains (e.X, e.Y)) {
1099 if (clicked == false) {
1103 listbox_ctrl.Hide ();
1104 DropDownListBoxFinished ();
1107 Invalidate (combobox_info.button_rect);
1111 internal virtual void OnMouseMoveCB (object sender, MouseEventArgs e)
1113 /* When there are no items, act as a regular button */
1114 if (clicked == true && Items.Count == 0 &&
1115 combobox_info.button_rect.Contains (e.X, e.Y) == false) {
1116 DropDownListBoxFinished ();
1120 internal virtual void OnMouseUpCB (object sender, MouseEventArgs e)
1122 /* Click on button*/
1123 if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) {
1124 DropDownListBoxFinished ();
1128 private void OnPaintCB (PaintEventArgs pevent)
1130 if (Width <= 0 || Height <= 0 || Visible == false || suspend_ctrlupdate == true)
1133 /* Copies memory drawing buffer to screen*/
1134 Draw (ClientRectangle, pevent.Graphics);
1137 Paint (this, pevent);
1140 private void OnTextChangedEdit (object sender, EventArgs e)
1142 if (process_textchanged_event == false)
1145 int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1150 listbox_ctrl.SetTopItem (item);
1151 listbox_ctrl.SetHighLightedItem (Items[item]);
1154 internal void SetControlText (string s)
1156 process_textchanged_event = false;
1157 textbox_ctrl.Text = s;
1158 process_textchanged_event = true;
1161 private void UpdatedItems ()
1163 if (dropdown_style != ComboBoxStyle.Simple)
1166 listbox_ctrl.UpdateLastVisibleItem ();
1167 listbox_ctrl.CalcListBoxArea ();
1168 listbox_ctrl.Refresh ();
1171 #endregion Private Methods
1175 ComboBox.ObjectCollection
1177 [ListBindableAttribute (false)]
1178 public class ObjectCollection : IList, ICollection, IEnumerable
1181 private ComboBox owner;
1182 internal ArrayList object_items = new ArrayList ();
1183 internal ArrayList combobox_items = new ArrayList ();
1185 public ObjectCollection (ComboBox owner)
1190 #region Public Properties
1191 public virtual int Count {
1192 get { return object_items.Count; }
1195 public virtual bool IsReadOnly {
1196 get { return false; }
1200 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1201 public virtual object this [int index] {
1203 if (index < 0 || index >= Count)
1204 throw new ArgumentOutOfRangeException ("Index of out range");
1206 return object_items[index];
1209 if (index < 0 || index >= Count)
1210 throw new ArgumentOutOfRangeException ("Index of out range");
1212 object_items[index] = value;
1216 bool ICollection.IsSynchronized {
1217 get { return false; }
1220 object ICollection.SyncRoot {
1221 get { return this; }
1224 bool IList.IsFixedSize {
1225 get { return false; }
1228 #endregion Public Properties
1230 #region Private Properties
1231 internal ArrayList ObjectItems {
1232 get { return object_items;}
1234 object_items = value;
1238 internal ArrayList ListBoxItems {
1239 get { return combobox_items;}
1241 combobox_items = value;
1244 #endregion Private Properties
1246 #region Public Methods
1247 public int Add (object item)
1251 idx = AddItem (item);
1252 owner.UpdatedItems ();
1256 public void AddRange (object[] items)
1258 foreach (object mi in items)
1261 owner.UpdatedItems ();
1264 public virtual void Clear ()
1266 owner.selected_index = -1;
1267 object_items.Clear ();
1268 combobox_items.Clear ();
1269 owner.UpdatedItems ();
1273 public virtual bool Contains (object obj)
1275 return object_items.Contains (obj);
1278 public void CopyTo (object[] dest, int arrayIndex)
1280 object_items.CopyTo (dest, arrayIndex);
1283 void ICollection.CopyTo (Array dest, int index)
1285 object_items.CopyTo (dest, index);
1288 public virtual IEnumerator GetEnumerator ()
1290 return object_items.GetEnumerator ();
1293 int IList.Add (object item)
1298 public virtual int IndexOf (object value)
1300 return object_items.IndexOf (value);
1303 public virtual void Insert (int index, object item)
1305 if (index < 0 || index > Count)
1306 throw new ArgumentOutOfRangeException ("Index of out range");
1308 ObjectCollection new_items = new ObjectCollection (owner);
1309 object sel_item = owner.SelectedItem;
1311 owner.BeginUpdate ();
1313 for (int i = 0; i < index; i++) {
1314 new_items.AddItem (ObjectItems[i]);
1317 new_items.AddItem (item);
1319 for (int i = index; i < Count; i++){
1320 new_items.AddItem (ObjectItems[i]);
1323 ObjectItems = new_items.ObjectItems;
1324 ListBoxItems = new_items.ListBoxItems;
1326 if (sel_item != null) {
1327 int idx = IndexOf (sel_item);
1328 owner.selected_index = idx;
1329 owner.listbox_ctrl.SetHighLightedItem (owner.Items[idx]);
1332 owner.EndUpdate (); // Calls UpdatedItems
1335 public virtual void Remove (object value)
1337 if (IndexOf (value) == owner.SelectedIndex)
1338 owner.SelectedItem = null;
1340 RemoveAt (IndexOf (value));
1344 public virtual void RemoveAt (int index)
1346 if (index < 0 || index >= Count)
1347 throw new ArgumentOutOfRangeException ("Index of out range");
1349 if (index == owner.SelectedIndex)
1350 owner.SelectedItem = null;
1352 object_items.RemoveAt (index);
1353 combobox_items.RemoveAt (index);
1354 owner.UpdatedItems ();
1356 #endregion Public Methods
1358 #region Private Methods
1359 private int AddItem (object item)
1361 int cnt = object_items.Count;
1362 object_items.Add (item);
1363 combobox_items.Add (new ComboBox.ComboBoxItem (cnt));
1367 internal void AddRange (IList items)
1369 foreach (object mi in items)
1372 owner.UpdatedItems ();
1375 internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
1377 if (index < 0 || index >= Count)
1378 throw new ArgumentOutOfRangeException ("Index of out range");
1380 return (ComboBox.ComboBoxItem) combobox_items[index];
1383 internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
1385 if (index < 0 || index >= Count)
1386 throw new ArgumentOutOfRangeException ("Index of out range");
1388 combobox_items[index] = item;
1391 #endregion Private Methods
1397 internal class ComboListBox : Control
1399 private ComboBox owner;
1400 private VScrollBarLB vscrollbar_ctrl;
1401 private int top_item; /* First item that we show the in the current page */
1402 private int last_item; /* Last visible item */
1403 public object highlighted_item; /* Item that is currently selected */
1404 internal int page_size; /* Number of listbox items per page */
1405 private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
1407 internal enum ItemNavigation
1417 class VScrollBarLB : VScrollBar
1419 public VScrollBarLB ()
1423 public void FireMouseDown (MouseEventArgs e)
1428 public void FireMouseUp (MouseEventArgs e)
1433 public void FireMouseMove (MouseEventArgs e)
1440 public ComboListBox (ComboBox owner) : base ()
1446 highlighted_item = null;
1448 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1449 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1450 MouseMove += new MouseEventHandler (OnMouseMovePUW);
1451 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1452 Paint += new PaintEventHandler (OnPaintPUW);
1453 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1454 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1457 protected override CreateParams CreateParams
1460 CreateParams cp = base.CreateParams;
1461 if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) {
1462 cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
1463 cp.ExStyle |= (int)(WindowStyles.WS_EX_TOOLWINDOW | WindowStyles.WS_EX_TOPMOST);
1469 #region Private Methods
1470 // Calcs the listbox area
1471 internal void CalcListBoxArea ()
1474 int item_height = owner.ItemHeight;
1475 bool show_scrollbar = false;
1477 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1478 width = owner.CBoxInfo.listbox_area.Width;
1479 height = owner.CBoxInfo.listbox_area.Height;
1481 if (owner.IntegralHeight == true) {
1482 int remaining = (height -
1483 ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1484 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)) %
1487 if (remaining > 0) {
1488 height -= remaining;
1492 else { // DropDown or DropDownList
1494 width = owner.DropDownWidth;
1495 int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
1497 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1499 for (int i = 0; i < count; i++) {
1500 height += owner.GetItemHeight (i);
1504 height = (item_height - 2) * count;
1508 height += ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);
1509 height += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1512 if (owner.Items.Count <= owner.MaxDropDownItems) {
1514 /* Does not need vertical scrollbar*/
1515 if (vscrollbar_ctrl != null) {
1516 vscrollbar_ctrl.Visible = false;
1520 /* Need vertical scrollbar */
1521 if (vscrollbar_ctrl == null) {
1522 vscrollbar_ctrl = new VScrollBarLB ();
1523 vscrollbar_ctrl.Minimum = 0;
1524 vscrollbar_ctrl.SmallChange = 1;
1525 vscrollbar_ctrl.LargeChange = 1;
1526 vscrollbar_ctrl.Maximum = 0;
1527 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1529 Controls.AddImplicit (vscrollbar_ctrl);
1532 vscrollbar_ctrl.Height = height - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1533 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1535 vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle),
1536 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle));
1538 vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems;
1539 show_scrollbar = vscrollbar_ctrl.Visible = true;
1543 Size = new Size (width, height);
1544 textarea_drawable = ClientRectangle;
1545 textarea_drawable.Width = width;
1546 textarea_drawable.Height = height;
1548 // Exclude decorations
1549 textarea_drawable.X += ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1550 textarea_drawable.Y += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1551 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1552 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1553 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);
1554 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1556 if (vscrollbar_ctrl != null && show_scrollbar)
1557 textarea_drawable.Width -= vscrollbar_ctrl.Width;
1559 last_item = LastVisibleItem ();
1560 page_size = textarea_drawable.Height / (item_height - 2);
1563 private void Draw (Rectangle clip, Graphics dc)
1565 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
1566 (owner.BackColor), clip);
1568 if (owner.Items.Count > 0) {
1569 Rectangle item_rect;
1570 DrawItemState state = DrawItemState.None;
1572 for (int i = top_item; i <= last_item; i++) {
1573 item_rect = GetItemDisplayRectangle (i, top_item);
1575 if (clip.IntersectsWith (item_rect) == false)
1579 state = DrawItemState.None;
1581 if (i == GetHighLightedIndex () ) {
1582 state |= DrawItemState.Selected;
1584 if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1585 state |= DrawItemState.Focus;
1589 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1590 i, state, owner.ForeColor, owner.BackColor));
1594 ThemeEngine.Current.DrawComboListBoxDecorations (dc, owner, ClientRectangle);
1597 public int GetHighLightedIndex ()
1599 return owner.Items.IndexOf (highlighted_item);
1602 public object GetHighLightedItem ()
1604 return highlighted_item;
1607 private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
1609 if (index < 0 || index >= owner.Items.Count)
1610 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1612 Rectangle item_rect = new Rectangle ();
1613 int height = owner.GetItemHeight (index);
1615 item_rect.X = ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1616 item_rect.Width = textarea_drawable.Width;
1617 item_rect.Y = ((height - 2) * (index - first_displayble));
1619 if (owner.dropdown_style == ComboBoxStyle.Simple)
1622 item_rect.Height = height;
1626 public void HideWindow ()
1628 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1633 highlighted_item = -1;
1634 owner.DropDownListBoxFinished ();
1637 private int IndexFromPointDisplayRectangle (int x, int y)
1639 for (int i = top_item; i <= last_item; i++) {
1640 if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1647 protected override bool IsInputKey (Keys keyData)
1649 return owner.IsInputKey (keyData);
1652 private int LastVisibleItem ()
1654 Rectangle item_rect;
1655 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1658 for (i = top_item; i < owner.Items.Count; i++) {
1659 item_rect = GetItemDisplayRectangle (i, top_item);
1660 if (item_rect.Y + item_rect.Height > top_y) {
1667 private void NavigateItemVisually (ItemNavigation navigation)
1671 switch (navigation) {
1672 case ItemNavigation.Next: {
1673 if (GetHighLightedIndex () + 1 < owner.Items.Count) {
1675 if (GetHighLightedIndex () + 1 > last_item) {
1677 vscrollbar_ctrl.Value = top_item;
1679 item = GetHighLightedIndex () + 1;
1684 case ItemNavigation.Previous: {
1685 if (GetHighLightedIndex () > 0) {
1687 if (GetHighLightedIndex () - 1 < top_item) {
1689 vscrollbar_ctrl.Value = top_item;
1691 item = GetHighLightedIndex () - 1;
1696 case ItemNavigation.NextPage: {
1697 if (GetHighLightedIndex () + page_size - 1 >= owner.Items.Count) {
1698 top_item = owner.Items.Count - page_size;
1699 vscrollbar_ctrl.Value = top_item;
1700 item = owner.Items.Count - 1;
1703 if (GetHighLightedIndex () + page_size - 1 > last_item) {
1704 top_item = GetHighLightedIndex ();
1705 vscrollbar_ctrl.Value = GetHighLightedIndex ();
1708 item = GetHighLightedIndex () + page_size - 1;
1713 case ItemNavigation.PreviousPage: {
1715 /* Go to the first item*/
1716 if (GetHighLightedIndex () - (page_size - 1) <= 0) {
1719 vscrollbar_ctrl.Value = top_item;
1722 else { /* One page back */
1723 if (GetHighLightedIndex () - (page_size - 1) < top_item) {
1724 top_item = GetHighLightedIndex () - (page_size - 1);
1725 vscrollbar_ctrl.Value = top_item;
1728 item = GetHighLightedIndex () - (page_size - 1);
1739 SetHighLightedItem (owner.Items[item]);
1741 owner.OnSelectionChangeCommitted (new EventArgs ());
1743 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1744 owner.SetControlText (owner.GetItemText (owner.Items[item]));
1749 private void OnKeyDownPUW (object sender, KeyEventArgs e)
1751 switch (e.KeyCode) {
1753 NavigateItemVisually (ItemNavigation.Previous);
1757 NavigateItemVisually (ItemNavigation.Next);
1761 NavigateItemVisually (ItemNavigation.PreviousPage);
1765 NavigateItemVisually (ItemNavigation.NextPage);
1773 public void SetHighLightedItem (object item)
1775 Rectangle invalidate;
1777 if (GetHighLightedItem () == item)
1781 if (GetHighLightedIndex () != -1) {
1782 invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item);
1783 if (ClientRectangle.Contains (invalidate))
1784 Invalidate (invalidate);
1787 highlighted_item = item;
1789 if (highlighted_item != null) {
1791 invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item);
1792 if (ClientRectangle.Contains (invalidate))
1793 Invalidate (invalidate);
1798 public void SetTopItem (int item)
1801 UpdateLastVisibleItem ();
1805 private void OnMouseDownPUW (object sender, MouseEventArgs e)
1807 Rectangle scrollbar_screenrect;
1808 Point mouse_screen, scrollbar_screen;
1809 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1811 /* Click on an element ? */
1812 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1814 owner.SelectedIndex = index;
1815 SetHighLightedItem (owner.Items[index]);
1816 owner.OnSelectionChangeCommitted (new EventArgs ());
1821 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1824 /* Reroute event to scrollbar */
1825 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1826 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1827 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1828 scrollbar_screenrect.X = scrollbar_screen.X;
1829 scrollbar_screenrect.Y = scrollbar_screen.Y;
1831 if (scrollbar_screenrect.Contains (mouse_screen)){
1832 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1833 vscrollbar_ctrl.FireMouseDown (new MouseEventArgs (e.Button, e.Clicks,
1834 pnt_client.X, pnt_client.Y, e.Delta));
1835 } else { /* Click in a non-client area*/
1838 } else { /* Click in a non-client area*/
1843 private void OnMouseMovePUW (object sender, MouseEventArgs e)
1845 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1848 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1851 SetHighLightedItem (owner.Items[index]);
1855 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1858 /* Reroute event to scrollbar */
1859 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1860 Rectangle scrollbar_screenrect;
1861 Point mouse_screen, scrollbar_screen;
1862 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1864 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1865 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1866 scrollbar_screenrect.X = scrollbar_screen.X;
1867 scrollbar_screenrect.Y = scrollbar_screen.Y;
1869 if (scrollbar_screenrect.Contains (mouse_screen)){
1870 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1872 vscrollbar_ctrl.FireMouseMove (new MouseEventArgs (e.Button, e.Clicks,
1873 pnt_client.X, pnt_client.Y, e.Delta));
1878 private void OnMouseUpPUW (object sender, MouseEventArgs e)
1880 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1883 /* Reroute event to scrollbar */
1884 Rectangle scrollbar_screenrect;
1885 Point mouse_screen, scrollbar_screen;
1886 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1888 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1889 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1890 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1891 scrollbar_screenrect.X = scrollbar_screen.X;
1892 scrollbar_screenrect.Y = scrollbar_screen.Y;
1894 if (scrollbar_screenrect.Contains (mouse_screen)){
1895 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1897 vscrollbar_ctrl.FireMouseUp (new MouseEventArgs (e.Button, e.Clicks,
1898 pnt_client.X, pnt_client.Y, e.Delta));
1903 private void OnPaintPUW (Object o, PaintEventArgs pevent)
1905 Draw (pevent.ClipRectangle,pevent.Graphics);
1908 public bool ShowWindow ()
1910 if (owner.DropDownStyle != ComboBoxStyle.Simple && owner.Items.Count == 0)
1914 SetHighLightedItem (owner.SelectedItem);
1919 if (owner.DropDownStyle != ComboBoxStyle.Simple) {
1925 if (owner.DropDown != null) {
1926 owner.DropDown (owner, EventArgs.Empty);
1932 public void UpdateLastVisibleItem ()
1934 last_item = LastVisibleItem ();
1938 private void VerticalScrollEvent (object sender, EventArgs e)
1940 top_item = vscrollbar_ctrl.Value;
1941 UpdateLastVisibleItem ();
1945 #endregion Private Methods