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 {
\r
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? */
98 public ComboBoxInfo ()
100 button_status = ButtonState.Normal;
104 original_height = -1;
108 internal class ComboBoxItem
111 internal int ItemHeight; /* Only used for OwnerDrawVariable */
113 public ComboBoxItem (int index)
122 items = new ObjectCollection (this);
125 combobox_info = new ComboBoxInfo ();
126 combobox_info.item_height = FontHeight + 2;
127 dropdown_style = (ComboBoxStyle)(-1);
128 DropDownStyle = ComboBoxStyle.DropDown;
129 BackColor = ThemeEngine.Current.ColorWindow;
130 draw_mode = DrawMode.Normal;
132 selected_item = null;
134 suspend_ctrlupdate = false;
138 integral_height = true;
139 process_textchanged_event = true;
143 MouseDown += new MouseEventHandler (OnMouseDownCB);
144 MouseUp += new MouseEventHandler (OnMouseUpCB);
145 MouseMove += new MouseEventHandler (OnMouseMoveCB);
151 [EditorBrowsable (EditorBrowsableState.Never)]
152 public new event EventHandler BackgroundImageChanged;
154 public event DrawItemEventHandler DrawItem;
155 public event EventHandler DropDown;
156 public event EventHandler DropDownStyleChanged;
157 public event MeasureItemEventHandler MeasureItem;
160 [EditorBrowsable (EditorBrowsableState.Never)]
161 public new event PaintEventHandler Paint;
163 public event EventHandler SelectedIndexChanged;
164 public event EventHandler SelectionChangeCommitted;
167 #region Public Properties
168 public override Color BackColor {
169 get { return base.BackColor; }
171 if (base.BackColor == value)
174 base.BackColor = value;
180 [EditorBrowsable (EditorBrowsableState.Never)]
181 public override Image BackgroundImage {
182 get { return base.BackgroundImage; }
184 if (base.BackgroundImage == value)
187 base.BackgroundImage = value;
189 if (BackgroundImageChanged != null)
190 BackgroundImageChanged (this, EventArgs.Empty);
196 protected override CreateParams CreateParams {
197 get { return base.CreateParams;}
200 protected override Size DefaultSize {
201 get { return new Size (121, PreferredHeight); }
204 [RefreshProperties(RefreshProperties.Repaint)]
205 [DefaultValue (DrawMode.Normal)]
206 public DrawMode DrawMode {
207 get { return draw_mode; }
210 if (!Enum.IsDefined (typeof (DrawMode), value))
211 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
213 if (draw_mode == value)
221 [DefaultValue (ComboBoxStyle.DropDown)]
222 [RefreshProperties(RefreshProperties.Repaint)]
223 public ComboBoxStyle DropDownStyle {
224 get { return dropdown_style; }
228 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
229 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
231 if (dropdown_style == value)
234 if (dropdown_style == ComboBoxStyle.Simple) {
235 if (listbox_ctrl != null) {
236 Controls.Remove (listbox_ctrl);
237 listbox_ctrl.Dispose ();
242 if (dropdown_style != ComboBoxStyle.DropDownList && value == ComboBoxStyle.DropDownList) {
243 if (textbox_ctrl != null) {
244 Controls.Remove (textbox_ctrl);
245 textbox_ctrl.Dispose ();
250 dropdown_style = value;
252 if (dropdown_style == ComboBoxStyle.Simple) {
253 CBoxInfo.show_button = false;
255 if (combobox_info.original_height != -1)
256 Height = combobox_info.original_height;
258 CreateComboListBox ();
260 if (IsHandleCreated == true) {
261 Controls.Add (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.Add (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 ArgumentOutOfRangeException ("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.Remove (listbox_ctrl);
606 if (textbox_ctrl != null) {
607 Controls.Remove (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, 0);
627 public int FindString (string s, int startIndex)
629 for (int i = startIndex; i < Items.Count; i++) {
630 if ((GetItemText (Items[i])).StartsWith (s))
637 public int FindStringExact (string s)
639 return FindStringExact (s, 0);
642 public int FindStringExact (string s, int startIndex)
644 for (int i = startIndex; i < Items.Count; i++) {
645 if ((GetItemText (Items[i])).Equals (s))
652 public int GetItemHeight (int index)
654 if (index < 0 || index >= Items.Count )
655 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
657 if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {
659 if ((Items.GetComboBoxItem (index)).ItemHeight != -1) {
660 return (Items.GetComboBoxItem (index)).ItemHeight;
663 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
664 OnMeasureItem (args);
665 (Items.GetComboBoxItem (index)).ItemHeight = args.ItemHeight;
666 return args.ItemHeight;
672 protected override bool IsInputKey (Keys keyData)
686 protected override void OnBackColorChanged (EventArgs e)
688 base.OnBackColorChanged (e);
691 protected override void OnDataSourceChanged (EventArgs e)
693 base.OnDataSourceChanged (e);
694 BindDataItems (items);
696 if (DataSource == null || DataManager == null) {
700 SelectedIndex = DataManager.Position;
704 protected override void OnDisplayMemberChanged (EventArgs e)
706 base.OnDisplayMemberChanged (e);
708 if (DataManager == null || !IsHandleCreated)
711 BindDataItems (items);
712 SelectedIndex = DataManager.Position;
715 protected virtual void OnDrawItem (DrawItemEventArgs e)
717 if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) {
722 ThemeEngine.Current.DrawComboBoxItem (this, e);
725 protected virtual void OnDropDown (EventArgs e)
727 if (DropDown != null)
731 protected virtual void OnDropDownStyleChanged (EventArgs e)
733 if (DropDownStyleChanged != null)
734 DropDownStyleChanged (this, e);
737 protected override void OnFontChanged (EventArgs e)
739 base.OnFontChanged (e);
741 if (textbox_ctrl != null) {
742 textbox_ctrl.Font = Font;
745 combobox_info.item_height = FontHeight + 2;
749 protected override void OnForeColorChanged (EventArgs e)
751 base.OnForeColorChanged (e);
754 [EditorBrowsable(EditorBrowsableState.Advanced)]
755 protected override void OnGotFocus (EventArgs e) {
760 [EditorBrowsable(EditorBrowsableState.Advanced)]
761 protected override void OnLostFocus (EventArgs e) {
766 protected override void OnHandleCreated (EventArgs e)
768 base.OnHandleCreated (e);
770 if (listbox_ctrl != null) {
771 Controls.Add (listbox_ctrl);
774 if (textbox_ctrl != null) {
775 Controls.Add (textbox_ctrl);
781 protected override void OnHandleDestroyed (EventArgs e)
783 base.OnHandleDestroyed (e);
786 protected override void OnKeyPress (KeyPressEventArgs e)
791 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
793 if (MeasureItem != null)
794 MeasureItem (this, e);
797 protected override void OnParentBackColorChanged (EventArgs e)
799 base.OnParentBackColorChanged (e);
802 protected override void OnResize (EventArgs e)
805 AdjustHeightForDropDown ();
809 protected override void OnSelectedIndexChanged (EventArgs e)
811 base.OnSelectedIndexChanged (e);
813 if (SelectedIndexChanged != null)
814 SelectedIndexChanged (this, e);
817 protected virtual void OnSelectedItemChanged (EventArgs e)
822 protected override void OnSelectedValueChanged (EventArgs e)
824 base.OnSelectedValueChanged (e);
827 protected virtual void OnSelectionChangeCommitted (EventArgs e)
829 if (SelectionChangeCommitted != null)
830 SelectionChangeCommitted (this, e);
833 protected override void RefreshItem (int index)
835 if (index < 0 || index >= Items.Count)
836 throw new ArgumentOutOfRangeException ("Index of out range");
838 if (draw_mode == DrawMode.OwnerDrawVariable) {
839 (Items.GetComboBoxItem (index)).ItemHeight = -1;
843 public void Select (int start, int lenght)
846 throw new ArgumentException ("Start cannot be less than zero");
849 throw new ArgumentException ("Start cannot be less than zero");
851 if (dropdown_style == ComboBoxStyle.DropDownList)
854 textbox_ctrl.Select (start, lenght);
857 public void SelectAll ()
859 if (dropdown_style == ComboBoxStyle.DropDownList)
862 textbox_ctrl.SelectAll ();
865 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
867 base.SetBoundsCore (x, y, width, height, specified);
870 protected override void SetItemCore (int index, object value)
872 if (index < 0 || index >= Items.Count)
875 Items[index] = value;
878 protected override void SetItemsCore (IList value)
880 Items.AddRange (value);
883 public override string ToString ()
885 return base.ToString () + ", Items.Count:" + Items.Count;
888 protected override void WndProc (ref Message m)
891 switch ((Msg) m.Msg) {
894 PaintEventArgs paint_event;
895 paint_event = XplatUI.PaintEventStart (Handle);
896 OnPaintCB (paint_event);
897 XplatUI.PaintEventEnd (Handle);
901 case Msg.WM_ERASEBKGND:
902 m.Result = (IntPtr) 1;
909 base.WndProc (ref m);
913 #endregion Public Methods
915 #region Private Methods
917 private void AdjustHeightForDropDown ()
919 if (dropdown_style == ComboBoxStyle.Simple)
922 int new_height = combobox_info.item_height + ThemeEngine.Current.DrawComboBoxEditDecorationTop () +
923 ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2;
925 if (Height == new_height)
928 combobox_info.original_height = Height;
932 private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e)
937 // Calcs the text area size
938 internal void CalcTextArea ()
940 combobox_info.textarea = ClientRectangle;
943 combobox_info.textarea.Height = ItemHeight + ThemeEngine.Current.DrawComboBoxEditDecorationTop () +
944 ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2;
945 // TODO: Does the +2 change at different font resolutions?
947 /* Edit area - minus decorations (text drawable area) */
948 combobox_info.textarea_drawable = combobox_info.textarea;
949 combobox_info.textarea_drawable.Y += ThemeEngine.Current.DrawComboBoxEditDecorationTop ();
950 combobox_info.textarea_drawable.X += ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
951 combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationBottom ();
952 combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationTop();
953 combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationRight ();
954 combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
956 /* Non-drawable area */
957 Region area = new Region (ClientRectangle);
958 area.Exclude (combobox_info.textarea);
959 RectangleF bounds = area.GetBounds (DeviceContext);
960 combobox_info.listbox_area = new Rectangle ((int)bounds.X, (int)bounds.Y,
961 (int)bounds.Width, (int)bounds.Height);
963 if (CBoxInfo.show_button) {
964 combobox_info.textarea_drawable.Width -= def_button_width;
966 combobox_info.button_rect = new Rectangle (combobox_info.textarea_drawable.X + combobox_info.textarea_drawable.Width,
967 combobox_info.textarea_drawable.Y, def_button_width, combobox_info.textarea_drawable.Height);
971 if (dropdown_style != ComboBoxStyle.DropDownList) { /* There is an edit control*/
972 if (textbox_ctrl != null) {
973 textbox_ctrl.Location = new Point (combobox_info.textarea_drawable.X, combobox_info.textarea_drawable.Y);
974 textbox_ctrl.Size = new Size (combobox_info.textarea_drawable.Width, combobox_info.textarea_drawable.Height);
978 if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
979 listbox_ctrl.Location = new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
980 combobox_info.textarea.Height);
981 listbox_ctrl.CalcListBoxArea ();
987 private void CreateComboListBox ()
989 listbox_ctrl = new ComboListBox (this);
992 internal void Draw (Rectangle clip, Graphics dc)
994 // No edit control, we paint the edit ourselfs
995 if (dropdown_style == ComboBoxStyle.DropDownList) {
996 DrawItemState state = DrawItemState.None;
997 Rectangle item_rect = combobox_info.textarea_drawable;
998 item_rect.Height = ItemHeight + 2;
1000 if (has_focus == true) {
1001 state = DrawItemState.Selected;
1002 state |= DrawItemState.Focus;
1005 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect,
1006 selected_index, state, ForeColor, BackColor));
1009 if (clip.IntersectsWith (combobox_info.listbox_area) == true) {
1010 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
1011 combobox_info.listbox_area);
1014 if (CBoxInfo.show_button) {
1015 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorButtonFace),
1016 combobox_info.button_rect);
1018 ThemeEngine.Current.CPDrawComboButton (dc,
1019 combobox_info.button_rect, combobox_info.button_status);
1022 ThemeEngine.Current.DrawComboBoxEditDecorations (dc, this, combobox_info.textarea);
1025 internal void DropDownListBox ()
1027 if (DropDownStyle == ComboBoxStyle.Simple)
1030 if (listbox_ctrl == null) {
1031 CreateComboListBox ();
1034 listbox_ctrl.Location = PointToScreen (new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
1035 combobox_info.textarea.Height));
1037 if (listbox_ctrl.ShowWindow () == true) {
1038 CBoxInfo.droppeddown = true;
1041 combobox_info.button_status = ButtonState.Pushed;
1042 if (dropdown_style == ComboBoxStyle.DropDownList) {
1043 Invalidate (combobox_info.textarea_drawable);
1047 internal void DropDownListBoxFinished ()
1049 if (DropDownStyle == ComboBoxStyle.Simple)
1052 combobox_info.button_status = ButtonState.Normal;
1053 Invalidate (combobox_info.button_rect);
1054 CBoxInfo.droppeddown = false;
1058 private int FindStringCaseInsensitive (string search)
1060 for (int i = 0; i < Items.Count; i++)
1062 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1069 internal virtual void OnMouseDownCB (object sender, MouseEventArgs e)
1071 /* Click On button*/
1074 if (dropdown_style == ComboBoxStyle.DropDownList) {
1075 hit_rect = combobox_info.textarea;
1077 hit_rect = combobox_info.button_rect;
1080 if (hit_rect.Contains (e.X, e.Y)) {
1081 if (clicked == false) {
1085 listbox_ctrl.Hide ();
1086 DropDownListBoxFinished ();
1089 Invalidate (combobox_info.button_rect);
1093 internal virtual void OnMouseMoveCB (object sender, MouseEventArgs e)
1095 /* When there are no items, act as a regular button */
1096 if (clicked == true && Items.Count == 0 &&
1097 combobox_info.button_rect.Contains (e.X, e.Y) == false) {
1098 DropDownListBoxFinished ();
1102 internal virtual void OnMouseUpCB (object sender, MouseEventArgs e)
1104 /* Click on button*/
1105 if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) {
1106 DropDownListBoxFinished ();
1110 private void OnPaintCB (PaintEventArgs pevent)
1112 if (Width <= 0 || Height <= 0 || Visible == false || suspend_ctrlupdate == true)
1115 /* Copies memory drawing buffer to screen*/
1116 Draw (ClientRectangle, pevent.Graphics);
1119 Paint (this, pevent);
1122 private void OnTextChangedEdit (object sender, EventArgs e)
1124 if (process_textchanged_event == false)
1127 int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1132 listbox_ctrl.SetTopItem (item);
1133 listbox_ctrl.SetHighLightedItem (Items[item]);
1136 internal void SetControlText (string s)
1138 process_textchanged_event = false;
1139 textbox_ctrl.Text = s;
1140 process_textchanged_event = true;
1143 private void UpdatedItems ()
1145 if (dropdown_style != ComboBoxStyle.Simple)
1148 listbox_ctrl.UpdateLastVisibleItem ();
1149 listbox_ctrl.CalcListBoxArea ();
1150 listbox_ctrl.Refresh ();
1153 #endregion Private Methods
1157 ComboBox.ObjectCollection
1159 [ListBindableAttribute (false)]
1160 public class ObjectCollection : IList, ICollection, IEnumerable
1163 private ComboBox owner;
1164 internal ArrayList object_items = new ArrayList ();
1165 internal ArrayList combobox_items = new ArrayList ();
1167 public ObjectCollection (ComboBox owner)
1172 #region Public Properties
1173 public virtual int Count {
1174 get { return object_items.Count; }
1177 public virtual bool IsReadOnly {
1178 get { return false; }
1182 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1183 public virtual object this [int index] {
1185 if (index < 0 || index >= Count)
1186 throw new ArgumentOutOfRangeException ("Index of out range");
1188 return object_items[index];
1191 if (index < 0 || index >= Count)
1192 throw new ArgumentOutOfRangeException ("Index of out range");
1194 object_items[index] = value;
1198 bool ICollection.IsSynchronized {
1199 get { return false; }
1202 object ICollection.SyncRoot {
1203 get { return this; }
1206 bool IList.IsFixedSize {
1207 get { return false; }
1210 #endregion Public Properties
1212 #region Private Properties
1213 internal ArrayList ObjectItems {
1214 get { return object_items;}
1216 object_items = value;
1220 internal ArrayList ListBoxItems {
1221 get { return combobox_items;}
1223 combobox_items = value;
1226 #endregion Private Properties
1228 #region Public Methods
1229 public int Add (object item)
1233 idx = AddItem (item);
1234 owner.UpdatedItems ();
1238 public void AddRange (object[] items)
1240 foreach (object mi in items)
1243 owner.UpdatedItems ();
1246 public virtual void Clear ()
1248 owner.selected_index = -1;
1249 object_items.Clear ();
1250 combobox_items.Clear ();
1251 owner.UpdatedItems ();
1255 public virtual bool Contains (object obj)
1257 return object_items.Contains (obj);
1260 public void CopyTo (object[] dest, int arrayIndex)
1262 object_items.CopyTo (dest, arrayIndex);
1265 void ICollection.CopyTo (Array dest, int index)
1267 object_items.CopyTo (dest, index);
1270 public virtual IEnumerator GetEnumerator ()
1272 return object_items.GetEnumerator ();
1275 int IList.Add (object item)
1280 public virtual int IndexOf (object value)
1282 return object_items.IndexOf (value);
1285 public virtual void Insert (int index, object item)
1287 if (index < 0 || index > Count)
1288 throw new ArgumentOutOfRangeException ("Index of out range");
1290 ObjectCollection new_items = new ObjectCollection (owner);
1291 object sel_item = owner.SelectedItem;
1293 owner.BeginUpdate ();
1295 for (int i = 0; i < index; i++) {
1296 new_items.AddItem (ObjectItems[i]);
1299 new_items.AddItem (item);
1301 for (int i = index; i < Count; i++){
1302 new_items.AddItem (ObjectItems[i]);
1305 ObjectItems = new_items.ObjectItems;
1306 ListBoxItems = new_items.ListBoxItems;
1308 if (sel_item != null) {
1309 int idx = IndexOf (sel_item);
1310 owner.selected_index = idx;
1311 owner.listbox_ctrl.SetHighLightedItem (owner.Items[idx]);
1314 owner.EndUpdate (); // Calls UpdatedItems
1317 public virtual void Remove (object value)
1319 if (IndexOf (value) == owner.SelectedIndex)
1320 owner.SelectedItem = null;
1322 RemoveAt (IndexOf (value));
1326 public virtual void RemoveAt (int index)
1328 if (index < 0 || index >= Count)
1329 throw new ArgumentOutOfRangeException ("Index of out range");
1331 if (index == owner.SelectedIndex)
1332 owner.SelectedItem = null;
1334 object_items.RemoveAt (index);
1335 combobox_items.RemoveAt (index);
1336 owner.UpdatedItems ();
1338 #endregion Public Methods
1340 #region Private Methods
1341 private int AddItem (object item)
1343 int cnt = object_items.Count;
1344 object_items.Add (item);
1345 combobox_items.Add (new ComboBox.ComboBoxItem (cnt));
1349 internal void AddRange (IList items)
1351 foreach (object mi in items)
1354 owner.UpdatedItems ();
1357 internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
1359 if (index < 0 || index >= Count)
1360 throw new ArgumentOutOfRangeException ("Index of out range");
1362 return (ComboBox.ComboBoxItem) combobox_items[index];
1365 internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
1367 if (index < 0 || index >= Count)
1368 throw new ArgumentOutOfRangeException ("Index of out range");
1370 combobox_items[index] = item;
1373 #endregion Private Methods
1379 internal class ComboListBox : Control
1381 private ComboBox owner;
1382 private VScrollBarLB vscrollbar_ctrl;
1383 private int top_item; /* First item that we show the in the current page */
1384 private int last_item; /* Last visible item */
1385 public object highlighted_item; /* Item that is currently selected */
1386 internal int page_size; /* Number of listbox items per page */
1387 private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
1389 internal enum ItemNavigation
1399 class VScrollBarLB : VScrollBar
1401 public VScrollBarLB ()
1405 public void FireMouseDown (MouseEventArgs e)
1410 public void FireMouseUp (MouseEventArgs e)
1415 public void FireMouseMove (MouseEventArgs e)
1422 public ComboListBox (ComboBox owner) : base ()
1428 highlighted_item = null;
1430 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1431 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1432 MouseMove += new MouseEventHandler (OnMouseMovePUW);
1433 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1434 Paint += new PaintEventHandler (OnPaintPUW);
1435 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1436 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1439 protected override CreateParams CreateParams
1442 CreateParams cp = base.CreateParams;
1443 if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) {
1444 cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
1445 cp.ExStyle |= (int)(WindowStyles.WS_EX_TOOLWINDOW | WindowStyles.WS_EX_TOPMOST);
1451 #region Private Methods
1452 // Calcs the listbox area
1453 internal void CalcListBoxArea ()
1456 int item_height = owner.ItemHeight;
1457 bool show_scrollbar = false;
1459 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1460 width = owner.CBoxInfo.listbox_area.Width;
1461 height = owner.CBoxInfo.listbox_area.Height;
1463 if (owner.IntegralHeight == true) {
1464 int remaining = (height -
1465 ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1466 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)) %
1469 if (remaining > 0) {
1470 height -= remaining;
1474 else { // DropDown or DropDownList
1476 width = owner.DropDownWidth;
1477 int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
1479 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1481 for (int i = 0; i < count; i++) {
1482 height += owner.GetItemHeight (i);
1486 height = (item_height - 2) * count;
1490 height += ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);
1491 height += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1494 if (owner.Items.Count <= owner.MaxDropDownItems) {
1496 /* Does not need vertical scrollbar*/
1497 if (vscrollbar_ctrl != null) {
1498 vscrollbar_ctrl.Visible = false;
1502 /* Need vertical scrollbar */
1503 if (vscrollbar_ctrl == null) {
1504 vscrollbar_ctrl = new VScrollBarLB ();
1505 vscrollbar_ctrl.Minimum = 0;
1506 vscrollbar_ctrl.SmallChange = 1;
1507 vscrollbar_ctrl.LargeChange = 1;
1508 vscrollbar_ctrl.Maximum = 0;
1509 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1511 Controls.Add (vscrollbar_ctrl);
1514 vscrollbar_ctrl.Height = height - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1515 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1517 vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle),
1518 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle));
1520 vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems;
1521 show_scrollbar = vscrollbar_ctrl.Visible = true;
1525 Size = new Size (width, height);
1526 textarea_drawable = ClientRectangle;
1527 textarea_drawable.Width = width;
1528 textarea_drawable.Height = height;
1530 // Exclude decorations
1531 textarea_drawable.X += ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1532 textarea_drawable.Y += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1533 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1534 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1535 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);
1536 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1538 if (vscrollbar_ctrl != null && show_scrollbar)
1539 textarea_drawable.Width -= vscrollbar_ctrl.Width;
1541 last_item = LastVisibleItem ();
1542 page_size = textarea_drawable.Height / (item_height - 2);
1545 private void Draw (Rectangle clip, Graphics dc)
1547 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
1548 (owner.BackColor), clip);
1550 if (owner.Items.Count > 0) {
1551 Rectangle item_rect;
1552 DrawItemState state = DrawItemState.None;
1554 for (int i = top_item; i <= last_item; i++) {
1555 item_rect = GetItemDisplayRectangle (i, top_item);
1557 if (clip.IntersectsWith (item_rect) == false)
1561 state = DrawItemState.None;
1563 if (i == GetHighLightedIndex () ) {
1564 state |= DrawItemState.Selected;
1566 if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1567 state |= DrawItemState.Focus;
1571 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1572 i, state, owner.ForeColor, owner.BackColor));
1576 ThemeEngine.Current.DrawComboListBoxDecorations (dc, owner, ClientRectangle);
1579 public int GetHighLightedIndex ()
1581 return owner.Items.IndexOf (highlighted_item);
1584 public object GetHighLightedItem ()
1586 return highlighted_item;
1589 private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
1591 if (index < 0 || index >= owner.Items.Count)
1592 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1594 Rectangle item_rect = new Rectangle ();
1595 int height = owner.GetItemHeight (index);
1597 item_rect.X = ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1598 item_rect.Width = textarea_drawable.Width;
1599 item_rect.Y = 2 + ((height - 2) * (index - first_displayble));
1600 item_rect.Height = height;
1604 public void HideWindow ()
1606 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1611 highlighted_item = -1;
1612 owner.DropDownListBoxFinished ();
1615 private int IndexFromPointDisplayRectangle (int x, int y)
1617 for (int i = top_item; i <= last_item; i++) {
1618 if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1625 protected override bool IsInputKey (Keys keyData)
1627 return owner.IsInputKey (keyData);
1630 private int LastVisibleItem ()
1632 Rectangle item_rect;
1633 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1636 for (i = top_item; i < owner.Items.Count; i++) {
1637 item_rect = GetItemDisplayRectangle (i, top_item);
1638 if (item_rect.Y + item_rect.Height > top_y) {
1645 private void NavigateItemVisually (ItemNavigation navigation)
1649 switch (navigation) {
1650 case ItemNavigation.Next: {
1651 if (GetHighLightedIndex () + 1 < owner.Items.Count) {
1653 if (GetHighLightedIndex () + 1 > last_item) {
1655 vscrollbar_ctrl.Value = top_item;
1657 item = GetHighLightedIndex () + 1;
1662 case ItemNavigation.Previous: {
1663 if (GetHighLightedIndex () > 0) {
1665 if (GetHighLightedIndex () - 1 < top_item) {
1667 vscrollbar_ctrl.Value = top_item;
1669 item = GetHighLightedIndex () - 1;
1674 case ItemNavigation.NextPage: {
1675 if (GetHighLightedIndex () + page_size - 1 >= owner.Items.Count) {
1676 top_item = owner.Items.Count - page_size;
1677 vscrollbar_ctrl.Value = top_item;
1678 item = owner.Items.Count - 1;
1681 if (GetHighLightedIndex () + page_size - 1 > last_item) {
1682 top_item = GetHighLightedIndex ();
1683 vscrollbar_ctrl.Value = GetHighLightedIndex ();
1686 item = GetHighLightedIndex () + page_size - 1;
1691 case ItemNavigation.PreviousPage: {
1693 /* Go to the first item*/
1694 if (GetHighLightedIndex () - (page_size - 1) <= 0) {
1697 vscrollbar_ctrl.Value = top_item;
1700 else { /* One page back */
1701 if (GetHighLightedIndex () - (page_size - 1) < top_item) {
1702 top_item = GetHighLightedIndex () - (page_size - 1);
1703 vscrollbar_ctrl.Value = top_item;
1706 item = GetHighLightedIndex () - (page_size - 1);
1717 SetHighLightedItem (owner.Items[item]);
1719 owner.OnSelectionChangeCommitted (new EventArgs ());
1721 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1722 owner.SetControlText (owner.GetItemText (owner.Items[item]));
1727 private void OnKeyDownPUW (object sender, KeyEventArgs e)
1729 switch (e.KeyCode) {
1731 NavigateItemVisually (ItemNavigation.Previous);
1735 NavigateItemVisually (ItemNavigation.Next);
1739 NavigateItemVisually (ItemNavigation.PreviousPage);
1743 NavigateItemVisually (ItemNavigation.NextPage);
1751 public void SetHighLightedItem (object item)
1753 Rectangle invalidate;
1755 if (GetHighLightedItem () == item)
1759 if (GetHighLightedIndex () != -1) {
1760 invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item);
1761 if (ClientRectangle.Contains (invalidate))
1762 Invalidate (invalidate);
1765 highlighted_item = item;
1767 if (highlighted_item != null) {
1769 invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item);
1770 if (ClientRectangle.Contains (invalidate))
1771 Invalidate (invalidate);
1776 public void SetTopItem (int item)
1779 UpdateLastVisibleItem ();
1783 private void OnMouseDownPUW (object sender, MouseEventArgs e)
1785 Rectangle scrollbar_screenrect;
1786 Point mouse_screen, scrollbar_screen;
1787 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1789 /* Click on an element ? */
1790 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1792 owner.SelectedIndex = index;
1793 SetHighLightedItem (owner.Items[index]);
1794 owner.OnSelectionChangeCommitted (new EventArgs ());
1799 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1802 /* Reroute event to scrollbar */
1803 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1804 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1805 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1806 scrollbar_screenrect.X = scrollbar_screen.X;
1807 scrollbar_screenrect.Y = scrollbar_screen.Y;
1809 if (scrollbar_screenrect.Contains (mouse_screen)){
1810 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1811 vscrollbar_ctrl.FireMouseDown (new MouseEventArgs (e.Button, e.Clicks,
1812 pnt_client.X, pnt_client.Y, e.Delta));
1813 } else { /* Click in a non-client area*/
1816 } else { /* Click in a non-client area*/
1821 private void OnMouseMovePUW (object sender, MouseEventArgs e)
1823 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1826 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1829 SetHighLightedItem (owner.Items[index]);
1833 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1836 /* Reroute event to scrollbar */
1837 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1838 Rectangle scrollbar_screenrect;
1839 Point mouse_screen, scrollbar_screen;
1840 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1842 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1843 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1844 scrollbar_screenrect.X = scrollbar_screen.X;
1845 scrollbar_screenrect.Y = scrollbar_screen.Y;
1847 if (scrollbar_screenrect.Contains (mouse_screen)){
1848 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1850 vscrollbar_ctrl.FireMouseMove (new MouseEventArgs (e.Button, e.Clicks,
1851 pnt_client.X, pnt_client.Y, e.Delta));
1856 private void OnMouseUpPUW (object sender, MouseEventArgs e)
1858 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1861 /* Reroute event to scrollbar */
1862 Rectangle scrollbar_screenrect;
1863 Point mouse_screen, scrollbar_screen;
1864 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1866 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1867 scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1868 scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1869 scrollbar_screenrect.X = scrollbar_screen.X;
1870 scrollbar_screenrect.Y = scrollbar_screen.Y;
1872 if (scrollbar_screenrect.Contains (mouse_screen)){
1873 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1875 vscrollbar_ctrl.FireMouseUp (new MouseEventArgs (e.Button, e.Clicks,
1876 pnt_client.X, pnt_client.Y, e.Delta));
1881 private void OnPaintPUW (Object o, PaintEventArgs pevent)
1883 Draw (pevent.ClipRectangle,pevent.Graphics);
1886 public bool ShowWindow ()
1888 if (owner.DropDownStyle != ComboBoxStyle.Simple && owner.Items.Count == 0)
1892 SetHighLightedItem (owner.SelectedItem);
1897 if (owner.DropDownStyle != ComboBoxStyle.Simple) {
1903 if (owner.DropDown != null) {
1904 owner.DropDown (owner, EventArgs.Empty);
1910 public void UpdateLastVisibleItem ()
1912 last_item = LastVisibleItem ();
1916 private void VerticalScrollEvent (object sender, EventArgs e)
1918 top_item = vscrollbar_ctrl.Value;
1919 UpdateLastVisibleItem ();
1923 #endregion Private Methods